]> git.openstreetmap.org Git - nominatim.git/commitdiff
remove PHP frontend
authorSarah Hoffmann <lonvia@denofr.de>
Sun, 15 Sep 2024 09:22:13 +0000 (11:22 +0200)
committerSarah Hoffmann <lonvia@denofr.de>
Sun, 15 Sep 2024 09:22:13 +0000 (11:22 +0200)
59 files changed:
CMakeLists.txt
cmake/paths-py.tmpl [deleted file]
lib-php/AddressDetails.php [deleted file]
lib-php/ClassTypes.php [deleted file]
lib-php/DB.php [deleted file]
lib-php/DatabaseError.php [deleted file]
lib-php/DebugHtml.php [deleted file]
lib-php/DebugNone.php [deleted file]
lib-php/Geocode.php [deleted file]
lib-php/ParameterParser.php [deleted file]
lib-php/Phrase.php [deleted file]
lib-php/PlaceLookup.php [deleted file]
lib-php/Result.php [deleted file]
lib-php/ReverseGeocode.php [deleted file]
lib-php/SearchContext.php [deleted file]
lib-php/SearchDescription.php [deleted file]
lib-php/SearchPosition.php [deleted file]
lib-php/Shell.php [deleted file]
lib-php/SimpleWordList.php [deleted file]
lib-php/SpecialSearchOperator.php [deleted file]
lib-php/Status.php [deleted file]
lib-php/TokenCountry.php [deleted file]
lib-php/TokenHousenumber.php [deleted file]
lib-php/TokenList.php [deleted file]
lib-php/TokenPartial.php [deleted file]
lib-php/TokenPostcode.php [deleted file]
lib-php/TokenSpecialTerm.php [deleted file]
lib-php/TokenWord.php [deleted file]
lib-php/cmd.php [deleted file]
lib-php/dotenv_loader.php [deleted file]
lib-php/init-cmd.php [deleted file]
lib-php/init-website.php [deleted file]
lib-php/init.php [deleted file]
lib-php/lib.php [deleted file]
lib-php/log.php [deleted file]
lib-php/output.php [deleted file]
lib-php/setup_functions.php [deleted file]
lib-php/template/address-geocodejson.php [deleted file]
lib-php/template/address-geojson.php [deleted file]
lib-php/template/address-json.php [deleted file]
lib-php/template/address-xml.php [deleted file]
lib-php/template/details-json.php [deleted file]
lib-php/template/error-json.php [deleted file]
lib-php/template/error-xml.php [deleted file]
lib-php/template/search-batch-json.php [deleted file]
lib-php/template/search-geocodejson.php [deleted file]
lib-php/template/search-geojson.php [deleted file]
lib-php/template/search-json.php [deleted file]
lib-php/template/search-xml.php [deleted file]
lib-php/tokenizer/icu_tokenizer.php [deleted file]
lib-php/tokenizer/legacy_tokenizer.php [deleted file]
lib-php/website/deletable.php [deleted file]
lib-php/website/details.php [deleted file]
lib-php/website/lookup.php [deleted file]
lib-php/website/polygons.php [deleted file]
lib-php/website/reverse-only-search.php [deleted file]
lib-php/website/reverse.php [deleted file]
lib-php/website/search.php [deleted file]
lib-php/website/status.php [deleted file]

index 19bf6655c3cd5b2f6132bc77ccc1d8df19ce2235..11f7f9297ccbb4b51fbce3cca4f2bf448f88ca13 100644 (file)
@@ -74,25 +74,6 @@ if (BUILD_IMPORTER OR BUILD_API)
     find_package(PythonInterp 3.7 REQUIRED)
 endif()
 
-#-----------------------------------------------------------------------------
-# PHP
-#-----------------------------------------------------------------------------
-
-# Setting PHP binary variable as to command line (prevailing) or auto detect
-
-if (BUILD_API)
-    if (NOT PHP_BIN)
-         find_program (PHP_BIN php)
-    endif()
-    # sanity check if PHP binary exists
-    if (NOT EXISTS ${PHP_BIN})
-        message(WARNING "PHP binary not found. Only Python frontend can be used.")
-        set(PHP_BIN "")
-    else()
-        message (STATUS "Using PHP binary " ${PHP_BIN})
-    endif()
-endif()
-
 #-----------------------------------------------------------------------------
 # import scripts and utilities (importer only)
 #-----------------------------------------------------------------------------
@@ -125,8 +106,6 @@ if (BUILD_TESTS)
     find_program(PYTHON_BEHAVE behave)
     find_program(PYLINT NAMES pylint3 pylint)
     find_program(PYTEST NAMES pytest py.test-3 py.test)
-    find_program(PHPCS phpcs)
-    find_program(PHPUNIT phpunit)
 
     if (PYTHON_BEHAVE)
         message(STATUS "Using Python behave binary ${PYTHON_BEHAVE}")
@@ -141,24 +120,6 @@ if (BUILD_TESTS)
         message(WARNING "behave not found. BDD tests disabled." )
     endif()
 
-    if (PHPUNIT)
-        message(STATUS "Using phpunit binary ${PHPUNIT}")
-        add_test(NAME php
-                 COMMAND ${PHPUNIT} ./
-                 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/test/php)
-    else()
-        message(WARNING "phpunit not found. PHP unit tests disabled." )
-    endif()
-
-    if (PHPCS)
-        message(STATUS "Using phpcs binary ${PHPCS}")
-        add_test(NAME phpcs
-                 COMMAND ${PHPCS} --report-width=120 --colors lib-php
-                 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
-    else()
-        message(WARNING "phpcs not found. PHP linting tests disabled." )
-    endif()
-
     if (PYLINT)
         message(STATUS "Using pylint binary ${PYLINT}")
         add_test(NAME pylint
@@ -203,11 +164,7 @@ if (BUILD_IMPORTER)
             DESTINATION ${CMAKE_INSTALL_BINDIR}
             RENAME nominatim)
 
-    if (EXISTS ${PHP_BIN})
-        configure_file(${PROJECT_SOURCE_DIR}/cmake/paths-py.tmpl paths-py.installed)
-    else()
-        configure_file(${PROJECT_SOURCE_DIR}/cmake/paths-py-no-php.tmpl paths-py.installed)
-    endif()
+    configure_file(${PROJECT_SOURCE_DIR}/cmake/paths-py-no-php.tmpl paths-py.installed)
 
     foreach (submodule nominatim_db nominatim_api)
         install(DIRECTORY src/${submodule}
@@ -243,10 +200,6 @@ if (BUILD_MODULE)
             DESTINATION ${NOMINATIM_LIBDIR}/module)
 endif()
 
-if (BUILD_API AND EXISTS ${PHP_BIN})
-    install(DIRECTORY lib-php DESTINATION ${NOMINATIM_LIBDIR})
-endif()
-
 install(FILES settings/env.defaults
               settings/address-levels.json
               settings/phrase-settings.json
diff --git a/cmake/paths-py.tmpl b/cmake/paths-py.tmpl
deleted file mode 100644 (file)
index 372a454..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# This file is part of Nominatim. (https://nominatim.org)
-#
-# Copyright (C) 2022 by the Nominatim developer community.
-# For a full list of authors see the git log.
-"""
-Path settings for extra data used by Nominatim (installed version).
-"""
-from pathlib import Path
-
-PHPLIB_DIR = (Path('@NOMINATIM_LIBDIR@') / 'lib-php').resolve()
-SQLLIB_DIR = (Path('@NOMINATIM_LIBDIR@') / 'lib-sql').resolve()
-DATA_DIR = Path('@NOMINATIM_DATADIR@').resolve()
-CONFIG_DIR = Path('@NOMINATIM_CONFIGDIR@').resolve()
diff --git a/lib-php/AddressDetails.php b/lib-php/AddressDetails.php
deleted file mode 100644 (file)
index cfdd041..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim;
-
-require_once(CONST_LibDir.'/ClassTypes.php');
-
-/**
- * Detailed list of address parts for a single result
- */
-class AddressDetails
-{
-    private $iPlaceID;
-    private $aAddressLines;
-
-    public function __construct(&$oDB, $iPlaceID, $sHousenumber, $mLangPref)
-    {
-        $this->iPlaceID = $iPlaceID;
-
-        if (is_array($mLangPref)) {
-            $mLangPref = $oDB->getArraySQL($oDB->getDBQuotedList($mLangPref));
-        }
-
-        if (!isset($sHousenumber)) {
-            $sHousenumber = -1;
-        }
-
-        $sSQL = 'SELECT *,';
-        $sSQL .= ' get_name_by_language(name,'.$mLangPref.') as localname';
-        $sSQL .= ' FROM get_addressdata('.$iPlaceID.','.$sHousenumber.')';
-        $sSQL .= ' ORDER BY rank_address DESC, isaddress DESC';
-
-        $this->aAddressLines = $oDB->getAll($sSQL);
-    }
-
-    private static function isAddress($aLine)
-    {
-        return $aLine['isaddress'] || $aLine['type'] == 'country_code';
-    }
-
-    public function getAddressDetails($bAll = false)
-    {
-        if ($bAll) {
-            return $this->aAddressLines;
-        }
-
-        return array_filter($this->aAddressLines, array(__CLASS__, 'isAddress'));
-    }
-
-    public function getLocaleAddress()
-    {
-        $aParts = array();
-        $sPrevResult = '';
-
-        foreach ($this->aAddressLines as $aLine) {
-            if ($aLine['isaddress'] && $sPrevResult != $aLine['localname']) {
-                $sPrevResult = $aLine['localname'];
-                $aParts[] = $sPrevResult;
-            }
-        }
-
-        return join(', ', $aParts);
-    }
-
-    public function getAddressNames()
-    {
-        $aAddress = array();
-
-        foreach ($this->aAddressLines as $aLine) {
-            if (!self::isAddress($aLine)) {
-                continue;
-            }
-
-            $sTypeLabel = ClassTypes\getLabelTag($aLine);
-
-            $sName = null;
-            if (isset($aLine['localname']) && $aLine['localname']!=='') {
-                $sName = $aLine['localname'];
-            } elseif (isset($aLine['housenumber']) && $aLine['housenumber']!=='') {
-                $sName = $aLine['housenumber'];
-            }
-
-            if (isset($sName)
-                && (!isset($aAddress[$sTypeLabel])
-                    || $aLine['class'] == 'place')
-            ) {
-                $aAddress[$sTypeLabel] = $sName;
-
-                if (!empty($aLine['name'])) {
-                    $this->addSubdivisionCode($aAddress, $aLine['admin_level'], $aLine['name']);
-                }
-            }
-        }
-
-        return $aAddress;
-    }
-
-    /**
-     * Annotates the given json with geocodejson address information fields.
-     *
-     * @param array  $aJson  Json hash to add the fields to.
-     *
-     * Geocodejson has the following fields:
-     *  street, locality, postcode, city, district,
-     *  county, state, country
-     *
-     * Postcode and housenumber are added by type, district is not used.
-     * All other fields are set according to address rank.
-     */
-    public function addGeocodeJsonAddressParts(&$aJson)
-    {
-        foreach (array_reverse($this->aAddressLines) as $aLine) {
-            if (!$aLine['isaddress']) {
-                continue;
-            }
-
-            if (!isset($aLine['localname']) || $aLine['localname'] == '') {
-                continue;
-            }
-
-            if ($aLine['type'] == 'postcode' || $aLine['type'] == 'postal_code') {
-                $aJson['postcode'] = $aLine['localname'];
-                continue;
-            }
-
-            if ($aLine['type'] == 'house_number') {
-                $aJson['housenumber'] = $aLine['localname'];
-                continue;
-            }
-
-            if ($this->iPlaceID == $aLine['place_id']) {
-                continue;
-            }
-
-            $iRank = (int)$aLine['rank_address'];
-
-            if ($iRank > 25 && $iRank < 28) {
-                $aJson['street'] = $aLine['localname'];
-            } elseif ($iRank >= 22 && $iRank <= 25) {
-                $aJson['locality'] = $aLine['localname'];
-            } elseif ($iRank >= 17 && $iRank <= 21) {
-                $aJson['district'] = $aLine['localname'];
-            } elseif ($iRank >= 13 && $iRank <= 16) {
-                $aJson['city'] = $aLine['localname'];
-            } elseif ($iRank >= 10 && $iRank <= 12) {
-                $aJson['county'] = $aLine['localname'];
-            } elseif ($iRank >= 5 && $iRank <= 9) {
-                $aJson['state'] = $aLine['localname'];
-            } elseif ($iRank == 4) {
-                $aJson['country'] = $aLine['localname'];
-            }
-        }
-    }
-
-    public function getAdminLevels()
-    {
-        $aAddress = array();
-        foreach (array_reverse($this->aAddressLines) as $aLine) {
-            if (self::isAddress($aLine)
-                && isset($aLine['admin_level'])
-                && $aLine['admin_level'] < 15
-                && !isset($aAddress['level'.$aLine['admin_level']])
-            ) {
-                $aAddress['level'.$aLine['admin_level']] = $aLine['localname'];
-            }
-        }
-        return $aAddress;
-    }
-
-    public function debugInfo()
-    {
-        return $this->aAddressLines;
-    }
-
-    private function addSubdivisionCode(&$aAddress, $iAdminLevel, $nameDetails)
-    {
-        if (is_string($nameDetails)) {
-            $nameDetails = json_decode('{' . str_replace('"=>"', '":"', $nameDetails) . '}', true);
-        }
-        if (!empty($nameDetails['ISO3166-2'])) {
-            $aAddress["ISO3166-2-lvl$iAdminLevel"] = $nameDetails['ISO3166-2'];
-        }
-    }
-}
diff --git a/lib-php/ClassTypes.php b/lib-php/ClassTypes.php
deleted file mode 100644 (file)
index 0561f48..0000000
+++ /dev/null
@@ -1,576 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim\ClassTypes;
-
-/**
- * Create a label tag for the given place that can be used as an XML name.
- *
- * @param array[] $aPlace  Information about the place to label.
- *
- * A label tag groups various object types together under a common
- * label. The returned value is lower case and has no spaces
- */
-function getLabelTag($aPlace, $sCountry = null)
-{
-    $iRank = (int) ($aPlace['rank_address'] ?? 30);
-    $sLabel;
-    if (isset($aPlace['place_type'])) {
-        $sLabel = $aPlace['place_type'];
-    } elseif ($aPlace['class'] == 'boundary' && $aPlace['type'] == 'administrative') {
-        $sLabel = getBoundaryLabel($iRank/2, $sCountry);
-    } elseif ($aPlace['type'] == 'postal_code') {
-        $sLabel = 'postcode';
-    } elseif ($iRank < 26) {
-        $sLabel = $aPlace['type'];
-    } elseif ($iRank < 28) {
-        $sLabel = 'road';
-    } elseif ($aPlace['class'] == 'place'
-            && ($aPlace['type'] == 'house_number' ||
-                $aPlace['type'] == 'house_name' ||
-                $aPlace['type'] == 'country_code')
-    ) {
-        $sLabel = $aPlace['type'];
-    } else {
-        $sLabel = $aPlace['class'];
-    }
-
-    return strtolower(str_replace(' ', '_', $sLabel));
-}
-
-/**
- * Create a label for the given place.
- *
- * @param array[] $aPlace  Information about the place to label.
- */
-function getLabel($aPlace, $sCountry = null)
-{
-    if (isset($aPlace['place_type'])) {
-        return ucwords(str_replace('_', ' ', $aPlace['place_type']));
-    }
-
-    if ($aPlace['class'] == 'boundary' && $aPlace['type'] == 'administrative') {
-        return getBoundaryLabel(($aPlace['rank_address'] ?? 30)/2, $sCountry ?? null);
-    }
-
-    // Return a label only for 'important' class/type combinations
-    if (getImportance($aPlace) !== null) {
-        return ucwords(str_replace('_', ' ', $aPlace['type']));
-    }
-
-    return null;
-}
-
-
-/**
- * Return a simple label for an administrative boundary for the given country.
- *
- * @param int $iAdminLevel   Content of admin_level tag.
- * @param string $sCountry   Country code of the country where the object is
- *                           in. May be null, in which case a world-wide
- *                           fallback is used.
- * @param string $sFallback  String to return if no explicit string is listed.
- *
- * @return string
- */
-function getBoundaryLabel($iAdminLevel, $sCountry, $sFallback = 'Administrative')
-{
-    static $aBoundaryList = array (
-                             'default' => array (
-                                           1 => 'Continent',
-                                           2 => 'Country',
-                                           3 => 'Region',
-                                           4 => 'State',
-                                           5 => 'State District',
-                                           6 => 'County',
-                                           7 => 'Municipality',
-                                           8 => 'City',
-                                           9 => 'City District',
-                                           10 => 'Suburb',
-                                           11 => 'Neighbourhood',
-                                           12 => 'City Block'
-                                          ),
-                             'no' => array (
-                                      3 => 'State',
-                                      4 => 'County'
-                                     ),
-                             'se' => array (
-                                      3 => 'State',
-                                      4 => 'County'
-                                     )
-            );
-
-    if (isset($aBoundaryList[$sCountry])
-        && isset($aBoundaryList[$sCountry][$iAdminLevel])
-    ) {
-        return $aBoundaryList[$sCountry][$iAdminLevel];
-    }
-
-    return $aBoundaryList['default'][$iAdminLevel] ?? $sFallback;
-}
-
-/**
- * Return an estimated radius of how far the object node extends.
- *
- * @param array[] $aPlace  Information about the place. This must be a node
- *                         feature.
- *
- * @return float  The radius around the feature in degrees.
- */
-function getDefRadius($aPlace)
-{
-    $aSpecialRadius = array(
-                       'place:continent' => 25,
-                       'place:country' => 7,
-                       'place:state' => 2.6,
-                       'place:province' => 2.6,
-                       'place:region' => 1.0,
-                       'place:county' => 0.7,
-                       'place:city' => 0.16,
-                       'place:municipality' => 0.16,
-                       'place:island' => 0.32,
-                       'place:postcode' => 0.16,
-                       'place:town' => 0.04,
-                       'place:village' => 0.02,
-                       'place:hamlet' => 0.02,
-                       'place:district' => 0.02,
-                       'place:borough' => 0.02,
-                       'place:suburb' => 0.02,
-                       'place:locality' => 0.01,
-                       'place:neighbourhood'=> 0.01,
-                       'place:quarter' => 0.01,
-                       'place:city_block' => 0.01,
-                       'landuse:farm' => 0.01,
-                       'place:farm' => 0.01,
-                       'place:airport' => 0.015,
-                       'aeroway:aerodrome' => 0.015,
-                       'railway:station' => 0.005
-           );
-
-    $sClassPlace = $aPlace['class'].':'.$aPlace['type'];
-
-    return $aSpecialRadius[$sClassPlace] ?? 0.00005;
-}
-
-/**
- * Get the icon to use with the given object.
- */
-function getIcon($aPlace)
-{
-    $aIcons = array(
-               'boundary:administrative' => 'poi_boundary_administrative',
-               'place:city' => 'poi_place_city',
-               'place:town' => 'poi_place_town',
-               'place:village' => 'poi_place_village',
-               'place:hamlet' => 'poi_place_village',
-               'place:suburb' => 'poi_place_village',
-               'place:locality' => 'poi_place_village',
-               'place:airport' => 'transport_airport2',
-               'aeroway:aerodrome' => 'transport_airport2',
-               'railway:station' => 'transport_train_station2',
-               'amenity:place_of_worship' => 'place_of_worship_unknown3',
-               'amenity:pub' => 'food_pub',
-               'amenity:bar' => 'food_bar',
-               'amenity:university' => 'education_university',
-               'tourism:museum' => 'tourist_museum',
-               'amenity:arts_centre' => 'tourist_art_gallery2',
-               'tourism:zoo' => 'tourist_zoo',
-               'tourism:theme_park' => 'poi_point_of_interest',
-               'tourism:attraction' => 'poi_point_of_interest',
-               'leisure:golf_course' => 'sport_golf',
-               'historic:castle' => 'tourist_castle',
-               'amenity:hospital' => 'health_hospital',
-               'amenity:school' => 'education_school',
-               'amenity:theatre' => 'tourist_theatre',
-               'amenity:library' => 'amenity_library',
-               'amenity:fire_station' => 'amenity_firestation3',
-               'amenity:police' => 'amenity_police2',
-               'amenity:bank' => 'money_bank2',
-               'amenity:post_office' => 'amenity_post_office',
-               'tourism:hotel' => 'accommodation_hotel2',
-               'amenity:cinema' => 'tourist_cinema',
-               'tourism:artwork' => 'tourist_art_gallery2',
-               'historic:archaeological_site' => 'tourist_archaeological2',
-               'amenity:doctors' => 'health_doctors',
-               'leisure:sports_centre' => 'sport_leisure_centre',
-               'leisure:swimming_pool' => 'sport_swimming_outdoor',
-               'shop:supermarket' => 'shopping_supermarket',
-               'shop:convenience' => 'shopping_convenience',
-               'amenity:restaurant' => 'food_restaurant',
-               'amenity:fast_food' => 'food_fastfood',
-               'amenity:cafe' => 'food_cafe',
-               'tourism:guest_house' => 'accommodation_bed_and_breakfast',
-               'amenity:pharmacy' => 'health_pharmacy_dispensing',
-               'amenity:fuel' => 'transport_fuel',
-               'natural:peak' => 'poi_peak',
-               'natural:wood' => 'landuse_coniferous_and_deciduous',
-               'shop:bicycle' => 'shopping_bicycle',
-               'shop:clothes' => 'shopping_clothes',
-               'shop:hairdresser' => 'shopping_hairdresser',
-               'shop:doityourself' => 'shopping_diy',
-               'shop:estate_agent' => 'shopping_estateagent2',
-               'shop:car' => 'shopping_car',
-               'shop:garden_centre' => 'shopping_garden_centre',
-               'shop:car_repair' => 'shopping_car_repair',
-               'shop:bakery' => 'shopping_bakery',
-               'shop:butcher' => 'shopping_butcher',
-               'shop:apparel' => 'shopping_clothes',
-               'shop:laundry' => 'shopping_laundrette',
-               'shop:beverages' => 'shopping_alcohol',
-               'shop:alcohol' => 'shopping_alcohol',
-               'shop:optician' => 'health_opticians',
-               'shop:chemist' => 'health_pharmacy',
-               'shop:gallery' => 'tourist_art_gallery2',
-               'shop:jewelry' => 'shopping_jewelry',
-               'tourism:information' => 'amenity_information',
-               'historic:ruins' => 'tourist_ruin',
-               'amenity:college' => 'education_school',
-               'historic:monument' => 'tourist_monument',
-               'historic:memorial' => 'tourist_monument',
-               'historic:mine' => 'poi_mine',
-               'tourism:caravan_site' => 'accommodation_caravan_park',
-               'amenity:bus_station' => 'transport_bus_station',
-               'amenity:atm' => 'money_atm2',
-               'tourism:viewpoint' => 'tourist_view_point',
-               'tourism:guesthouse' => 'accommodation_bed_and_breakfast',
-               'railway:tram' => 'transport_tram_stop',
-               'amenity:courthouse' => 'amenity_court',
-               'amenity:recycling' => 'amenity_recycling',
-               'amenity:dentist' => 'health_dentist',
-               'natural:beach' => 'tourist_beach',
-               'railway:tram_stop' => 'transport_tram_stop',
-               'amenity:prison' => 'amenity_prison',
-               'highway:bus_stop' => 'transport_bus_stop2'
-    );
-
-    $sClassPlace = $aPlace['class'].':'.$aPlace['type'];
-
-    return $aIcons[$sClassPlace] ?? null;
-}
-
-/**
- * Get an icon for the given object with its full URL.
- */
-function getIconFile($aPlace)
-{
-    if (CONST_MapIcon_URL === false) {
-        return null;
-    }
-
-    $sIcon = getIcon($aPlace);
-
-    if (!isset($sIcon)) {
-        return null;
-    }
-
-    return CONST_MapIcon_URL.'/'.$sIcon.'.p.20.png';
-}
-
-/**
- * Return a class importance value for the given place.
- *
- * @param array[] $aPlace  Information about the place.
- *
- * @return int  An importance value. The lower the value, the more
- *              important the class.
- */
-function getImportance($aPlace)
-{
-    static $aWithImportance = null;
-
-    if ($aWithImportance === null) {
-        $aWithImportance = array_flip(array(
-                                           'boundary:administrative',
-                                           'place:country',
-                                           'place:state',
-                                           'place:province',
-                                           'place:county',
-                                           'place:city',
-                                           'place:region',
-                                           'place:island',
-                                           'place:town',
-                                           'place:village',
-                                           'place:hamlet',
-                                           'place:suburb',
-                                           'place:locality',
-                                           'landuse:farm',
-                                           'place:farm',
-                                           'highway:motorway_junction',
-                                           'highway:motorway',
-                                           'highway:trunk',
-                                           'highway:primary',
-                                           'highway:secondary',
-                                           'highway:tertiary',
-                                           'highway:residential',
-                                           'highway:unclassified',
-                                           'highway:living_street',
-                                           'highway:service',
-                                           'highway:track',
-                                           'highway:road',
-                                           'highway:byway',
-                                           'highway:bridleway',
-                                           'highway:cycleway',
-                                           'highway:pedestrian',
-                                           'highway:footway',
-                                           'highway:steps',
-                                           'highway:motorway_link',
-                                           'highway:trunk_link',
-                                           'highway:primary_link',
-                                           'landuse:industrial',
-                                           'landuse:residential',
-                                           'landuse:retail',
-                                           'landuse:commercial',
-                                           'place:airport',
-                                           'aeroway:aerodrome',
-                                           'railway:station',
-                                           'amenity:place_of_worship',
-                                           'amenity:pub',
-                                           'amenity:bar',
-                                           'amenity:university',
-                                           'tourism:museum',
-                                           'amenity:arts_centre',
-                                           'tourism:zoo',
-                                           'tourism:theme_park',
-                                           'tourism:attraction',
-                                           'leisure:golf_course',
-                                           'historic:castle',
-                                           'amenity:hospital',
-                                           'amenity:school',
-                                           'amenity:theatre',
-                                           'amenity:public_building',
-                                           'amenity:library',
-                                           'amenity:townhall',
-                                           'amenity:community_centre',
-                                           'amenity:fire_station',
-                                           'amenity:police',
-                                           'amenity:bank',
-                                           'amenity:post_office',
-                                           'leisure:park',
-                                           'amenity:park',
-                                           'landuse:park',
-                                           'landuse:recreation_ground',
-                                           'tourism:hotel',
-                                           'tourism:motel',
-                                           'amenity:cinema',
-                                           'tourism:artwork',
-                                           'historic:archaeological_site',
-                                           'amenity:doctors',
-                                           'leisure:sports_centre',
-                                           'leisure:swimming_pool',
-                                           'shop:supermarket',
-                                           'shop:convenience',
-                                           'amenity:restaurant',
-                                           'amenity:fast_food',
-                                           'amenity:cafe',
-                                           'tourism:guest_house',
-                                           'amenity:pharmacy',
-                                           'amenity:fuel',
-                                           'natural:peak',
-                                           'waterway:waterfall',
-                                           'natural:wood',
-                                           'natural:water',
-                                           'landuse:forest',
-                                           'landuse:cemetery',
-                                           'landuse:allotments',
-                                           'landuse:farmyard',
-                                           'railway:rail',
-                                           'waterway:canal',
-                                           'waterway:river',
-                                           'waterway:stream',
-                                           'shop:bicycle',
-                                           'shop:clothes',
-                                           'shop:hairdresser',
-                                           'shop:doityourself',
-                                           'shop:estate_agent',
-                                           'shop:car',
-                                           'shop:garden_centre',
-                                           'shop:car_repair',
-                                           'shop:newsagent',
-                                           'shop:bakery',
-                                           'shop:furniture',
-                                           'shop:butcher',
-                                           'shop:apparel',
-                                           'shop:electronics',
-                                           'shop:department_store',
-                                           'shop:books',
-                                           'shop:yes',
-                                           'shop:outdoor',
-                                           'shop:mall',
-                                           'shop:florist',
-                                           'shop:charity',
-                                           'shop:hardware',
-                                           'shop:laundry',
-                                           'shop:shoes',
-                                           'shop:beverages',
-                                           'shop:dry_cleaning',
-                                           'shop:carpet',
-                                           'shop:computer',
-                                           'shop:alcohol',
-                                           'shop:optician',
-                                           'shop:chemist',
-                                           'shop:gallery',
-                                           'shop:mobile_phone',
-                                           'shop:sports',
-                                           'shop:jewelry',
-                                           'shop:pet',
-                                           'shop:beauty',
-                                           'shop:stationery',
-                                           'shop:shopping_centre',
-                                           'shop:general',
-                                           'shop:electrical',
-                                           'shop:toys',
-                                           'shop:jeweller',
-                                           'shop:betting',
-                                           'shop:household',
-                                           'shop:travel_agency',
-                                           'shop:hifi',
-                                           'amenity:shop',
-                                           'tourism:information',
-                                           'place:house',
-                                           'place:house_name',
-                                           'place:house_number',
-                                           'place:country_code',
-                                           'leisure:pitch',
-                                           'highway:unsurfaced',
-                                           'historic:ruins',
-                                           'amenity:college',
-                                           'historic:monument',
-                                           'railway:subway',
-                                           'historic:memorial',
-                                           'leisure:nature_reserve',
-                                           'leisure:common',
-                                           'waterway:lock_gate',
-                                           'natural:fell',
-                                           'amenity:nightclub',
-                                           'highway:path',
-                                           'leisure:garden',
-                                           'landuse:reservoir',
-                                           'leisure:playground',
-                                           'leisure:stadium',
-                                           'historic:mine',
-                                           'natural:cliff',
-                                           'tourism:caravan_site',
-                                           'amenity:bus_station',
-                                           'amenity:kindergarten',
-                                           'highway:construction',
-                                           'amenity:atm',
-                                           'amenity:emergency_phone',
-                                           'waterway:lock',
-                                           'waterway:riverbank',
-                                           'natural:coastline',
-                                           'tourism:viewpoint',
-                                           'tourism:hostel',
-                                           'tourism:bed_and_breakfast',
-                                           'railway:halt',
-                                           'railway:platform',
-                                           'railway:tram',
-                                           'amenity:courthouse',
-                                           'amenity:recycling',
-                                           'amenity:dentist',
-                                           'natural:beach',
-                                           'place:moor',
-                                           'amenity:grave_yard',
-                                           'waterway:drain',
-                                           'landuse:grass',
-                                           'landuse:village_green',
-                                           'natural:bay',
-                                           'railway:tram_stop',
-                                           'leisure:marina',
-                                           'highway:stile',
-                                           'natural:moor',
-                                           'railway:light_rail',
-                                           'railway:narrow_gauge',
-                                           'natural:land',
-                                           'amenity:village_hall',
-                                           'waterway:dock',
-                                           'amenity:veterinary',
-                                           'landuse:brownfield',
-                                           'leisure:track',
-                                           'railway:historic_station',
-                                           'landuse:construction',
-                                           'amenity:prison',
-                                           'landuse:quarry',
-                                           'amenity:telephone',
-                                           'highway:traffic_signals',
-                                           'natural:heath',
-                                           'historic:house',
-                                           'amenity:social_club',
-                                           'landuse:military',
-                                           'amenity:health_centre',
-                                           'historic:building',
-                                           'amenity:clinic',
-                                           'highway:services',
-                                           'amenity:ferry_terminal',
-                                           'natural:marsh',
-                                           'natural:hill',
-                                           'highway:raceway',
-                                           'amenity:taxi',
-                                           'amenity:take_away',
-                                           'amenity:car_rental',
-                                           'place:islet',
-                                           'amenity:nursery',
-                                           'amenity:nursing_home',
-                                           'amenity:toilets',
-                                           'amenity:hall',
-                                           'waterway:boatyard',
-                                           'highway:mini_roundabout',
-                                           'historic:manor',
-                                           'tourism:chalet',
-                                           'amenity:bicycle_parking',
-                                           'amenity:hotel',
-                                           'waterway:weir',
-                                           'natural:wetland',
-                                           'natural:cave_entrance',
-                                           'amenity:crematorium',
-                                           'tourism:picnic_site',
-                                           'landuse:wood',
-                                           'landuse:basin',
-                                           'natural:tree',
-                                           'leisure:slipway',
-                                           'landuse:meadow',
-                                           'landuse:piste',
-                                           'amenity:care_home',
-                                           'amenity:club',
-                                           'amenity:medical_centre',
-                                           'historic:roman_road',
-                                           'historic:fort',
-                                           'railway:subway_entrance',
-                                           'historic:yes',
-                                           'highway:gate',
-                                           'leisure:fishing',
-                                           'historic:museum',
-                                           'amenity:car_wash',
-                                           'railway:level_crossing',
-                                           'leisure:bird_hide',
-                                           'natural:headland',
-                                           'tourism:apartments',
-                                           'amenity:shopping',
-                                           'natural:scrub',
-                                           'natural:fen',
-                                           'building:yes',
-                                           'mountain_pass:yes',
-                                           'amenity:parking',
-                                           'highway:bus_stop',
-                                           'place:postcode',
-                                           'amenity:post_box',
-                                           'place:houses',
-                                           'railway:preserved',
-                                           'waterway:derelict_canal',
-                                           'amenity:dead_pub',
-                                           'railway:disused_station',
-                                           'railway:abandoned',
-                                           'railway:disused'
-                ));
-    }
-
-    $sClassPlace = $aPlace['class'].':'.$aPlace['type'];
-
-    return $aWithImportance[$sClassPlace] ?? null;
-}
diff --git a/lib-php/DB.php b/lib-php/DB.php
deleted file mode 100644 (file)
index 553d945..0000000
+++ /dev/null
@@ -1,362 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim;
-
-require_once(CONST_LibDir.'/DatabaseError.php');
-
-/**
- * Uses PDO to access the database specified in the CONST_Database_DSN
- * setting.
- */
-class DB
-{
-    protected $connection;
-
-    public function __construct($sDSN = null)
-    {
-        $this->sDSN = $sDSN ?? getSetting('DATABASE_DSN');
-    }
-
-    public function connect($bNew = false, $bPersistent = true)
-    {
-        if (isset($this->connection) && !$bNew) {
-            return true;
-        }
-        $aConnOptions = array(
-                         \PDO::ATTR_ERRMODE            => \PDO::ERRMODE_EXCEPTION,
-                         \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
-                         \PDO::ATTR_PERSISTENT         => $bPersistent
-        );
-
-        // https://secure.php.net/manual/en/ref.pdo-pgsql.connection.php
-        try {
-            $this->connection = new \PDO($this->sDSN, null, null, $aConnOptions);
-        } catch (\PDOException $e) {
-            $sMsg = 'Failed to establish database connection:' . $e->getMessage();
-            throw new \Nominatim\DatabaseError($sMsg, 500, null, $e->getMessage());
-        }
-
-        $this->connection->exec("SET DateStyle TO 'sql,european'");
-        $this->connection->exec("SET client_encoding TO 'utf-8'");
-        // Disable JIT and parallel workers. They interfere badly with search SQL.
-        $this->connection->exec('SET max_parallel_workers_per_gather TO 0');
-        if ($this->getPostgresVersion() >= 11) {
-            $this->connection->exec('SET jit_above_cost TO -1');
-        }
-        
-        $iMaxExecution = ini_get('max_execution_time');
-        if ($iMaxExecution > 0) {
-            $this->connection->setAttribute(\PDO::ATTR_TIMEOUT, $iMaxExecution); // seconds
-        }
-
-        return true;
-    }
-
-    // returns the number of rows that were modified or deleted by the SQL
-    // statement. If no rows were affected returns 0.
-    public function exec($sSQL, $aInputVars = null, $sErrMessage = 'Database query failed')
-    {
-        $val = null;
-        try {
-            if (isset($aInputVars)) {
-                $stmt = $this->connection->prepare($sSQL);
-                $stmt->execute($aInputVars);
-            } else {
-                $val = $this->connection->exec($sSQL);
-            }
-        } catch (\PDOException $e) {
-            throw new \Nominatim\DatabaseError($sErrMessage, 500, null, $e, $sSQL);
-        }
-        return $val;
-    }
-
-    /**
-     * Executes query. Returns first row as array.
-     * Returns false if no result found.
-     *
-     * @param string  $sSQL
-     *
-     * @return array[]
-     */
-    public function getRow($sSQL, $aInputVars = null, $sErrMessage = 'Database query failed')
-    {
-        try {
-            $stmt = $this->getQueryStatement($sSQL, $aInputVars, $sErrMessage);
-            $row = $stmt->fetch();
-        } catch (\PDOException $e) {
-            throw new \Nominatim\DatabaseError($sErrMessage, 500, null, $e, $sSQL);
-        }
-        return $row;
-    }
-
-    /**
-     * Executes query. Returns first value of first result.
-     * Returns false if no results found.
-     *
-     * @param string  $sSQL
-     *
-     * @return array[]
-     */
-    public function getOne($sSQL, $aInputVars = null, $sErrMessage = 'Database query failed')
-    {
-        try {
-            $stmt = $this->getQueryStatement($sSQL, $aInputVars, $sErrMessage);
-            $row = $stmt->fetch(\PDO::FETCH_NUM);
-            if ($row === false) {
-                return false;
-            }
-        } catch (\PDOException $e) {
-            throw new \Nominatim\DatabaseError($sErrMessage, 500, null, $e, $sSQL);
-        }
-        return $row[0];
-    }
-
-    /**
-     * Executes query. Returns array of results (arrays).
-     * Returns empty array if no results found.
-     *
-     * @param string  $sSQL
-     *
-     * @return array[]
-     */
-    public function getAll($sSQL, $aInputVars = null, $sErrMessage = 'Database query failed')
-    {
-        try {
-            $stmt = $this->getQueryStatement($sSQL, $aInputVars, $sErrMessage);
-            $rows = $stmt->fetchAll();
-        } catch (\PDOException $e) {
-            throw new \Nominatim\DatabaseError($sErrMessage, 500, null, $e, $sSQL);
-        }
-        return $rows;
-    }
-
-    /**
-     * Executes query. Returns array of the first value of each result.
-     * Returns empty array if no results found.
-     *
-     * @param string  $sSQL
-     *
-     * @return array[]
-     */
-    public function getCol($sSQL, $aInputVars = null, $sErrMessage = 'Database query failed')
-    {
-        $aVals = array();
-        try {
-            $stmt = $this->getQueryStatement($sSQL, $aInputVars, $sErrMessage);
-
-            while (($val = $stmt->fetchColumn(0)) !== false) { // returns first column or false
-                $aVals[] = $val;
-            }
-        } catch (\PDOException $e) {
-            throw new \Nominatim\DatabaseError($sErrMessage, 500, null, $e, $sSQL);
-        }
-        return $aVals;
-    }
-
-    /**
-     * Executes query. Returns associate array mapping first value to second value of each result.
-     * Returns empty array if no results found.
-     *
-     * @param string  $sSQL
-     *
-     * @return array[]
-     */
-    public function getAssoc($sSQL, $aInputVars = null, $sErrMessage = 'Database query failed')
-    {
-        try {
-            $stmt = $this->getQueryStatement($sSQL, $aInputVars, $sErrMessage);
-
-            $aList = array();
-            while ($aRow = $stmt->fetch(\PDO::FETCH_NUM)) {
-                $aList[$aRow[0]] = $aRow[1];
-            }
-        } catch (\PDOException $e) {
-            throw new \Nominatim\DatabaseError($sErrMessage, 500, null, $e, $sSQL);
-        }
-        return $aList;
-    }
-
-    /**
-     * Executes query. Returns a PDO statement to iterate over.
-     *
-     * @param string  $sSQL
-     *
-     * @return PDOStatement
-     */
-    public function getQueryStatement($sSQL, $aInputVars = null, $sErrMessage = 'Database query failed')
-    {
-        try {
-            if (isset($aInputVars)) {
-                $stmt = $this->connection->prepare($sSQL);
-                $stmt->execute($aInputVars);
-            } else {
-                $stmt = $this->connection->query($sSQL);
-            }
-        } catch (\PDOException $e) {
-            throw new \Nominatim\DatabaseError($sErrMessage, 500, null, $e, $sSQL);
-        }
-        return $stmt;
-    }
-
-    /**
-     * St. John's Way => 'St. John\'s Way'
-     *
-     * @param string  $sVal  Text to be quoted.
-     *
-     * @return string
-     */
-    public function getDBQuoted($sVal)
-    {
-        return $this->connection->quote($sVal);
-    }
-
-    /**
-     * Like getDBQuoted, but takes an array.
-     *
-     * @param array  $aVals  List of text to be quoted.
-     *
-     * @return array[]
-     */
-    public function getDBQuotedList($aVals)
-    {
-        return array_map(function ($sVal) {
-            return $this->getDBQuoted($sVal);
-        }, $aVals);
-    }
-
-    /**
-     * [1,2,'b'] => 'ARRAY[1,2,'b']''
-     *
-     * @param array  $aVals  List of text to be quoted.
-     *
-     * @return string
-     */
-    public function getArraySQL($a)
-    {
-        return 'ARRAY['.join(',', $a).']';
-    }
-
-    /**
-     * Check if a table exists in the database. Returns true if it does.
-     *
-     * @param string  $sTableName
-     *
-     * @return boolean
-     */
-    public function tableExists($sTableName)
-    {
-        $sSQL = 'SELECT count(*) FROM pg_tables WHERE tablename = :tablename';
-        return ($this->getOne($sSQL, array(':tablename' => $sTableName)) == 1);
-    }
-
-    /**
-     * Deletes a table. Returns true if deleted or didn't exist.
-     *
-     * @param string  $sTableName
-     *
-     * @return boolean
-     */
-    public function deleteTable($sTableName)
-    {
-        return $this->exec('DROP TABLE IF EXISTS '.$sTableName.' CASCADE') == 0;
-    }
-
-    /**
-     * Tries to connect to the database but on failure doesn't throw an exception.
-     *
-     * @return boolean
-     */
-    public function checkConnection()
-    {
-        $bExists = true;
-        try {
-            $this->connect(true);
-        } catch (\Nominatim\DatabaseError $e) {
-            $bExists = false;
-        }
-        return $bExists;
-    }
-
-    /**
-     * e.g. 9.6, 10, 11.2
-     *
-     * @return float
-     */
-    public function getPostgresVersion()
-    {
-        $sVersionString = $this->getOne('SHOW server_version_num');
-        preg_match('#([0-9]?[0-9])([0-9][0-9])[0-9][0-9]#', $sVersionString, $aMatches);
-        return (float) ($aMatches[1].'.'.$aMatches[2]);
-    }
-
-    /**
-     * e.g. 2, 2.2
-     *
-     * @return float
-     */
-    public function getPostgisVersion()
-    {
-        $sVersionString = $this->getOne('select postgis_lib_version()');
-        preg_match('#^([0-9]+)[.]([0-9]+)[.]#', $sVersionString, $aMatches);
-        return (float) ($aMatches[1].'.'.$aMatches[2]);
-    }
-
-    /**
-     * Returns an associate array of postgresql database connection settings. Keys can
-     * be 'database', 'hostspec', 'port', 'username', 'password'.
-     * Returns empty array on failure, thus check if at least 'database' is set.
-     *
-     * @return array[]
-     */
-    public static function parseDSN($sDSN)
-    {
-        // https://secure.php.net/manual/en/ref.pdo-pgsql.connection.php
-        $aInfo = array();
-        if (preg_match('/^pgsql:(.+)$/', $sDSN, $aMatches)) {
-            foreach (explode(';', $aMatches[1]) as $sKeyVal) {
-                list($sKey, $sVal) = explode('=', $sKeyVal, 2);
-                if ($sKey == 'host') {
-                    $sKey = 'hostspec';
-                } elseif ($sKey == 'dbname') {
-                    $sKey = 'database';
-                } elseif ($sKey == 'user') {
-                    $sKey = 'username';
-                }
-                $aInfo[$sKey] = $sVal;
-            }
-        }
-        return $aInfo;
-    }
-
-    /**
-     * Takes an array of settings and return the DNS string. Key names can be
-     * 'database', 'hostspec', 'port', 'username', 'password' but aliases
-     * 'dbname', 'host' and 'user' are also supported.
-     *
-     * @return string
-     *
-     */
-    public static function generateDSN($aInfo)
-    {
-        $sDSN = sprintf(
-            'pgsql:host=%s;port=%s;dbname=%s;user=%s;password=%s;',
-            $aInfo['host'] ?? $aInfo['hostspec'] ?? '',
-            $aInfo['port'] ?? '',
-            $aInfo['dbname'] ?? $aInfo['database'] ?? '',
-            $aInfo['user'] ?? '',
-            $aInfo['password'] ?? ''
-        );
-        $sDSN = preg_replace('/\b\w+=;/', '', $sDSN);
-        $sDSN = preg_replace('/;\Z/', '', $sDSN);
-
-        return $sDSN;
-    }
-}
diff --git a/lib-php/DatabaseError.php b/lib-php/DatabaseError.php
deleted file mode 100644 (file)
index 68f1efe..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim;
-
-class DatabaseError extends \Exception
-{
-
-    public function __construct($message, $code, $previous, $oPDOErr, $sSql = null)
-    {
-        parent::__construct($message, $code, $previous);
-        // https://secure.php.net/manual/en/class.pdoexception.php
-        $this->oPDOErr = $oPDOErr;
-        $this->sSql = $sSql;
-    }
-
-    public function __toString()
-    {
-        return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
-    }
-
-    public function getSqlError()
-    {
-        return $this->oPDOErr->getMessage();
-    }
-
-    public function getSqlDebugDump()
-    {
-        if (CONST_Debug) {
-            return var_export($this->oPDOErr, true);
-        } else {
-            return $this->sSql;
-        }
-    }
-}
diff --git a/lib-php/DebugHtml.php b/lib-php/DebugHtml.php
deleted file mode 100644 (file)
index 7b0cba2..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim;
-
-class Debug
-{
-    public static function newFunction($sHeading)
-    {
-        echo "<pre><h2>Debug output for $sHeading</h2></pre>\n";
-    }
-
-    public static function newSection($sHeading)
-    {
-        echo "<hr><pre><h3>$sHeading</h3></pre>\n";
-    }
-
-    public static function printVar($sHeading, $mVar)
-    {
-        echo '<pre><b>'.$sHeading. ':</b>  ';
-        Debug::outputVar($mVar, str_repeat(' ', strlen($sHeading) + 3));
-        echo "</pre>\n";
-    }
-
-    public static function fmtArrayVals($aArr)
-    {
-        return array('__debug_format' => 'array_vals', 'data' => $aArr);
-    }
-
-    public static function printDebugArray($sHeading, $oVar)
-    {
-
-        if ($oVar === null) {
-            Debug::printVar($sHeading, 'null');
-        } else {
-            Debug::printVar($sHeading, $oVar->debugInfo());
-        }
-    }
-
-    public static function printDebugTable($sHeading, $aVar)
-    {
-        echo '<b>'.$sHeading.":</b>\n";
-        echo "<table border='1'>\n";
-        if (!empty($aVar)) {
-            echo "  <tr>\n";
-            $aKeys = array();
-            $aInfo = reset($aVar);
-            if (!is_array($aInfo)) {
-                $aInfo = $aInfo->debugInfo();
-            }
-            foreach ($aInfo as $sKey => $mVal) {
-                echo '    <th><small>'.$sKey.'</small></th>'."\n";
-                $aKeys[] = $sKey;
-            }
-            echo "  </tr>\n";
-            foreach ($aVar as $oRow) {
-                $aInfo = $oRow;
-                if (!is_array($oRow)) {
-                    $aInfo = $oRow->debugInfo();
-                }
-                echo "  <tr>\n";
-                foreach ($aKeys as $sKey) {
-                    echo '    <td><pre>';
-                    if (isset($aInfo[$sKey])) {
-                        Debug::outputVar($aInfo[$sKey], '');
-                    }
-                    echo '</pre></td>'."\n";
-                }
-                echo "  </tr>\n";
-            }
-        }
-        echo "</table>\n";
-    }
-
-    public static function printGroupedSearch($aSearches, $aWordsIDs)
-    {
-        echo '<table border="1">';
-        echo '<tr><th>rank</th><th>Name Tokens</th><th>Name Not</th>';
-        echo '<th>Address Tokens</th><th>Address Not</th>';
-        echo '<th>country</th><th>operator</th>';
-        echo '<th>class</th><th>type</th><th>postcode</th><th>housenumber</th></tr>';
-        foreach ($aSearches as $aRankedSet) {
-            foreach ($aRankedSet as $aRow) {
-                $aRow->dumpAsHtmlTableRow($aWordsIDs);
-            }
-        }
-        echo '</table>';
-    }
-
-    public static function printGroupTable($sHeading, $aVar)
-    {
-        echo '<b>'.$sHeading.":</b>\n";
-        echo "<table border='1'>\n";
-        if (!empty($aVar)) {
-            echo "  <tr>\n";
-            echo '    <th><small>Group</small></th>'."\n";
-            $aKeys = array();
-            $aInfo = reset($aVar)[0];
-            if (!is_array($aInfo)) {
-                $aInfo = $aInfo->debugInfo();
-            }
-            foreach ($aInfo as $sKey => $mVal) {
-                echo '    <th><small>'.$sKey.'</small></th>'."\n";
-                $aKeys[] = $sKey;
-            }
-            echo "  </tr>\n";
-            foreach ($aVar as $sGrpKey => $aGroup) {
-                foreach ($aGroup as $oRow) {
-                    $aInfo = $oRow;
-                    if (!is_array($oRow)) {
-                        $aInfo = $oRow->debugInfo();
-                    }
-                    echo "  <tr>\n";
-                    echo '    <td><pre>'.$sGrpKey.'</pre></td>'."\n";
-                    foreach ($aKeys as $sKey) {
-                        echo '    <td><pre>';
-                        if (!empty($aInfo[$sKey])) {
-                            Debug::outputVar($aInfo[$sKey], '');
-                        }
-                        echo '</pre></td>'."\n";
-                    }
-                    echo "  </tr>\n";
-                }
-            }
-        }
-        echo "</table>\n";
-    }
-
-    public static function printSQL($sSQL)
-    {
-        echo '<p><tt><b>'.date('c').'</b> <font color="#aaa">'.htmlspecialchars($sSQL, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401).'</font></tt></p>'."\n";
-    }
-
-    private static function outputVar($mVar, $sPreNL)
-    {
-        if (is_array($mVar) && !isset($mVar['__debug_format'])) {
-            $sPre = '';
-            foreach ($mVar as $mKey => $aValue) {
-                echo $sPre;
-                $iKeyLen = Debug::outputSimpleVar($mKey);
-                echo ' => ';
-                Debug::outputVar(
-                    $aValue,
-                    $sPreNL.str_repeat(' ', $iKeyLen + 4)
-                );
-                $sPre = "\n".$sPreNL;
-            }
-        } elseif (is_array($mVar) && isset($mVar['__debug_format'])) {
-            if (!empty($mVar['data'])) {
-                $sPre = '';
-                foreach ($mVar['data'] as $mValue) {
-                    echo $sPre;
-                    Debug::outputSimpleVar($mValue);
-                    $sPre = ', ';
-                }
-            }
-        } elseif (is_object($mVar) && method_exists($mVar, 'debugInfo')) {
-            Debug::outputVar($mVar->debugInfo(), $sPreNL);
-        } elseif (is_a($mVar, 'stdClass')) {
-            Debug::outputVar(json_decode(json_encode($mVar), true), $sPreNL);
-        } else {
-            Debug::outputSimpleVar($mVar);
-        }
-    }
-
-    private static function outputSimpleVar($mVar)
-    {
-        if (is_bool($mVar)) {
-            echo '<i>'.($mVar ? 'True' : 'False').'</i>';
-            return $mVar ? 4 : 5;
-        }
-
-        if (is_string($mVar)) {
-            $sOut = "'$mVar'";
-        } else {
-            $sOut = (string)$mVar;
-        }
-
-        echo htmlspecialchars($sOut, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401);
-        return strlen($sOut);
-    }
-}
diff --git a/lib-php/DebugNone.php b/lib-php/DebugNone.php
deleted file mode 100644 (file)
index 818cc08..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim;
-
-class Debug
-{
-    public static function __callStatic($name, $arguments)
-    {
-        // nothing
-    }
-}
diff --git a/lib-php/Geocode.php b/lib-php/Geocode.php
deleted file mode 100644 (file)
index 0881d20..0000000
+++ /dev/null
@@ -1,938 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim;
-
-require_once(CONST_LibDir.'/PlaceLookup.php');
-require_once(CONST_LibDir.'/Phrase.php');
-require_once(CONST_LibDir.'/ReverseGeocode.php');
-require_once(CONST_LibDir.'/SearchDescription.php');
-require_once(CONST_LibDir.'/SearchContext.php');
-require_once(CONST_LibDir.'/SearchPosition.php');
-require_once(CONST_LibDir.'/TokenList.php');
-require_once(CONST_TokenizerDir.'/tokenizer.php');
-
-class Geocode
-{
-    protected $oDB;
-
-    protected $oPlaceLookup;
-    protected $oTokenizer;
-
-    protected $aLangPrefOrder = array();
-
-    protected $aExcludePlaceIDs = array();
-
-    protected $iLimit = 20;
-    protected $iFinalLimit = 10;
-    protected $iOffset = 0;
-    protected $bFallback = false;
-
-    protected $aCountryCodes = false;
-
-    protected $bBoundedSearch = false;
-    protected $aViewBox = false;
-    protected $aRoutePoints = false;
-    protected $aRouteWidth = false;
-
-    protected $iMaxRank = 20;
-    protected $iMinAddressRank = 0;
-    protected $iMaxAddressRank = 30;
-    protected $aAddressRankList = array();
-
-    protected $sAllowedTypesSQLList = false;
-
-    protected $sQuery = false;
-    protected $aStructuredQuery = false;
-
-
-    public function __construct(&$oDB)
-    {
-        $this->oDB =& $oDB;
-        $this->oPlaceLookup = new PlaceLookup($this->oDB);
-        $this->oTokenizer = new \Nominatim\Tokenizer($this->oDB);
-    }
-
-    public function setLanguagePreference($aLangPref)
-    {
-        $this->aLangPrefOrder = $aLangPref;
-    }
-
-    public function getMoreUrlParams()
-    {
-        if ($this->aStructuredQuery) {
-            $aParams = $this->aStructuredQuery;
-        } else {
-            $aParams = array('q' => $this->sQuery);
-        }
-
-        $aParams = array_merge($aParams, $this->oPlaceLookup->getMoreUrlParams());
-
-        if ($this->aExcludePlaceIDs) {
-            $aParams['exclude_place_ids'] = implode(',', $this->aExcludePlaceIDs);
-        }
-
-        if ($this->bBoundedSearch) {
-            $aParams['bounded'] = '1';
-        }
-
-        if ($this->aCountryCodes) {
-            $aParams['countrycodes'] = implode(',', $this->aCountryCodes);
-        }
-
-        if ($this->aViewBox) {
-            $aParams['viewbox'] = join(',', $this->aViewBox);
-        }
-
-        return $aParams;
-    }
-
-    public function setLimit($iLimit = 10)
-    {
-        if ($iLimit > 50) {
-            $iLimit = 50;
-        } elseif ($iLimit < 1) {
-            $iLimit = 1;
-        }
-
-        $this->iFinalLimit = $iLimit;
-        $this->iLimit = $iLimit + max($iLimit, 10);
-    }
-
-    public function setFeatureType($sFeatureType)
-    {
-        switch ($sFeatureType) {
-            case 'country':
-                $this->setRankRange(4, 4);
-                break;
-            case 'state':
-                $this->setRankRange(8, 8);
-                break;
-            case 'city':
-                $this->setRankRange(14, 16);
-                break;
-            case 'settlement':
-                $this->setRankRange(8, 20);
-                break;
-        }
-    }
-
-    public function setRankRange($iMin, $iMax)
-    {
-        $this->iMinAddressRank = $iMin;
-        $this->iMaxAddressRank = $iMax;
-    }
-
-    public function setViewbox($aViewbox)
-    {
-        $aBox = array_map('floatval', $aViewbox);
-
-        $this->aViewBox[0] = max(-180.0, min($aBox[0], $aBox[2]));
-        $this->aViewBox[1] = max(-90.0, min($aBox[1], $aBox[3]));
-        $this->aViewBox[2] = min(180.0, max($aBox[0], $aBox[2]));
-        $this->aViewBox[3] = min(90.0, max($aBox[1], $aBox[3]));
-
-        if ($this->aViewBox[2] - $this->aViewBox[0] < 0.000000001
-            || $this->aViewBox[3] - $this->aViewBox[1] < 0.000000001
-        ) {
-            userError("Bad parameter 'viewbox'. Not a box.");
-        }
-    }
-
-    private function viewboxImportanceFactor($fX, $fY)
-    {
-        if (!$this->aViewBox) {
-            return 1;
-        }
-
-        $fWidth = ($this->aViewBox[2] - $this->aViewBox[0])/2;
-        $fHeight = ($this->aViewBox[3] - $this->aViewBox[1])/2;
-
-        $fXDist = abs($fX - ($this->aViewBox[0] + $this->aViewBox[2])/2);
-        $fYDist = abs($fY - ($this->aViewBox[1] + $this->aViewBox[3])/2);
-
-        if ($fXDist <= $fWidth && $fYDist <= $fHeight) {
-            return 1;
-        }
-
-        if ($fXDist <= $fWidth * 3 && $fYDist <= 3 * $fHeight) {
-            return 0.5;
-        }
-
-        return 0.25;
-    }
-
-    public function setQuery($sQueryString)
-    {
-        $this->sQuery = $sQueryString;
-        $this->aStructuredQuery = false;
-    }
-
-    public function getQueryString()
-    {
-        return $this->sQuery;
-    }
-
-
-    public function loadParamArray($oParams, $sForceGeometryType = null)
-    {
-        $this->bBoundedSearch = $oParams->getBool('bounded', $this->bBoundedSearch);
-
-        $this->setLimit($oParams->getInt('limit', $this->iFinalLimit));
-        $this->iOffset = $oParams->getInt('offset', $this->iOffset);
-
-        $this->bFallback = $oParams->getBool('fallback', $this->bFallback);
-
-        // List of excluded Place IDs - used for more accurate pageing
-        $sExcluded = $oParams->getStringList('exclude_place_ids');
-        if ($sExcluded) {
-            foreach ($sExcluded as $iExcludedPlaceID) {
-                $iExcludedPlaceID = (int)$iExcludedPlaceID;
-                if ($iExcludedPlaceID) {
-                    $aExcludePlaceIDs[$iExcludedPlaceID] = $iExcludedPlaceID;
-                }
-            }
-
-            if (isset($aExcludePlaceIDs)) {
-                $this->aExcludePlaceIDs = $aExcludePlaceIDs;
-            }
-        }
-
-        // Only certain ranks of feature
-        $sFeatureType = $oParams->getString('featureType');
-        if (!$sFeatureType) {
-            $sFeatureType = $oParams->getString('featuretype');
-        }
-        if ($sFeatureType) {
-            $this->setFeatureType($sFeatureType);
-        }
-
-        // Country code list
-        $sCountries = $oParams->getStringList('countrycodes');
-        if ($sCountries) {
-            foreach ($sCountries as $sCountryCode) {
-                if (preg_match('/^[a-zA-Z][a-zA-Z]$/', $sCountryCode)) {
-                    $aCountries[] = strtolower($sCountryCode);
-                }
-            }
-            if (isset($aCountries)) {
-                $this->aCountryCodes = $aCountries;
-            }
-        }
-
-        $aViewbox = $oParams->getStringList('viewboxlbrt');
-        if ($aViewbox) {
-            if (count($aViewbox) != 4) {
-                userError("Bad parameter 'viewboxlbrt'. Expected 4 coordinates.");
-            }
-            $this->setViewbox($aViewbox);
-        } else {
-            $aViewbox = $oParams->getStringList('viewbox');
-            if ($aViewbox) {
-                if (count($aViewbox) != 4) {
-                    userError("Bad parameter 'viewbox'. Expected 4 coordinates.");
-                }
-                $this->setViewBox($aViewbox);
-            } else {
-                $aRoute = $oParams->getStringList('route');
-                $fRouteWidth = $oParams->getFloat('routewidth');
-                if ($aRoute && $fRouteWidth) {
-                    $this->aRoutePoints = $aRoute;
-                    $this->aRouteWidth = $fRouteWidth;
-                }
-            }
-        }
-
-        $this->oPlaceLookup->loadParamArray($oParams, $sForceGeometryType);
-        $this->oPlaceLookup->setIncludeAddressDetails($oParams->getBool('addressdetails', false));
-    }
-
-    public function setQueryFromParams($oParams)
-    {
-        // Search query
-        $sQuery = $oParams->getString('q');
-        if (!$sQuery) {
-            $this->setStructuredQuery(
-                $oParams->getString('amenity'),
-                $oParams->getString('street'),
-                $oParams->getString('city'),
-                $oParams->getString('county'),
-                $oParams->getString('state'),
-                $oParams->getString('country'),
-                $oParams->getString('postalcode')
-            );
-        } else {
-            $this->setQuery($sQuery);
-        }
-    }
-
-    public function loadStructuredAddressElement($sValue, $sKey, $iNewMinAddressRank, $iNewMaxAddressRank, $aItemListValues)
-    {
-        $sValue = trim($sValue);
-        if (!$sValue) {
-            return false;
-        }
-        $this->aStructuredQuery[$sKey] = $sValue;
-        if ($this->iMinAddressRank == 0 && $this->iMaxAddressRank == 30) {
-            $this->iMinAddressRank = $iNewMinAddressRank;
-            $this->iMaxAddressRank = $iNewMaxAddressRank;
-        }
-        if ($aItemListValues) {
-            $this->aAddressRankList = array_merge($this->aAddressRankList, $aItemListValues);
-        }
-        return true;
-    }
-
-    public function setStructuredQuery($sAmenity = false, $sStreet = false, $sCity = false, $sCounty = false, $sState = false, $sCountry = false, $sPostalCode = false)
-    {
-        $this->sQuery = false;
-
-        // Reset
-        $this->iMinAddressRank = 0;
-        $this->iMaxAddressRank = 30;
-        $this->aAddressRankList = array();
-
-        $this->aStructuredQuery = array();
-        $this->sAllowedTypesSQLList = false;
-
-        $this->loadStructuredAddressElement($sAmenity, 'amenity', 26, 30, false);
-        $this->loadStructuredAddressElement($sStreet, 'street', 26, 30, false);
-        $this->loadStructuredAddressElement($sCity, 'city', 14, 24, false);
-        $this->loadStructuredAddressElement($sCounty, 'county', 9, 13, false);
-        $this->loadStructuredAddressElement($sState, 'state', 8, 8, false);
-        $this->loadStructuredAddressElement($sPostalCode, 'postalcode', 5, 11, array(5, 11));
-        $this->loadStructuredAddressElement($sCountry, 'country', 4, 4, false);
-
-        if (!empty($this->aStructuredQuery)) {
-            $this->sQuery = join(', ', $this->aStructuredQuery);
-            if ($this->iMaxAddressRank < 30) {
-                $this->sAllowedTypesSQLList = '(\'place\',\'boundary\')';
-            }
-        }
-    }
-
-    public function fallbackStructuredQuery()
-    {
-        $aParams = $this->aStructuredQuery;
-
-        if (!$aParams || count($aParams) == 1) {
-            return false;
-        }
-
-        $aOrderToFallback = array('postalcode', 'street', 'city', 'county', 'state');
-
-        foreach ($aOrderToFallback as $sType) {
-            if (isset($aParams[$sType])) {
-                unset($aParams[$sType]);
-                $this->setStructuredQuery(@$aParams['amenity'], @$aParams['street'], @$aParams['city'], @$aParams['county'], @$aParams['state'], @$aParams['country'], @$aParams['postalcode']);
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    public function getGroupedSearches($aSearches, $aPhrases, $oValidTokens)
-    {
-        /*
-             Calculate all searches using oValidTokens i.e.
-             'Wodsworth Road, Sheffield' =>
-
-             Phrase Wordset
-             0      0       (wodsworth road)
-             0      1       (wodsworth)(road)
-             1      0       (sheffield)
-
-             Score how good the search is so they can be ordered
-         */
-        foreach ($aPhrases as $iPhrase => $oPhrase) {
-            $aNewPhraseSearches = array();
-            $oPosition = new SearchPosition(
-                $oPhrase->getPhraseType(),
-                $iPhrase,
-                count($aPhrases)
-            );
-
-            foreach ($oPhrase->getWordSets() as $aWordset) {
-                $aWordsetSearches = $aSearches;
-
-                // Add all words from this wordset
-                foreach ($aWordset as $iToken => $sToken) {
-                    $aNewWordsetSearches = array();
-                    $oPosition->setTokenPosition($iToken, count($aWordset));
-
-                    foreach ($aWordsetSearches as $oCurrentSearch) {
-                        foreach ($oValidTokens->get($sToken) as $oSearchTerm) {
-                            if ($oSearchTerm->isExtendable($oCurrentSearch, $oPosition)) {
-                                $aNewSearches = $oSearchTerm->extendSearch(
-                                    $oCurrentSearch,
-                                    $oPosition
-                                );
-
-                                foreach ($aNewSearches as $oSearch) {
-                                    if ($oSearch->getRank() < $this->iMaxRank) {
-                                        $aNewWordsetSearches[] = $oSearch;
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    // Sort and cut
-                    usort($aNewWordsetSearches, array('Nominatim\SearchDescription', 'bySearchRank'));
-                    $aWordsetSearches = array_slice($aNewWordsetSearches, 0, 50);
-                }
-
-                $aNewPhraseSearches = array_merge($aNewPhraseSearches, $aNewWordsetSearches);
-                usort($aNewPhraseSearches, array('Nominatim\SearchDescription', 'bySearchRank'));
-
-                $aSearchHash = array();
-                foreach ($aNewPhraseSearches as $iSearch => $aSearch) {
-                    $sHash = serialize($aSearch);
-                    if (isset($aSearchHash[$sHash])) {
-                        unset($aNewPhraseSearches[$iSearch]);
-                    } else {
-                        $aSearchHash[$sHash] = 1;
-                    }
-                }
-
-                $aNewPhraseSearches = array_slice($aNewPhraseSearches, 0, 50);
-            }
-
-            // Re-group the searches by their score, junk anything over 20 as just not worth trying
-            $aGroupedSearches = array();
-            foreach ($aNewPhraseSearches as $aSearch) {
-                $iRank = $aSearch->getRank();
-                if ($iRank < $this->iMaxRank) {
-                    if (!isset($aGroupedSearches[$iRank])) {
-                        $aGroupedSearches[$iRank] = array();
-                    }
-                    $aGroupedSearches[$iRank][] = $aSearch;
-                }
-            }
-            ksort($aGroupedSearches);
-
-            $iSearchCount = 0;
-            $aSearches = array();
-            foreach ($aGroupedSearches as $aNewSearches) {
-                $iSearchCount += count($aNewSearches);
-                $aSearches = array_merge($aSearches, $aNewSearches);
-                if ($iSearchCount > 50) {
-                    break;
-                }
-            }
-        }
-
-        // Revisit searches, drop bad searches and give penalty to unlikely combinations.
-        $aGroupedSearches = array();
-        foreach ($aSearches as $oSearch) {
-            if (!$oSearch->isValidSearch()) {
-                continue;
-            }
-
-            $iRank = $oSearch->getRank();
-            if (!isset($aGroupedSearches[$iRank])) {
-                $aGroupedSearches[$iRank] = array();
-            }
-            $aGroupedSearches[$iRank][] = $oSearch;
-        }
-        ksort($aGroupedSearches);
-
-        return $aGroupedSearches;
-    }
-
-    /* Perform the actual query lookup.
-
-        Returns an ordered list of results, each with the following fields:
-            osm_type: type of corresponding OSM object
-                        N - node
-                        W - way
-                        R - relation
-                        P - postcode (internally computed)
-            osm_id: id of corresponding OSM object
-            class: general object class (corresponds to tag key of primary OSM tag)
-            type: subclass of object (corresponds to tag value of primary OSM tag)
-            admin_level: see https://wiki.openstreetmap.org/wiki/Admin_level
-            rank_search: rank in search hierarchy
-                        (see also https://wiki.openstreetmap.org/wiki/Nominatim/Development_overview#Country_to_street_level)
-            rank_address: rank in address hierarchy (determines orer in address)
-            place_id: internal key (may differ between different instances)
-            country_code: ISO country code
-            langaddress: localized full address
-            placename: localized name of object
-            ref: content of ref tag (if available)
-            lon: longitude
-            lat: latitude
-            importance: importance of place based on Wikipedia link count
-            addressimportance: cumulated importance of address elements
-            extra_place: type of place (for admin boundaries, if there is a place tag)
-            aBoundingBox: bounding Box
-            label: short description of the object class/type (English only)
-            name: full name (currently the same as langaddress)
-            foundorder: secondary ordering for places with same importance
-    */
-
-
-    public function lookup()
-    {
-        Debug::newFunction('Geocode::lookup');
-        if (!$this->sQuery && !$this->aStructuredQuery) {
-            return array();
-        }
-
-        Debug::printDebugArray('Geocode', $this);
-
-        $oCtx = new SearchContext();
-
-        if ($this->aRoutePoints) {
-            $oCtx->setViewboxFromRoute(
-                $this->oDB,
-                $this->aRoutePoints,
-                $this->aRouteWidth,
-                $this->bBoundedSearch
-            );
-        } elseif ($this->aViewBox) {
-            $oCtx->setViewboxFromBox($this->aViewBox, $this->bBoundedSearch);
-        }
-        if ($this->aExcludePlaceIDs) {
-            $oCtx->setExcludeList($this->aExcludePlaceIDs);
-        }
-        if ($this->aCountryCodes) {
-            $oCtx->setCountryList($this->aCountryCodes);
-        }
-
-        Debug::newSection('Query Preprocessing');
-
-        $sQuery = $this->sQuery;
-        if (!preg_match('//u', $sQuery)) {
-            userError('Query string is not UTF-8 encoded.');
-        }
-
-        // Do we have anything that looks like a lat/lon pair?
-        $sQuery = $oCtx->setNearPointFromQuery($sQuery);
-
-        if ($sQuery || $this->aStructuredQuery) {
-            // Start with a single blank search
-            $aSearches = array(new SearchDescription($oCtx));
-
-            if ($sQuery) {
-                $sQuery = $aSearches[0]->extractKeyValuePairs($sQuery);
-            }
-
-            $sSpecialTerm = '';
-            if ($sQuery) {
-                preg_match_all(
-                    '/\\[([\\w ]*)\\]/u',
-                    $sQuery,
-                    $aSpecialTermsRaw,
-                    PREG_SET_ORDER
-                );
-                if (!empty($aSpecialTermsRaw)) {
-                    Debug::printVar('Special terms', $aSpecialTermsRaw);
-                }
-
-                foreach ($aSpecialTermsRaw as $aSpecialTerm) {
-                    $sQuery = str_replace($aSpecialTerm[0], ' ', $sQuery);
-                    if (!$sSpecialTerm) {
-                        $sSpecialTerm = $aSpecialTerm[1];
-                    }
-                }
-            }
-            if (!$sSpecialTerm && $this->aStructuredQuery
-                && isset($this->aStructuredQuery['amenity'])) {
-                $sSpecialTerm = $this->aStructuredQuery['amenity'];
-                unset($this->aStructuredQuery['amenity']);
-            }
-
-            if ($sSpecialTerm && !$aSearches[0]->hasOperator()) {
-                $aTokens = $this->oTokenizer->tokensForSpecialTerm($sSpecialTerm);
-
-                if (!empty($aTokens)) {
-                    $aNewSearches = array();
-                    $oPosition = new SearchPosition('', 0, 1);
-                    $oPosition->setTokenPosition(0, 1);
-
-                    foreach ($aSearches as $oSearch) {
-                        foreach ($aTokens as $oToken) {
-                            $aNewSearches = array_merge(
-                                $aNewSearches,
-                                $oToken->extendSearch($oSearch, $oPosition)
-                            );
-                        }
-                    }
-                    $aSearches = $aNewSearches;
-                }
-            }
-
-            // Split query into phrases
-            // Commas are used to reduce the search space by indicating where phrases split
-            $aPhrases = array();
-            if ($this->aStructuredQuery) {
-                foreach ($this->aStructuredQuery as $iPhrase => $sPhrase) {
-                    $aPhrases[] = new Phrase($sPhrase, $iPhrase);
-                }
-            } else {
-                foreach (explode(',', $sQuery) as $sPhrase) {
-                    $aPhrases[] = new Phrase($sPhrase, '');
-                }
-            }
-
-            Debug::printDebugArray('Search context', $oCtx);
-            Debug::printDebugArray('Base search', empty($aSearches) ? null : $aSearches[0]);
-
-            Debug::newSection('Tokenization');
-            $oValidTokens = $this->oTokenizer->extractTokensFromPhrases($aPhrases);
-
-            if ($oValidTokens->count() > 0) {
-                $oCtx->setFullNameWords($oValidTokens->getFullWordIDs());
-
-                $aPhrases = array_filter($aPhrases, function ($oPhrase) {
-                    return $oPhrase->getWordSets() !== null;
-                });
-
-                // Any words that have failed completely?
-                // TODO: suggestions
-
-                Debug::printGroupTable('Valid Tokens', $oValidTokens->debugInfo());
-                Debug::printDebugTable('Phrases', $aPhrases);
-
-                Debug::newSection('Search candidates');
-
-                $aGroupedSearches = $this->getGroupedSearches($aSearches, $aPhrases, $oValidTokens);
-
-                if (!$this->aStructuredQuery) {
-                    // Reverse phrase array and also reverse the order of the wordsets in
-                    // the first and final phrase. Don't bother about phrases in the middle
-                    // because order in the address doesn't matter.
-                    $aPhrases = array_reverse($aPhrases);
-                    $aPhrases[0]->invertWordSets();
-                    if (count($aPhrases) > 1) {
-                        $aPhrases[count($aPhrases)-1]->invertWordSets();
-                    }
-                    $aReverseGroupedSearches = $this->getGroupedSearches($aSearches, $aPhrases, $oValidTokens);
-
-                    foreach ($aReverseGroupedSearches as $aSearches) {
-                        foreach ($aSearches as $aSearch) {
-                            if (!isset($aGroupedSearches[$aSearch->getRank()])) {
-                                $aGroupedSearches[$aSearch->getRank()] = array();
-                            }
-                            $aGroupedSearches[$aSearch->getRank()][] = $aSearch;
-                        }
-                    }
-
-                    ksort($aGroupedSearches);
-                }
-            } else {
-                // Re-group the searches by their score, junk anything over 20 as just not worth trying
-                $aGroupedSearches = array();
-                foreach ($aSearches as $aSearch) {
-                    if ($aSearch->getRank() < $this->iMaxRank) {
-                        if (!isset($aGroupedSearches[$aSearch->getRank()])) {
-                            $aGroupedSearches[$aSearch->getRank()] = array();
-                        }
-                        $aGroupedSearches[$aSearch->getRank()][] = $aSearch;
-                    }
-                }
-                ksort($aGroupedSearches);
-            }
-
-            // Filter out duplicate searches
-            $aSearchHash = array();
-            foreach ($aGroupedSearches as $iGroup => $aSearches) {
-                foreach ($aSearches as $iSearch => $aSearch) {
-                    $sHash = serialize($aSearch);
-                    if (isset($aSearchHash[$sHash])) {
-                        unset($aGroupedSearches[$iGroup][$iSearch]);
-                        if (empty($aGroupedSearches[$iGroup])) {
-                            unset($aGroupedSearches[$iGroup]);
-                        }
-                    } else {
-                        $aSearchHash[$sHash] = 1;
-                    }
-                }
-            }
-
-            Debug::printGroupedSearch(
-                $aGroupedSearches,
-                $oValidTokens->debugTokenByWordIdList()
-            );
-
-            // Start the search process
-            $iGroupLoop = 0;
-            $iQueryLoop = 0;
-            $aNextResults = array();
-            foreach ($aGroupedSearches as $iGroupedRank => $aSearches) {
-                $iGroupLoop++;
-                $aResults = $aNextResults;
-                foreach ($aSearches as $oSearch) {
-                    $iQueryLoop++;
-
-                    Debug::newSection("Search Loop, group $iGroupLoop, loop $iQueryLoop");
-                    Debug::printGroupedSearch(
-                        array($iGroupedRank => array($oSearch)),
-                        $oValidTokens->debugTokenByWordIdList()
-                    );
-
-                    $aNewResults = $oSearch->query(
-                        $this->oDB,
-                        $this->iMinAddressRank,
-                        $this->iMaxAddressRank,
-                        $this->iLimit
-                    );
-
-                    // The same result may appear in different rounds, only
-                    // use the one with minimal rank.
-                    foreach ($aNewResults as $iPlace => $oRes) {
-                        if (!isset($aResults[$iPlace])
-                            || $aResults[$iPlace]->iResultRank > $oRes->iResultRank) {
-                            $aResults[$iPlace] = $oRes;
-                        }
-                    }
-
-                    if ($iQueryLoop > 20) {
-                        break;
-                    }
-                }
-
-                if (!empty($aResults)) {
-                    $aSplitResults = Result::splitResults($aResults);
-                    Debug::printVar('Split results', $aSplitResults);
-                    if ($iGroupLoop <= 4
-                        && reset($aSplitResults['head'])->iResultRank > 0
-                        && $iGroupedRank !== array_key_last($aGroupedSearches)) {
-                        // Haven't found an exact match for the query yet.
-                        // Therefore add result from the next group level.
-                        $aNextResults = $aSplitResults['head'];
-                        foreach ($aNextResults as $oRes) {
-                            $oRes->iResultRank--;
-                        }
-                        foreach ($aSplitResults['tail'] as $oRes) {
-                            $oRes->iResultRank--;
-                            $aNextResults[$oRes->iId] = $oRes;
-                        }
-                        $aResults = array();
-                    } else {
-                        $aResults = $aSplitResults['head'];
-                    }
-                }
-
-                if (!empty($aResults) && ($this->iMinAddressRank != 0 || $this->iMaxAddressRank != 30)) {
-                    // Need to verify passes rank limits before dropping out of the loop (yuk!)
-                    // reduces the number of place ids, like a filter
-                    // rank_address is 30 for interpolated housenumbers
-                    $aFilterSql = array();
-                    $sPlaceIds = Result::joinIdsByTable($aResults, Result::TABLE_PLACEX);
-                    if ($sPlaceIds) {
-                        $sSQL = 'SELECT place_id FROM placex ';
-                        $sSQL .= 'WHERE place_id in ('.$sPlaceIds.') ';
-                        $sSQL .= '  AND (';
-                        $sSQL .= "         placex.rank_address between $this->iMinAddressRank and $this->iMaxAddressRank ";
-                        $sSQL .= "         OR placex.rank_search between $this->iMinAddressRank and $this->iMaxAddressRank ";
-                        if ($this->aAddressRankList) {
-                            $sSQL .= '     OR placex.rank_address in ('.join(',', $this->aAddressRankList).')';
-                        }
-                        $sSQL .= ')';
-                        $aFilterSql[] = $sSQL;
-                    }
-                    $sPlaceIds = Result::joinIdsByTable($aResults, Result::TABLE_POSTCODE);
-                    if ($sPlaceIds) {
-                        $sSQL = ' SELECT place_id FROM location_postcode lp ';
-                        $sSQL .= 'WHERE place_id in ('.$sPlaceIds.') ';
-                        $sSQL .= "  AND (lp.rank_address between $this->iMinAddressRank and $this->iMaxAddressRank ";
-                        if ($this->aAddressRankList) {
-                            $sSQL .= '     OR lp.rank_address in ('.join(',', $this->aAddressRankList).')';
-                        }
-                        $sSQL .= ') ';
-                        $aFilterSql[] = $sSQL;
-                    }
-
-                    $aFilteredIDs = array();
-                    if ($aFilterSql) {
-                        $sSQL = join(' UNION ', $aFilterSql);
-                        Debug::printSQL($sSQL);
-                        $aFilteredIDs = $this->oDB->getCol($sSQL);
-                    }
-
-                    $tempIDs = array();
-                    foreach ($aResults as $oResult) {
-                        if (($this->iMaxAddressRank == 30 &&
-                             ($oResult->iTable == Result::TABLE_OSMLINE
-                              || $oResult->iTable == Result::TABLE_TIGER))
-                            || in_array($oResult->iId, $aFilteredIDs)
-                        ) {
-                            $tempIDs[$oResult->iId] = $oResult;
-                        }
-                    }
-                    $aResults = $tempIDs;
-                }
-
-                if (!empty($aResults) || $iGroupLoop > 4 || $iQueryLoop > 30) {
-                    break;
-                }
-            }
-        } else {
-            // Just interpret as a reverse geocode
-            $oReverse = new ReverseGeocode($this->oDB);
-            $oReverse->setZoom(18);
-
-            $oLookup = $oReverse->lookupPoint($oCtx->sqlNear, false);
-
-            Debug::printVar('Reverse search', $oLookup);
-
-            if ($oLookup) {
-                $aResults = array($oLookup->iId => $oLookup);
-            }
-        }
-
-        // No results? Done
-        if (empty($aResults)) {
-            if ($this->bFallback && $this->fallbackStructuredQuery()) {
-                return $this->lookup();
-            }
-
-            return array();
-        }
-
-        if ($this->aAddressRankList) {
-            $this->oPlaceLookup->setAddressRankList($this->aAddressRankList);
-        }
-        $this->oPlaceLookup->setAllowedTypesSQLList($this->sAllowedTypesSQLList);
-        $this->oPlaceLookup->setLanguagePreference($this->aLangPrefOrder);
-        if ($oCtx->hasNearPoint()) {
-            $this->oPlaceLookup->setAnchorSql($oCtx->sqlNear);
-        }
-
-        $aSearchResults = $this->oPlaceLookup->lookup($aResults);
-
-        $aRecheckWords = preg_split('/\b[\s,\\-]*/u', $sQuery);
-        foreach ($aRecheckWords as $i => $sWord) {
-            if (!preg_match('/[\pL\pN]/', $sWord)) {
-                unset($aRecheckWords[$i]);
-            }
-        }
-
-        Debug::printVar('Recheck words', $aRecheckWords);
-
-        foreach ($aSearchResults as $iIdx => $aResult) {
-            $fRadius = ClassTypes\getDefRadius($aResult);
-
-            $aOutlineResult = $this->oPlaceLookup->getOutlines($aResult['place_id'], $aResult['lon'], $aResult['lat'], $fRadius);
-            if ($aOutlineResult) {
-                $aResult = array_merge($aResult, $aOutlineResult);
-            }
-
-            // Is there an icon set for this type of result?
-            $sIcon = ClassTypes\getIconFile($aResult);
-            if (isset($sIcon)) {
-                $aResult['icon'] = $sIcon;
-            }
-
-            $sLabel = ClassTypes\getLabel($aResult);
-            if (isset($sLabel)) {
-                $aResult['label'] = $sLabel;
-            }
-            $aResult['name'] = $aResult['langaddress'];
-
-            if ($oCtx->hasNearPoint()) {
-                $aResult['importance'] = 0.001;
-                $aResult['foundorder'] = $aResult['addressimportance'];
-            } else {
-                if ($aResult['importance'] == 0) {
-                    $aResult['importance'] = 0.0001;
-                }
-                $aResult['importance'] *= $this->viewboxImportanceFactor(
-                    $aResult['lon'],
-                    $aResult['lat']
-                );
-
-                // secondary ordering (for results with same importance (the smaller the better):
-                // - approximate importance of address parts
-                if (isset($aResult['addressimportance']) && $aResult['addressimportance']) {
-                    $aResult['foundorder'] = -$aResult['addressimportance']/10;
-                } else {
-                    $aResult['foundorder'] = -$aResult['importance'];
-                }
-                // - number of exact matches from the query
-                $aResult['foundorder'] -= $aResults[$aResult['place_id']]->iExactMatches;
-                // - importance of the class/type
-                $iClassImportance = ClassTypes\getImportance($aResult);
-                if (isset($iClassImportance)) {
-                    $aResult['foundorder'] += 0.0001 * $iClassImportance;
-                } else {
-                    $aResult['foundorder'] += 0.01;
-                }
-                // - rank
-                $aResult['foundorder'] -= 0.00001 * (30 - $aResult['rank_search']);
-
-                // Adjust importance for the number of exact string matches in the result
-                $iCountWords = 0;
-                $sAddress = $aResult['langaddress'];
-                foreach ($aRecheckWords as $i => $sWord) {
-                    if (grapheme_stripos($sAddress, $sWord)!==false) {
-                        $iCountWords++;
-                        if (preg_match('/(^|,)\s*'.preg_quote($sWord, '/').'\s*(,|$)/', $sAddress)) {
-                            $iCountWords += 0.1;
-                        }
-                    }
-                }
-
-                // 0.1 is a completely arbitrary number but something in the range 0.1 to 0.5 would seem right
-                $aResult['importance'] = $aResult['importance'] + ($iCountWords*0.1);
-            }
-            $aSearchResults[$iIdx] = $aResult;
-        }
-        uasort($aSearchResults, 'byImportance');
-        Debug::printVar('Pre-filter results', $aSearchResults);
-
-        $aOSMIDDone = array();
-        $aClassTypeNameDone = array();
-        $aToFilter = $aSearchResults;
-        $aSearchResults = array();
-
-        foreach ($aToFilter as $aResult) {
-            $this->aExcludePlaceIDs[$aResult['place_id']] = $aResult['place_id'];
-            if (!$this->oPlaceLookup->doDeDupe() || (!isset($aOSMIDDone[$aResult['osm_type'].$aResult['osm_id']])
-                && !isset($aClassTypeNameDone[$aResult['osm_type'].$aResult['class'].$aResult['type'].$aResult['name'].$aResult['admin_level']]))
-            ) {
-                $aOSMIDDone[$aResult['osm_type'].$aResult['osm_id']] = true;
-                $aClassTypeNameDone[$aResult['osm_type'].$aResult['class'].$aResult['type'].$aResult['name'].$aResult['admin_level']] = true;
-                $aSearchResults[] = $aResult;
-            }
-
-            // Absolute limit on number of results
-            if (count($aSearchResults) >= $this->iFinalLimit) {
-                break;
-            }
-        }
-
-        Debug::printVar('Post-filter results', $aSearchResults);
-        return $aSearchResults;
-    } // end lookup()
-
-    public function debugInfo()
-    {
-        return array(
-                'Query' => $this->sQuery,
-                'Structured query' => $this->aStructuredQuery,
-                'Name keys' => Debug::fmtArrayVals($this->aLangPrefOrder),
-                'Excluded place IDs' => Debug::fmtArrayVals($this->aExcludePlaceIDs),
-                'Limit (for searches)' => $this->iLimit,
-                'Limit (for results)'=> $this->iFinalLimit,
-                'Country codes' => Debug::fmtArrayVals($this->aCountryCodes),
-                'Bounded search' => $this->bBoundedSearch,
-                'Viewbox' => Debug::fmtArrayVals($this->aViewBox),
-                'Route points' => Debug::fmtArrayVals($this->aRoutePoints),
-                'Route width' => $this->aRouteWidth,
-                'Max rank' => $this->iMaxRank,
-                'Min address rank' => $this->iMinAddressRank,
-                'Max address rank' => $this->iMaxAddressRank,
-                'Address rank list' => Debug::fmtArrayVals($this->aAddressRankList)
-               );
-    }
-} // end class
diff --git a/lib-php/ParameterParser.php b/lib-php/ParameterParser.php
deleted file mode 100644 (file)
index a4936d3..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim;
-
-class ParameterParser
-{
-    private $aParams;
-
-
-    public function __construct($aParams = null)
-    {
-        $this->aParams = ($aParams === null) ? $_GET : $aParams;
-    }
-
-    public function getBool($sName, $bDefault = false)
-    {
-        if (!isset($this->aParams[$sName])
-            || !is_string($this->aParams[$sName])
-            || strlen($this->aParams[$sName]) == 0
-        ) {
-            return $bDefault;
-        }
-
-        return (bool) $this->aParams[$sName];
-    }
-
-    public function getInt($sName, $bDefault = false)
-    {
-        if (!isset($this->aParams[$sName]) || is_array($this->aParams[$sName])) {
-            return $bDefault;
-        }
-
-        if (!preg_match('/^[+-]?[0-9]+$/', $this->aParams[$sName])) {
-            userError("Integer number expected for parameter '$sName'");
-        }
-
-        return (int) $this->aParams[$sName];
-    }
-
-    public function getFloat($sName, $bDefault = false)
-    {
-        if (!isset($this->aParams[$sName]) || is_array($this->aParams[$sName])) {
-            return $bDefault;
-        }
-
-        if (!preg_match('/^[+-]?[0-9]*\.?[0-9]+$/', $this->aParams[$sName])) {
-            userError("Floating-point number expected for parameter '$sName'");
-        }
-
-        return (float) $this->aParams[$sName];
-    }
-
-    public function getString($sName, $bDefault = false)
-    {
-        if (!isset($this->aParams[$sName])
-            || !is_string($this->aParams[$sName])
-            || strlen($this->aParams[$sName]) == 0
-        ) {
-            return $bDefault;
-        }
-
-        return $this->aParams[$sName];
-    }
-
-    public function getSet($sName, $aValues, $sDefault = false)
-    {
-        if (!isset($this->aParams[$sName])
-            || !is_string($this->aParams[$sName])
-            || strlen($this->aParams[$sName]) == 0
-        ) {
-            return $sDefault;
-        }
-
-        if (!in_array($this->aParams[$sName], $aValues, true)) {
-            userError("Parameter '$sName' must be one of: ".join(', ', $aValues));
-        }
-
-        return $this->aParams[$sName];
-    }
-
-    public function getStringList($sName, $aDefault = false)
-    {
-        $sValue = $this->getString($sName);
-
-        if ($sValue) {
-            // removes all NULL, FALSE and Empty Strings but leaves 0 (zero) values
-            return array_values(array_filter(explode(',', $sValue), 'strlen'));
-        }
-
-        return $aDefault;
-    }
-
-    public function getPreferredLanguages($sFallback = null)
-    {
-        if ($sFallback === null && isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
-            $sFallback = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
-        }
-
-        $aLanguages = array();
-        $sLangString = $this->getString('accept-language', $sFallback);
-
-        if ($sLangString
-            && preg_match_all('/(([a-z]{1,8})([-_][a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $sLangString, $aLanguagesParse, PREG_SET_ORDER)
-        ) {
-            foreach ($aLanguagesParse as $iLang => $aLanguage) {
-                $aLanguages[$aLanguage[1]] = isset($aLanguage[5])?(float)$aLanguage[5]:1 - ($iLang/100);
-                if (!isset($aLanguages[$aLanguage[2]])) {
-                    $aLanguages[$aLanguage[2]] = $aLanguages[$aLanguage[1]]/10;
-                }
-            }
-            arsort($aLanguages);
-        }
-        if (empty($aLanguages) && CONST_Default_Language) {
-            $aLanguages[CONST_Default_Language] = 1;
-        }
-
-        foreach ($aLanguages as $sLanguage => $fLanguagePref) {
-            $this->addNameTag($aLangPrefOrder, 'name:'.$sLanguage);
-        }
-        $this->addNameTag($aLangPrefOrder, 'name');
-        $this->addNameTag($aLangPrefOrder, 'brand');
-        foreach ($aLanguages as $sLanguage => $fLanguagePref) {
-            $this->addNameTag($aLangPrefOrder, 'official_name:'.$sLanguage);
-            $this->addNameTag($aLangPrefOrder, 'short_name:'.$sLanguage);
-        }
-        $this->addNameTag($aLangPrefOrder, 'official_name');
-        $this->addNameTag($aLangPrefOrder, 'short_name');
-        $this->addNameTag($aLangPrefOrder, 'ref');
-        $this->addNameTag($aLangPrefOrder, 'type');
-        return $aLangPrefOrder;
-    }
-
-    private function addNameTag(&$aLangPrefOrder, $sTag)
-    {
-        $aLangPrefOrder[$sTag] = $sTag;
-        $aLangPrefOrder['_place_'.$sTag] = '_place_'.$sTag;
-    }
-
-    public function hasSetAny($aParamNames)
-    {
-        foreach ($aParamNames as $sName) {
-            if ($this->getBool($sName)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-}
diff --git a/lib-php/Phrase.php b/lib-php/Phrase.php
deleted file mode 100644 (file)
index 4ed4d40..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim;
-
-/**
- * Segment of a query string.
- *
- * The parts of a query strings are usually separated by commas.
- */
-class Phrase
-{
-    // Complete phrase as a string (guaranteed to have no leading or trailing
-    // spaces).
-    private $sPhrase;
-    // Element type for structured searches.
-    private $sPhraseType;
-    // Possible segmentations of the phrase.
-    private $aWordSets;
-
-    public function __construct($sPhrase, $sPhraseType)
-    {
-        $this->sPhrase = trim($sPhrase);
-        $this->sPhraseType = $sPhraseType;
-    }
-
-    /**
-     * Get the original phrase of the string.
-     */
-    public function getPhrase()
-    {
-        return $this->sPhrase;
-    }
-
-    /**
-     * Return the element type of the phrase.
-     *
-     * @return string Pharse type if the phrase comes from a structured query
-     *                or empty string otherwise.
-     */
-    public function getPhraseType()
-    {
-        return $this->sPhraseType;
-    }
-
-    public function setWordSets($aWordSets)
-    {
-        $this->aWordSets = $aWordSets;
-    }
-
-    /**
-     * Return the array of possible segmentations of the phrase.
-     *
-     * @return string[][] Array of segmentations, each consisting of an
-     *                    array of terms.
-     */
-    public function getWordSets()
-    {
-        return $this->aWordSets;
-    }
-
-    /**
-     * Invert the set of possible segmentations.
-     *
-     * @return void
-     */
-    public function invertWordSets()
-    {
-        foreach ($this->aWordSets as $i => $aSet) {
-            $this->aWordSets[$i] = array_reverse($aSet);
-        }
-    }
-
-    public function debugInfo()
-    {
-        return array(
-                'Type' => $this->sPhraseType,
-                'Phrase' => $this->sPhrase,
-                'WordSets' => $this->aWordSets
-               );
-    }
-}
diff --git a/lib-php/PlaceLookup.php b/lib-php/PlaceLookup.php
deleted file mode 100644 (file)
index 895a30d..0000000
+++ /dev/null
@@ -1,615 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim;
-
-require_once(CONST_LibDir.'/AddressDetails.php');
-require_once(CONST_LibDir.'/Result.php');
-
-class PlaceLookup
-{
-    protected $oDB;
-
-    protected $aLangPrefOrderSql = "''";
-
-    protected $bAddressDetails = false;
-    protected $bExtraTags = false;
-    protected $bNameDetails = false;
-
-    protected $bIncludePolygonAsText = false;
-    protected $bIncludePolygonAsGeoJSON = false;
-    protected $bIncludePolygonAsKML = false;
-    protected $bIncludePolygonAsSVG = false;
-    protected $fPolygonSimplificationThreshold = 0.0;
-
-    protected $sAnchorSql = null;
-    protected $sAddressRankListSql = null;
-    protected $sAllowedTypesSQLList = null;
-    protected $bDeDupe = true;
-
-
-    public function __construct(&$oDB)
-    {
-        $this->oDB =& $oDB;
-    }
-
-    public function doDeDupe()
-    {
-        return $this->bDeDupe;
-    }
-
-    public function setIncludeAddressDetails($b)
-    {
-        $this->bAddressDetails = $b;
-    }
-
-    public function loadParamArray($oParams, $sGeomType = null)
-    {
-        $aLangs = $oParams->getPreferredLanguages();
-        $this->aLangPrefOrderSql =
-            'ARRAY['.join(',', $this->oDB->getDBQuotedList($aLangs)).']';
-
-        $this->bExtraTags = $oParams->getBool('extratags', false);
-        $this->bNameDetails = $oParams->getBool('namedetails', false);
-
-        $this->bDeDupe = $oParams->getBool('dedupe', $this->bDeDupe);
-
-        if ($sGeomType === null || $sGeomType == 'geojson') {
-            $this->bIncludePolygonAsGeoJSON = $oParams->getBool('polygon_geojson');
-        }
-
-        if ($oParams->getString('format', '') !== 'geojson') {
-            if ($sGeomType === null || $sGeomType == 'text') {
-                $this->bIncludePolygonAsText = $oParams->getBool('polygon_text');
-            }
-            if ($sGeomType === null || $sGeomType == 'kml') {
-                $this->bIncludePolygonAsKML = $oParams->getBool('polygon_kml');
-            }
-            if ($sGeomType === null || $sGeomType == 'svg') {
-                $this->bIncludePolygonAsSVG = $oParams->getBool('polygon_svg');
-            }
-        }
-        $this->fPolygonSimplificationThreshold
-            = $oParams->getFloat('polygon_threshold', 0.0);
-
-        $iWantedTypes =
-            ($this->bIncludePolygonAsText ? 1 : 0) +
-            ($this->bIncludePolygonAsGeoJSON ? 1 : 0) +
-            ($this->bIncludePolygonAsKML ? 1 : 0) +
-            ($this->bIncludePolygonAsSVG ? 1 : 0);
-        if ($iWantedTypes > CONST_PolygonOutput_MaximumTypes) {
-            if (CONST_PolygonOutput_MaximumTypes) {
-                userError('Select only '.CONST_PolygonOutput_MaximumTypes.' polygon output option');
-            } else {
-                userError('Polygon output is disabled');
-            }
-        }
-    }
-
-    public function getMoreUrlParams()
-    {
-        $aParams = array();
-
-        if ($this->bAddressDetails) {
-            $aParams['addressdetails'] = '1';
-        }
-        if ($this->bExtraTags) {
-            $aParams['extratags'] = '1';
-        }
-        if ($this->bNameDetails) {
-            $aParams['namedetails'] = '1';
-        }
-
-        if ($this->bIncludePolygonAsText) {
-            $aParams['polygon_text'] = '1';
-        }
-        if ($this->bIncludePolygonAsGeoJSON) {
-            $aParams['polygon_geojson'] = '1';
-        }
-        if ($this->bIncludePolygonAsKML) {
-            $aParams['polygon_kml'] = '1';
-        }
-        if ($this->bIncludePolygonAsSVG) {
-            $aParams['polygon_svg'] = '1';
-        }
-
-        if ($this->fPolygonSimplificationThreshold > 0.0) {
-            $aParams['polygon_threshold'] = $this->fPolygonSimplificationThreshold;
-        }
-
-        if (!$this->bDeDupe) {
-            $aParams['dedupe'] = '0';
-        }
-
-        return $aParams;
-    }
-
-    public function setAnchorSql($sPoint)
-    {
-        $this->sAnchorSql = $sPoint;
-    }
-
-    public function setAddressRankList($aList)
-    {
-        $this->sAddressRankListSql = '('.join(',', $aList).')';
-    }
-
-    public function setAllowedTypesSQLList($sSql)
-    {
-        $this->sAllowedTypesSQLList = $sSql;
-    }
-
-    public function setLanguagePreference($aLangPrefOrder)
-    {
-        $this->aLangPrefOrderSql = $this->oDB->getArraySQL(
-            $this->oDB->getDBQuotedList($aLangPrefOrder)
-        );
-    }
-
-    private function addressImportanceSql($sGeometry, $sPlaceId)
-    {
-        if ($this->sAnchorSql) {
-            $sSQL = 'ST_Distance('.$this->sAnchorSql.','.$sGeometry.')';
-        } else {
-            $sSQL = '(SELECT max(ai_p.importance * (ai_p.rank_address + 2))';
-            $sSQL .= '   FROM place_addressline ai_s, placex ai_p';
-            $sSQL .= '   WHERE ai_s.place_id = '.$sPlaceId;
-            $sSQL .= '     AND ai_p.place_id = ai_s.address_place_id ';
-            $sSQL .= '     AND ai_s.isaddress ';
-            $sSQL .= '     AND ai_p.importance is not null)';
-        }
-
-        return $sSQL.' AS addressimportance,';
-    }
-
-    private function langAddressSql($sHousenumber)
-    {
-        if ($this->bAddressDetails) {
-            return ''; // langaddress will be computed from address details
-        }
-
-        return 'get_address_by_language(place_id,'.$sHousenumber.','.$this->aLangPrefOrderSql.') AS langaddress,';
-    }
-
-    public function lookupOSMID($sType, $iID)
-    {
-        $sSQL = 'select place_id from placex where osm_type = :type and osm_id = :id';
-        $iPlaceID = $this->oDB->getOne($sSQL, array(':type' => $sType, ':id' => $iID));
-
-        if (!$iPlaceID) {
-            return null;
-        }
-
-        $aResults = $this->lookup(array($iPlaceID => new Result($iPlaceID)), 0, 30, true);
-
-        return empty($aResults) ? null : reset($aResults);
-    }
-
-    public function lookup($aResults, $iMinRank = 0, $iMaxRank = 30, $bAllowLinked = false)
-    {
-        Debug::newFunction('Place lookup');
-
-        if (empty($aResults)) {
-            return array();
-        }
-        $aSubSelects = array();
-
-        $sPlaceIDs = Result::joinIdsByTable($aResults, Result::TABLE_PLACEX);
-        if ($sPlaceIDs) {
-            Debug::printVar('Ids from placex', $sPlaceIDs);
-            $sSQL  = 'SELECT ';
-            $sSQL .= '    osm_type,';
-            $sSQL .= '    osm_id,';
-            $sSQL .= '    class,';
-            $sSQL .= '    type,';
-            $sSQL .= '    admin_level,';
-            $sSQL .= '    rank_search,';
-            $sSQL .= '    rank_address,';
-            $sSQL .= '    min(place_id) AS place_id,';
-            $sSQL .= '    min(parent_place_id) AS parent_place_id,';
-            $sSQL .= '    -1 as housenumber,';
-            $sSQL .= '    country_code,';
-            $sSQL .= $this->langAddressSql('-1');
-            $sSQL .= '    get_name_by_language(name,'.$this->aLangPrefOrderSql.') AS placename,';
-            $sSQL .= "    get_name_by_language(name, ARRAY['ref']) AS ref,";
-            if ($this->bExtraTags) {
-                $sSQL .= 'hstore_to_json(extratags)::text AS extra,';
-            }
-            if ($this->bNameDetails) {
-                $sSQL .= 'hstore_to_json(name)::text AS names,';
-            }
-            $sSQL .= '    avg(ST_X(centroid)) AS lon, ';
-            $sSQL .= '    avg(ST_Y(centroid)) AS lat, ';
-            $sSQL .= '    COALESCE(importance,0.75-(rank_search::float/40)) AS importance, ';
-            $sSQL .= $this->addressImportanceSql(
-                'ST_Collect(centroid)',
-                'min(CASE WHEN placex.rank_search < 28 THEN placex.place_id ELSE placex.parent_place_id END)'
-            );
-            $sSQL .= "    COALESCE(extratags->'place', extratags->'linked_place') AS extra_place ";
-            $sSQL .= ' FROM placex';
-            $sSQL .= " WHERE place_id in ($sPlaceIDs) ";
-            $sSQL .= '   AND (';
-            $sSQL .= "        placex.rank_address between $iMinRank and $iMaxRank ";
-            if (14 >= $iMinRank && 14 <= $iMaxRank) {
-                $sSQL .= "    OR (extratags->'place') = 'city'";
-            }
-            if ($this->sAddressRankListSql) {
-                $sSQL .= '    OR placex.rank_address in '.$this->sAddressRankListSql;
-            }
-            $sSQL .= '       ) ';
-            if ($this->sAllowedTypesSQLList) {
-                $sSQL .= 'AND placex.class in '.$this->sAllowedTypesSQLList;
-            }
-            if (!$bAllowLinked) {
-                $sSQL .= '    AND linked_place_id is null ';
-            }
-            $sSQL .= ' GROUP BY ';
-            $sSQL .= '     osm_type, ';
-            $sSQL .= '     osm_id, ';
-            $sSQL .= '     class, ';
-            $sSQL .= '     type, ';
-            $sSQL .= '     admin_level, ';
-            $sSQL .= '     rank_search, ';
-            $sSQL .= '     rank_address, ';
-            $sSQL .= '     housenumber,';
-            $sSQL .= '     country_code, ';
-            $sSQL .= '     importance, ';
-            if (!$this->bDeDupe) {
-                $sSQL .= 'place_id,';
-            }
-            if (!$this->bAddressDetails) {
-                $sSQL .= 'langaddress, ';
-            }
-            $sSQL .= '     placename, ';
-            $sSQL .= '     ref, ';
-            if ($this->bExtraTags) {
-                $sSQL .= 'extratags, ';
-            }
-            if ($this->bNameDetails) {
-                $sSQL .= 'name, ';
-            }
-            $sSQL .= '     extra_place ';
-
-            $aSubSelects[] = $sSQL;
-        }
-
-        // postcode table
-        $sPlaceIDs = Result::joinIdsByTable($aResults, Result::TABLE_POSTCODE);
-        if ($sPlaceIDs) {
-            Debug::printVar('Ids from location_postcode', $sPlaceIDs);
-            $sSQL = 'SELECT';
-            $sSQL .= "  'P' as osm_type,";
-            $sSQL .= '  (SELECT osm_id from placex p WHERE p.place_id = lp.parent_place_id) as osm_id,';
-            $sSQL .= "  'place' as class, 'postcode' as type,";
-            $sSQL .= '  null::smallint as admin_level, rank_search, rank_address,';
-            $sSQL .= '  place_id, parent_place_id,';
-            $sSQL .= '  -1 as housenumber,';
-            $sSQL .= '  country_code,';
-            $sSQL .= $this->langAddressSql('-1');
-            $sSQL .= '  postcode as placename,';
-            $sSQL .= '  postcode as ref,';
-            if ($this->bExtraTags) {
-                $sSQL .= 'null::text AS extra,';
-            }
-            if ($this->bNameDetails) {
-                $sSQL .= 'null::text AS names,';
-            }
-            $sSQL .= '  ST_x(geometry) AS lon, ST_y(geometry) AS lat,';
-            $sSQL .= '  (0.75-(rank_search::float/40)) AS importance, ';
-            $sSQL .= $this->addressImportanceSql('geometry', 'lp.parent_place_id');
-            $sSQL .= '  null::text AS extra_place ';
-            $sSQL .= 'FROM location_postcode lp';
-            $sSQL .= " WHERE place_id in ($sPlaceIDs) ";
-            $sSQL .= "   AND lp.rank_address between $iMinRank and $iMaxRank";
-
-            $aSubSelects[] = $sSQL;
-        }
-
-        // All other tables are rank 30 only.
-        if ($iMaxRank == 30) {
-            // TIGER table
-            if (CONST_Use_US_Tiger_Data) {
-                $sPlaceIDs = Result::joinIdsByTable($aResults, Result::TABLE_TIGER);
-                if ($sPlaceIDs) {
-                    Debug::printVar('Ids from Tiger table', $sPlaceIDs);
-                    $sHousenumbers = Result::sqlHouseNumberTable($aResults, Result::TABLE_TIGER);
-                    // Tiger search only if a housenumber was searched and if it was found
-                    // (realized through a join)
-                    $sSQL = ' SELECT ';
-                    $sSQL .= "     'T' AS osm_type, ";
-                    $sSQL .= '     (SELECT osm_id from placex p WHERE p.place_id=blub.parent_place_id) as osm_id, ';
-                    $sSQL .= "     'place' AS class, ";
-                    $sSQL .= "     'house' AS type, ";
-                    $sSQL .= '     null::smallint AS admin_level, ';
-                    $sSQL .= '     30 AS rank_search, ';
-                    $sSQL .= '     30 AS rank_address, ';
-                    $sSQL .= '     place_id, ';
-                    $sSQL .= '     parent_place_id, ';
-                    $sSQL .= '     housenumber_for_place as housenumber,';
-                    $sSQL .= "     'us' AS country_code, ";
-                    $sSQL .= $this->langAddressSql('housenumber_for_place');
-                    $sSQL .= '     null::text AS placename, ';
-                    $sSQL .= '     null::text AS ref, ';
-                    if ($this->bExtraTags) {
-                        $sSQL .= 'null::text AS extra,';
-                    }
-                    if ($this->bNameDetails) {
-                        $sSQL .= 'null::text AS names,';
-                    }
-                    $sSQL .= '     st_x(centroid) AS lon, ';
-                    $sSQL .= '     st_y(centroid) AS lat,';
-                    $sSQL .= '     -1.15 AS importance, ';
-                    $sSQL .= $this->addressImportanceSql('centroid', 'blub.parent_place_id');
-                    $sSQL .= '     null::text AS extra_place ';
-                    $sSQL .= ' FROM (';
-                    $sSQL .= '     SELECT place_id, ';    // interpolate the Tiger housenumbers here
-                    $sSQL .= '         CASE WHEN startnumber != endnumber';
-                    $sSQL .= '              THEN ST_LineInterpolatePoint(linegeo, (housenumber_for_place-startnumber::float)/(endnumber-startnumber)::float)';
-                    $sSQL .= '              ELSE ST_LineInterpolatePoint(linegeo, 0.5) END AS centroid, ';
-                    $sSQL .= '         parent_place_id, ';
-                    $sSQL .= '         housenumber_for_place';
-                    $sSQL .= '     FROM (';
-                    $sSQL .= '            location_property_tiger ';
-                    $sSQL .= '            JOIN (values '.$sHousenumbers.') AS housenumbers(place_id, housenumber_for_place) USING(place_id)) ';
-                    $sSQL .= '     WHERE ';
-                    $sSQL .= '         housenumber_for_place >= startnumber';
-                    $sSQL .= '         AND housenumber_for_place <= endnumber';
-                    $sSQL .= ' ) AS blub'; //postgres wants an alias here
-
-                    $aSubSelects[] = $sSQL;
-                }
-            }
-
-            // osmline - interpolated housenumbers
-            $sPlaceIDs = Result::joinIdsByTable($aResults, Result::TABLE_OSMLINE);
-            if ($sPlaceIDs) {
-                Debug::printVar('Ids from interpolation', $sPlaceIDs);
-                $sHousenumbers = Result::sqlHouseNumberTable($aResults, Result::TABLE_OSMLINE);
-                // interpolation line search only if a housenumber was searched
-                // (realized through a join)
-                $sSQL = 'SELECT ';
-                $sSQL .= "  'W' AS osm_type, ";
-                $sSQL .= '  osm_id, ';
-                $sSQL .= "  'place' AS class, ";
-                $sSQL .= "  'house' AS type, ";
-                $sSQL .= '  null::smallint AS admin_level, ';
-                $sSQL .= '  30 AS rank_search, ';
-                $sSQL .= '  30 AS rank_address, ';
-                $sSQL .= '  place_id, ';
-                $sSQL .= '  parent_place_id, ';
-                $sSQL .= '  housenumber_for_place as housenumber,';
-                $sSQL .= '  country_code, ';
-                $sSQL .= $this->langAddressSql('housenumber_for_place');
-                $sSQL .= '  null::text AS placename, ';
-                $sSQL .= '  null::text AS ref, ';
-                if ($this->bExtraTags) {
-                    $sSQL .= 'null::text AS extra, ';
-                }
-                if ($this->bNameDetails) {
-                    $sSQL .= 'null::text AS names, ';
-                }
-                $sSQL .= '  st_x(centroid) AS lon, ';
-                $sSQL .= '  st_y(centroid) AS lat, ';
-                // slightly smaller than the importance for normal houses
-                $sSQL .= '  -0.1 AS importance, ';
-                $sSQL .= $this->addressImportanceSql('centroid', 'blub.parent_place_id');
-                $sSQL .= '  null::text AS extra_place ';
-                $sSQL .= '  FROM (';
-                $sSQL .= '     SELECT ';
-                $sSQL .= '         osm_id, ';
-                $sSQL .= '         place_id, ';
-                $sSQL .= '         country_code, ';
-                $sSQL .= '         CASE ';             // interpolate the housenumbers here
-                $sSQL .= '           WHEN startnumber != endnumber ';
-                $sSQL .= '           THEN ST_LineInterpolatePoint(linegeo, (housenumber_for_place-startnumber::float)/(endnumber-startnumber)::float) ';
-                $sSQL .= '           ELSE linegeo ';
-                $sSQL .= '         END as centroid, ';
-                $sSQL .= '         parent_place_id, ';
-                $sSQL .= '         housenumber_for_place ';
-                $sSQL .= '     FROM (';
-                $sSQL .= '            location_property_osmline ';
-                $sSQL .= '            JOIN (values '.$sHousenumbers.') AS housenumbers(place_id, housenumber_for_place) USING(place_id)';
-                $sSQL .= '          ) ';
-                $sSQL .= '     WHERE housenumber_for_place >= 0 ';
-                $sSQL .= '  ) as blub'; //postgres wants an alias here
-
-                $aSubSelects[] = $sSQL;
-            }
-        }
-
-        if (empty($aSubSelects)) {
-            return array();
-        }
-
-        $sSQL = join(' UNION ', $aSubSelects);
-        Debug::printSQL($sSQL);
-        $aPlaces = $this->oDB->getAll($sSQL, null, 'Could not lookup place');
-
-        foreach ($aPlaces as &$aPlace) {
-            $aPlace['importance'] = (float) $aPlace['importance'];
-            if ($this->bAddressDetails) {
-                // to get addressdetails for tiger data, the housenumber is needed
-                $aPlace['address'] = new AddressDetails(
-                    $this->oDB,
-                    $aPlace['place_id'],
-                    $aPlace['housenumber'],
-                    $this->aLangPrefOrderSql
-                );
-                $aPlace['langaddress'] = $aPlace['address']->getLocaleAddress();
-            }
-
-            if ($this->bExtraTags) {
-                if ($aPlace['extra']) {
-                    $aPlace['sExtraTags'] = json_decode($aPlace['extra'], true);
-                } else {
-                    $aPlace['sExtraTags'] = (object) array();
-                }
-            }
-
-            if ($this->bNameDetails) {
-                $aPlace['sNameDetails'] = $this->extractNames($aPlace['names']);
-            }
-
-            $aPlace['addresstype'] = ClassTypes\getLabelTag(
-                $aPlace,
-                $aPlace['country_code']
-            );
-
-            $aResults[$aPlace['place_id']] = $aPlace;
-        }
-
-        $aResults = array_filter(
-            $aResults,
-            function ($v) {
-                return !($v instanceof Result);
-            }
-        );
-
-        Debug::printVar('Places', $aResults);
-
-        return $aResults;
-    }
-
-
-    private function extractNames($sNames)
-    {
-        if (!$sNames) {
-            return (object) array();
-        }
-
-        $aFullNames = json_decode($sNames, true);
-        $aNames = array();
-
-        foreach ($aFullNames as $sKey => $sValue) {
-            if (strpos($sKey, '_place_') === 0) {
-                $sSubKey = substr($sKey, 7);
-                if (array_key_exists($sSubKey, $aFullNames)) {
-                    $aNames[$sKey] = $sValue;
-                } else {
-                    $aNames[$sSubKey] = $sValue;
-                }
-            } else {
-                $aNames[$sKey] = $sValue;
-            }
-        }
-
-        return $aNames;
-    }
-
-
-    /* returns an array which will contain the keys
-     *   aBoundingBox
-     * and may also contain one or more of the keys
-     *   asgeojson
-     *   askml
-     *   assvg
-     *   astext
-     *   lat
-     *   lon
-     */
-    public function getOutlines($iPlaceID, $fLon = null, $fLat = null, $fRadius = null, $fLonReverse = null, $fLatReverse = null)
-    {
-
-        $aOutlineResult = array();
-        if (!$iPlaceID) {
-            return $aOutlineResult;
-        }
-
-        // Get the bounding box and outline polygon
-        $sSQL = 'select place_id,0 as numfeatures,st_area(geometry) as area,';
-        $sSQL .= ' ST_Y(centroid) as centrelat, ST_X(centroid) as centrelon,';
-        $sSQL .= ' ST_YMin(geometry) as minlat,ST_YMax(geometry) as maxlat,';
-        $sSQL .= ' ST_XMin(geometry) as minlon,ST_XMax(geometry) as maxlon';
-        if ($this->bIncludePolygonAsGeoJSON) {
-            $sSQL .= ',ST_AsGeoJSON(geometry) as asgeojson';
-        }
-        if ($this->bIncludePolygonAsKML) {
-            $sSQL .= ',ST_AsKML(geometry) as askml';
-        }
-        if ($this->bIncludePolygonAsSVG) {
-            $sSQL .= ',ST_AsSVG(geometry) as assvg';
-        }
-        if ($this->bIncludePolygonAsText) {
-            $sSQL .= ',ST_AsText(geometry) as astext';
-        }
-
-        $sSQL .= ' FROM (SELECT place_id';
-        if ($fLonReverse != null && $fLatReverse != null) {
-            $sSQL .= ',CASE WHEN (class = \'highway\') AND (ST_GeometryType(geometry) = \'ST_LineString\') THEN ';
-            $sSQL .=' ST_ClosestPoint(geometry, ST_SetSRID(ST_Point('.$fLatReverse.','.$fLonReverse.'),4326))';
-            $sSQL .=' ELSE centroid END AS centroid';
-        } else {
-            $sSQL .= ',centroid';
-        }
-        if ($this->fPolygonSimplificationThreshold > 0) {
-            $sSQL .= ',ST_SimplifyPreserveTopology(geometry,'.$this->fPolygonSimplificationThreshold.') as geometry';
-        } else {
-            $sSQL .= ',geometry';
-        }
-        $sSQL .= ' FROM placex where place_id = '.$iPlaceID.') as plx';
-
-        $aPointPolygon = $this->oDB->getRow($sSQL, null, 'Could not get outline');
-
-        if ($aPointPolygon && $aPointPolygon['place_id']) {
-            if ($aPointPolygon['centrelon'] !== null && $aPointPolygon['centrelat'] !== null) {
-                $aOutlineResult['lat'] = $aPointPolygon['centrelat'];
-                $aOutlineResult['lon'] = $aPointPolygon['centrelon'];
-            }
-
-            if ($this->bIncludePolygonAsGeoJSON) {
-                $aOutlineResult['asgeojson'] = $aPointPolygon['asgeojson'];
-            }
-            if ($this->bIncludePolygonAsKML) {
-                $aOutlineResult['askml'] = $aPointPolygon['askml'];
-            }
-            if ($this->bIncludePolygonAsSVG) {
-                $aOutlineResult['assvg'] = $aPointPolygon['assvg'];
-            }
-            if ($this->bIncludePolygonAsText) {
-                $aOutlineResult['astext'] = $aPointPolygon['astext'];
-            }
-
-            if (abs($aPointPolygon['minlat'] - $aPointPolygon['maxlat']) < 0.0000001) {
-                $aPointPolygon['minlat'] = $aPointPolygon['minlat'] - $fRadius;
-                $aPointPolygon['maxlat'] = $aPointPolygon['maxlat'] + $fRadius;
-            }
-
-            if (abs($aPointPolygon['minlon'] - $aPointPolygon['maxlon']) < 0.0000001) {
-                $aPointPolygon['minlon'] = $aPointPolygon['minlon'] - $fRadius;
-                $aPointPolygon['maxlon'] = $aPointPolygon['maxlon'] + $fRadius;
-            }
-
-            $aOutlineResult['aBoundingBox'] = array(
-                                               (string)$aPointPolygon['minlat'],
-                                               (string)$aPointPolygon['maxlat'],
-                                               (string)$aPointPolygon['minlon'],
-                                               (string)$aPointPolygon['maxlon']
-                                              );
-        }
-
-        // as a fallback we generate a bounding box without knowing the size of the geometry
-        if ((!isset($aOutlineResult['aBoundingBox'])) && isset($fLon)) {
-            $aBounds = array(
-                        'minlat' => $fLat - $fRadius,
-                        'maxlat' => $fLat + $fRadius,
-                        'minlon' => $fLon - $fRadius,
-                        'maxlon' => $fLon + $fRadius
-                       );
-
-            $aOutlineResult['aBoundingBox'] = array(
-                                               (string)$aBounds['minlat'],
-                                               (string)$aBounds['maxlat'],
-                                               (string)$aBounds['minlon'],
-                                               (string)$aBounds['maxlon']
-                                              );
-        }
-        return $aOutlineResult;
-    }
-}
diff --git a/lib-php/Result.php b/lib-php/Result.php
deleted file mode 100644 (file)
index 4b244d1..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim;
-
-/**
- * A single result of a search operation or a reverse lookup.
- *
- * This object only contains the id of the result. It does not yet
- * have any details needed to format the output document.
- */
-class Result
-{
-    const TABLE_PLACEX = 0;
-    const TABLE_POSTCODE = 1;
-    const TABLE_OSMLINE = 2;
-    const TABLE_TIGER = 3;
-
-    /// Database table that contains the result.
-    public $iTable;
-    /// Id of the result.
-    public $iId;
-    /// House number (only for interpolation results).
-    public $iHouseNumber = -1;
-    /// Number of exact matches in address (address searches only).
-    public $iExactMatches = 0;
-    /// Subranking within the results (the higher the worse).
-    public $iResultRank = 0;
-    /// Address rank of the result.
-    public $iAddressRank;
-
-    public function debugInfo()
-    {
-        return array(
-                'Table' => $this->iTable,
-                'ID' => $this->iId,
-                'House number' => $this->iHouseNumber,
-                'Exact Matches' => $this->iExactMatches,
-                'Result rank' => $this->iResultRank
-               );
-    }
-
-
-    public function __construct($sId, $iTable = Result::TABLE_PLACEX)
-    {
-        $this->iTable = $iTable;
-        $this->iId = (int) $sId;
-    }
-
-    public static function joinIdsByTable($aResults, $iTable)
-    {
-        return join(',', array_keys(array_filter(
-            $aResults,
-            function ($aValue) use ($iTable) {
-                return $aValue->iTable == $iTable;
-            }
-        )));
-    }
-
-    public static function joinIdsByTableMinRank($aResults, $iTable, $iMinAddressRank)
-    {
-        return join(',', array_keys(array_filter(
-            $aResults,
-            function ($aValue) use ($iTable, $iMinAddressRank) {
-                return $aValue->iTable == $iTable && $aValue->iAddressRank >= $iMinAddressRank;
-            }
-        )));
-    }
-
-    public static function joinIdsByTableMaxRank($aResults, $iTable, $iMaxAddressRank)
-    {
-        return join(',', array_keys(array_filter(
-            $aResults,
-            function ($aValue) use ($iTable, $iMaxAddressRank) {
-                return $aValue->iTable == $iTable && $aValue->iAddressRank <= $iMaxAddressRank;
-            }
-        )));
-    }
-
-    public static function sqlHouseNumberTable($aResults, $iTable)
-    {
-        $sHousenumbers = '';
-        $sSep = '';
-        foreach ($aResults as $oResult) {
-            if ($oResult->iTable == $iTable) {
-                $sHousenumbers .= $sSep.'('.$oResult->iId.',';
-                $sHousenumbers .= $oResult->iHouseNumber.')';
-                $sSep = ',';
-            }
-        }
-
-        return $sHousenumbers;
-    }
-
-    /**
-     * Split a result array into highest ranked result and the rest
-     *
-     * @param object[] $aResults List of results to split.
-     *
-     * @return array[]
-     */
-    public static function splitResults($aResults)
-    {
-        $aHead = array();
-        $aTail = array();
-        $iMinRank = 10000;
-
-        foreach ($aResults as $oRes) {
-            if ($oRes->iResultRank < $iMinRank) {
-                $aTail += $aHead;
-                $aHead = array($oRes->iId => $oRes);
-                $iMinRank = $oRes->iResultRank;
-            } elseif ($oRes->iResultRank == $iMinRank) {
-                $aHead[$oRes->iId] = $oRes;
-            } else {
-                $aTail[$oRes->iId] = $oRes;
-            }
-        }
-
-        return array('head' => $aHead, 'tail' => $aTail);
-    }
-}
diff --git a/lib-php/ReverseGeocode.php b/lib-php/ReverseGeocode.php
deleted file mode 100644 (file)
index f6ea590..0000000
+++ /dev/null
@@ -1,401 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim;
-
-require_once(CONST_LibDir.'/Result.php');
-
-class ReverseGeocode
-{
-    protected $oDB;
-    protected $iMaxRank = 28;
-
-
-    public function __construct(&$oDB)
-    {
-        $this->oDB =& $oDB;
-    }
-
-
-    public function setZoom($iZoom)
-    {
-        // Zoom to rank, this could probably be calculated but a lookup gives fine control
-        $aZoomRank = array(
-                      0 => 2, // Continent / Sea
-                      1 => 2,
-                      2 => 2,
-                      3 => 4, // Country
-                      4 => 4,
-                      5 => 8, // State
-                      6 => 10, // Region
-                      7 => 10,
-                      8 => 12, // County
-                      9 => 12,
-                      10 => 17, // City
-                      11 => 17,
-                      12 => 18, // Town
-                      13 => 19, // Village
-                      14 => 22, // Neighbourhood
-                      15 => 25, // Locality
-                      16 => 26, // major street
-                      17 => 27, // minor street
-                      18 => 30, // or >, Building
-                      19 => 30, // or >, Building
-                     );
-        $this->iMaxRank = (isset($iZoom) && isset($aZoomRank[$iZoom]))?$aZoomRank[$iZoom]:28;
-    }
-
-    /**
-     * Find the closest interpolation with the given search diameter.
-     *
-     * @param string $sPointSQL   Reverse geocoding point as SQL
-     * @param float  $fSearchDiam Search diameter
-     *
-     * @return Record of the interpolation or null.
-     */
-    protected function lookupInterpolation($sPointSQL, $fSearchDiam)
-    {
-        Debug::newFunction('lookupInterpolation');
-        $sSQL = 'SELECT place_id, parent_place_id, 30 as rank_search,';
-        $sSQL .= '  (CASE WHEN endnumber != startnumber';
-        $sSQL .= '        THEN (endnumber - startnumber) * ST_LineLocatePoint(linegeo,'.$sPointSQL.')';
-        $sSQL .= '        ELSE startnumber END) as fhnr,';
-        $sSQL .= '  startnumber, endnumber, step,';
-        $sSQL .= '  ST_Distance(linegeo,'.$sPointSQL.') as distance';
-        $sSQL .= ' FROM location_property_osmline';
-        $sSQL .= ' WHERE ST_DWithin('.$sPointSQL.', linegeo, '.$fSearchDiam.')';
-        $sSQL .= '       and indexed_status = 0 and startnumber is not NULL ';
-        $sSQL .= '       and parent_place_id != 0';
-        $sSQL .= ' ORDER BY distance ASC limit 1';
-        Debug::printSQL($sSQL);
-
-        return $this->oDB->getRow(
-            $sSQL,
-            null,
-            'Could not determine closest housenumber on an osm interpolation line.'
-        );
-    }
-
-    protected function lookupLargeArea($sPointSQL, $iMaxRank)
-    {
-        $sCountryCode = $this->getCountryCode($sPointSQL);
-        if (CONST_Search_WithinCountries and $sCountryCode == null) {
-            return  null;
-        }
-
-        if ($iMaxRank > 4) {
-            $aPlace = $this->lookupPolygon($sPointSQL, $iMaxRank);
-            if ($aPlace) {
-                return new Result($aPlace['place_id']);
-            }
-        }
-
-        // If no polygon which contains the searchpoint is found,
-        // searches in the country_osm_grid table for a polygon.
-        return  $this->lookupInCountry($sPointSQL, $iMaxRank, $sCountryCode);
-    }
-
-    protected function getCountryCode($sPointSQL)
-    {
-        Debug::newFunction('getCountryCode');
-        // searches for polygon in table country_osm_grid which contains the searchpoint
-        // and searches for the nearest place node to the searchpoint in this polygon
-        $sSQL = 'SELECT country_code FROM country_osm_grid';
-        $sSQL .= ' WHERE ST_CONTAINS(geometry, '.$sPointSQL.') LIMIT 1';
-        Debug::printSQL($sSQL);
-
-        $sCountryCode = $this->oDB->getOne(
-            $sSQL,
-            null,
-            'Could not determine country polygon containing the point.'
-        );
-        return $sCountryCode;
-    }
-
-    protected function lookupInCountry($sPointSQL, $iMaxRank, $sCountryCode)
-    {
-        Debug::newFunction('lookupInCountry');
-        if ($sCountryCode) {
-            if ($iMaxRank > 4) {
-                // look for place nodes with the given country code
-                $sSQL = 'SELECT place_id FROM';
-                $sSQL .= ' (SELECT place_id, rank_search,';
-                $sSQL .= '         ST_distance('.$sPointSQL.', geometry) as distance';
-                $sSQL .= ' FROM placex';
-                $sSQL .= ' WHERE osm_type = \'N\'';
-                $sSQL .= ' AND country_code = \''.$sCountryCode.'\'';
-                $sSQL .= ' AND rank_address between 4 and 25'; // needed to select right index
-                $sSQL .= ' AND rank_search between 5 and ' .min(25, $iMaxRank);
-                $sSQL .= ' AND type != \'postcode\'';
-                $sSQL .= ' AND name IS NOT NULL ';
-                $sSQL .= ' and indexed_status = 0 and linked_place_id is null';
-                $sSQL .= ' AND ST_Buffer(geometry, reverse_place_diameter(rank_search)) && '.$sPointSQL;
-                $sSQL .= ') as a ';
-                $sSQL .= 'WHERE distance <= reverse_place_diameter(rank_search)';
-                $sSQL .= ' ORDER BY rank_search DESC, distance ASC';
-                $sSQL .= ' LIMIT 1';
-                Debug::printSQL($sSQL);
-
-                $aPlace = $this->oDB->getRow($sSQL, null, 'Could not determine place node.');
-                Debug::printVar('Country node', $aPlace);
-
-                if ($aPlace) {
-                    return new Result($aPlace['place_id']);
-                }
-            }
-
-            // still nothing, then return the country object
-            $sSQL = 'SELECT place_id, ST_distance('.$sPointSQL.', centroid) as distance';
-            $sSQL .= ' FROM placex';
-            $sSQL .= ' WHERE country_code = \''.$sCountryCode.'\'';
-            $sSQL .= ' AND rank_search = 4 AND rank_address = 4';
-            $sSQL .= ' AND class in (\'boundary\',  \'place\')';
-            $sSQL .= ' AND linked_place_id is null';
-            $sSQL .= ' ORDER BY distance ASC';
-            Debug::printSQL($sSQL);
-
-            $aPlace = $this->oDB->getRow($sSQL, null, 'Could not determine place node.');
-            Debug::printVar('Country place', $aPlace);
-            if ($aPlace) {
-                return new Result($aPlace['place_id']);
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Search for areas or nodes for areas or nodes between state and suburb level.
-     *
-     * @param string $sPointSQL Search point as SQL string.
-     * @param int    $iMaxRank  Maximum address rank of the feature.
-     *
-     * @return Record of the found feature or null.
-     *
-     * Searches first for polygon that contains the search point.
-     * If such a polygon is found, place nodes with a higher rank are
-     * searched inside the polygon.
-     */
-    protected function lookupPolygon($sPointSQL, $iMaxRank)
-    {
-        Debug::newFunction('lookupPolygon');
-        // polygon search begins at suburb-level
-        if ($iMaxRank > 25) {
-            $iMaxRank = 25;
-        }
-        // no polygon search over country-level
-        if ($iMaxRank < 5) {
-            $iMaxRank = 5;
-        }
-        // search for polygon
-        $sSQL = 'SELECT place_id, parent_place_id, rank_address, rank_search FROM';
-        $sSQL .= '(select place_id, parent_place_id, rank_address, rank_search, country_code, geometry';
-        $sSQL .= ' FROM placex';
-        $sSQL .= ' WHERE ST_GeometryType(geometry) in (\'ST_Polygon\', \'ST_MultiPolygon\')';
-        // Ensure that query planner doesn't use the index on rank_search.
-        $sSQL .= ' AND coalesce(rank_search, 0) between 5 and ' .$iMaxRank;
-        $sSQL .= ' AND rank_address between 4 and 25'; // needed for index selection
-        $sSQL .= ' AND geometry && '.$sPointSQL;
-        $sSQL .= ' AND type != \'postcode\' ';
-        $sSQL .= ' AND name is not null';
-        $sSQL .= ' AND indexed_status = 0 and linked_place_id is null';
-        $sSQL .= ' ORDER BY rank_search DESC LIMIT 50 ) as a';
-        $sSQL .= ' WHERE ST_Contains(geometry, '.$sPointSQL.' )';
-        $sSQL .= ' ORDER BY rank_search DESC LIMIT 1';
-        Debug::printSQL($sSQL);
-
-        $aPoly = $this->oDB->getRow($sSQL, null, 'Could not determine polygon containing the point.');
-        Debug::printVar('Polygon result', $aPoly);
-
-        if ($aPoly) {
-        // if a polygon is found, search for placenodes begins ...
-            $iRankAddress = $aPoly['rank_address'];
-            $iRankSearch = $aPoly['rank_search'];
-            $iPlaceID = $aPoly['place_id'];
-
-            if ($iRankSearch != $iMaxRank) {
-                $sSQL = 'SELECT place_id FROM ';
-                $sSQL .= '(SELECT place_id, rank_search, country_code, geometry,';
-                $sSQL .= ' ST_distance('.$sPointSQL.', geometry) as distance';
-                $sSQL .= ' FROM placex';
-                $sSQL .= ' WHERE osm_type = \'N\'';
-                $sSQL .= ' AND rank_search > '.$iRankSearch;
-                $sSQL .= ' AND rank_search <= '.$iMaxRank;
-                $sSQL .= ' AND rank_address between 4 and 25';  // needed to select right index
-                $sSQL .= ' AND type != \'postcode\'';
-                $sSQL .= ' AND name IS NOT NULL ';
-                $sSQL .= ' AND indexed_status = 0 AND linked_place_id is null';
-                $sSQL .= ' AND ST_Buffer(geometry, reverse_place_diameter(rank_search)) && '.$sPointSQL;
-                $sSQL .= ' ORDER BY rank_search DESC, distance ASC';
-                $sSQL .= ' limit 100) as a';
-                $sSQL .= ' WHERE ST_Contains((SELECT geometry FROM placex WHERE place_id = '.$iPlaceID.'), geometry )';
-                $sSQL .= ' AND distance <= reverse_place_diameter(rank_search)';
-                $sSQL .= ' ORDER BY rank_search DESC, distance ASC';
-                $sSQL .= ' LIMIT 1';
-                Debug::printSQL($sSQL);
-
-                $aPlaceNode = $this->oDB->getRow($sSQL, null, 'Could not determine place node.');
-                Debug::printVar('Nearest place node', $aPlaceNode);
-                if ($aPlaceNode) {
-                    return $aPlaceNode;
-                }
-            }
-        }
-        return $aPoly;
-    }
-
-
-    public function lookup($fLat, $fLon, $bDoInterpolation = true)
-    {
-        return $this->lookupPoint(
-            'ST_SetSRID(ST_Point('.$fLon.','.$fLat.'),4326)',
-            $bDoInterpolation
-        );
-    }
-
-    public function lookupPoint($sPointSQL, $bDoInterpolation = true)
-    {
-        Debug::newFunction('lookupPoint');
-        // Find the nearest point
-        $fSearchDiam = 0.006;
-        $oResult = null;
-        $aPlace = null;
-
-        // for POI or street level
-        if ($this->iMaxRank >= 26) {
-            // starts if the search is on POI or street level,
-            // searches for the nearest POI or street,
-            // if a street is found and a POI is searched for,
-            // the nearest POI which the found street is a parent of is chosen.
-            $sSQL = 'select place_id,parent_place_id,rank_address,country_code,';
-            $sSQL .= ' ST_distance('.$sPointSQL.', geometry) as distance';
-            $sSQL .= ' FROM ';
-            $sSQL .= ' placex';
-            $sSQL .= '   WHERE ST_DWithin('.$sPointSQL.', geometry, '.$fSearchDiam.')';
-            $sSQL .= '   AND';
-            $sSQL .= ' rank_address between 26 and '.$this->iMaxRank;
-            $sSQL .= ' and (name is not null or housenumber is not null';
-            $sSQL .= ' or rank_address between 26 and 27)';
-            $sSQL .= ' and (rank_address between 26 and 27';
-            $sSQL .= '      or ST_GeometryType(geometry) != \'ST_LineString\')';
-            $sSQL .= ' and class not in (\'boundary\')';
-            $sSQL .= ' and indexed_status = 0 and linked_place_id is null';
-            $sSQL .= ' and (ST_GeometryType(geometry) not in (\'ST_Polygon\',\'ST_MultiPolygon\') ';
-            $sSQL .= ' OR ST_DWithin('.$sPointSQL.', centroid, '.$fSearchDiam.'))';
-            $sSQL .= ' ORDER BY distance ASC limit 1';
-            Debug::printSQL($sSQL);
-
-            $aPlace = $this->oDB->getRow($sSQL, null, 'Could not determine closest place.');
-
-            Debug::printVar('POI/street level result', $aPlace);
-            if ($aPlace) {
-                $iPlaceID = $aPlace['place_id'];
-                $oResult = new Result($iPlaceID);
-                $iRankAddress = $aPlace['rank_address'];
-            }
-
-            if ($aPlace) {
-                // if street and maxrank > streetlevel
-                if ($iRankAddress <= 27 && $this->iMaxRank > 27) {
-                    // find the closest object (up to a certain radius) of which the street is a parent of
-                    $sSQL = ' select place_id,';
-                    $sSQL .= ' ST_distance('.$sPointSQL.', geometry) as distance';
-                    $sSQL .= ' FROM ';
-                    $sSQL .= ' placex';
-                    // radius ?
-                    $sSQL .= ' WHERE ST_DWithin('.$sPointSQL.', geometry, 0.001)';
-                    $sSQL .= ' AND parent_place_id = '.$iPlaceID;
-                    $sSQL .= ' and rank_address > 28';
-                    $sSQL .= ' and ST_GeometryType(geometry) != \'ST_LineString\'';
-                    $sSQL .= ' and (name is not null or housenumber is not null)';
-                    $sSQL .= ' and class not in (\'boundary\')';
-                    $sSQL .= ' and indexed_status = 0 and linked_place_id is null';
-                    $sSQL .= ' ORDER BY distance ASC limit 1';
-                    Debug::printSQL($sSQL);
-
-                    $aStreet = $this->oDB->getRow($sSQL, null, 'Could not determine closest place.');
-                    Debug::printVar('Closest POI result', $aStreet);
-
-                    if ($aStreet) {
-                        $aPlace = $aStreet;
-                        $oResult = new Result($aStreet['place_id']);
-                        $iRankAddress = 30;
-                    }
-                }
-
-                  // In the US we can check TIGER data for nearest housenumber
-                if (CONST_Use_US_Tiger_Data
-                    && $iRankAddress <= 27
-                    && $aPlace['country_code'] == 'us'
-                    && $this->iMaxRank >= 28
-                ) {
-                    $sSQL = 'SELECT place_id,parent_place_id,30 as rank_search,';
-                    $sSQL .= '      (endnumber - startnumber) * ST_LineLocatePoint(linegeo,'.$sPointSQL.') as fhnr,';
-                    $sSQL .= '      startnumber, endnumber, step,';
-                    $sSQL .= '      ST_Distance('.$sPointSQL.', linegeo) as distance';
-                    $sSQL .= ' FROM location_property_tiger WHERE parent_place_id = '.$oResult->iId;
-                    $sSQL .= ' AND ST_DWithin('.$sPointSQL.', linegeo, 0.001)';
-                    $sSQL .= ' ORDER BY distance ASC limit 1';
-                    Debug::printSQL($sSQL);
-
-                    $aPlaceTiger = $this->oDB->getRow($sSQL, null, 'Could not determine closest Tiger place.');
-                    Debug::printVar('Tiger house number result', $aPlaceTiger);
-
-                    if ($aPlaceTiger) {
-                        $aPlace = $aPlaceTiger;
-                        $oResult = new Result($aPlaceTiger['place_id'], Result::TABLE_TIGER);
-                        $iRndNum = max(0, round($aPlaceTiger['fhnr'] / $aPlaceTiger['step']) * $aPlaceTiger['step']);
-                        $oResult->iHouseNumber = $aPlaceTiger['startnumber'] + $iRndNum;
-                        if ($oResult->iHouseNumber > $aPlaceTiger['endnumber']) {
-                            $oResult->iHouseNumber = $aPlaceTiger['endnumber'];
-                        }
-                        $iRankAddress = 30;
-                    }
-                }
-            }
-
-            if ($bDoInterpolation && $this->iMaxRank >= 30) {
-                $fDistance = $fSearchDiam;
-                if ($aPlace) {
-                    // We can't reliably go from the closest street to an
-                    // interpolation line because the closest interpolation
-                    // may have a different street segments as a parent.
-                    // Therefore allow an interpolation line to take precedence
-                    // even when the street is closer.
-                    $fDistance = $iRankAddress < 28 ? 0.001 : $aPlace['distance'];
-                }
-
-                $aHouse = $this->lookupInterpolation($sPointSQL, $fDistance);
-                Debug::printVar('Interpolation result', $aPlace);
-
-                if ($aHouse) {
-                    $oResult = new Result($aHouse['place_id'], Result::TABLE_OSMLINE);
-                    $iRndNum = max(0, round($aHouse['fhnr'] / $aHouse['step']) * $aHouse['step']);
-                    $oResult->iHouseNumber = $aHouse['startnumber'] + $iRndNum;
-                    if ($oResult->iHouseNumber > $aHouse['endnumber']) {
-                        $oResult->iHouseNumber = $aHouse['endnumber'];
-                    }
-                    $aPlace = $aHouse;
-                }
-            }
-
-            if (!$aPlace) {
-                // if no POI or street is found ...
-                $oResult = $this->lookupLargeArea($sPointSQL, 25);
-            }
-        } else {
-            // lower than street level ($iMaxRank < 26 )
-            $oResult = $this->lookupLargeArea($sPointSQL, $this->iMaxRank);
-        }
-
-        Debug::printVar('Final result', $oResult);
-        return $oResult;
-    }
-}
diff --git a/lib-php/SearchContext.php b/lib-php/SearchContext.php
deleted file mode 100644 (file)
index 3223b5c..0000000
+++ /dev/null
@@ -1,319 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim;
-
-require_once(CONST_LibDir.'/lib.php');
-
-
-/**
- * Collection of search constraints that are independent of the
- * actual interpretation of the search query.
- *
- * The search context is shared between all SearchDescriptions. This
- * object mainly serves as context provider for the database queries.
- * Therefore most data is directly cached as SQL statements.
- */
-class SearchContext
-{
-    /// Search radius around a given Near reference point.
-    private $fNearRadius = false;
-    /// True if search must be restricted to viewbox only.
-    public $bViewboxBounded = false;
-
-    /// Reference point for search (as SQL).
-    public $sqlNear = '';
-    /// Viewbox selected for search (as SQL).
-    public $sqlViewboxSmall = '';
-    /// Viewbox with a larger buffer around (as SQL).
-    public $sqlViewboxLarge = '';
-    /// Reference along a route (as SQL).
-    public $sqlViewboxCentre = '';
-    /// List of countries to restrict search to (as array).
-    public $aCountryList = null;
-    /// List of countries to restrict search to (as SQL).
-    public $sqlCountryList = '';
-    /// List of place IDs to exclude (as SQL).
-    private $sqlExcludeList = '';
-    /// Subset of word ids of full words in the query.
-    private $aFullNameWords = array();
-
-    public function setFullNameWords($aWordList)
-    {
-        $this->aFullNameWords = $aWordList;
-    }
-
-    public function getFullNameTerms()
-    {
-        return $this->aFullNameWords;
-    }
-
-    /**
-     * Check if a reference point is defined.
-     *
-     * @return bool True if a reference point is defined.
-     */
-    public function hasNearPoint()
-    {
-        return $this->fNearRadius !== false;
-    }
-
-    /**
-     * Get radius around reference point.
-     *
-     * @return float Search radius around reference point.
-     */
-    public function nearRadius()
-    {
-        return $this->fNearRadius;
-    }
-
-    /**
-     * Set search reference point in WGS84.
-     *
-     * If set, then only places around this point will be taken into account.
-     *
-     * @param float $fLat    Latitude of point.
-     * @param float $fLon    Longitude of point.
-     * @param float $fRadius Search radius around point.
-     *
-     * @return void
-     */
-    public function setNearPoint($fLat, $fLon, $fRadius = 0.1)
-    {
-        $this->fNearRadius = $fRadius;
-        $this->sqlNear = 'ST_SetSRID(ST_Point('.$fLon.','.$fLat.'),4326)';
-    }
-
-    /**
-     * Check if the search is geographically restricted.
-     *
-     * Searches are restricted if a reference point is given or if
-     * a bounded viewbox is set.
-     *
-     * @return bool True, if the search is geographically bounded.
-     */
-    public function isBoundedSearch()
-    {
-        return $this->hasNearPoint() || ($this->sqlViewboxSmall && $this->bViewboxBounded);
-    }
-
-    /**
-     * Set rectangular viewbox.
-     *
-     * The viewbox may be bounded which means that no search results
-     * must be outside the viewbox.
-     *
-     * @param float[4] $aViewBox Coordinates of the viewbox.
-     * @param bool     $bBounded True if the viewbox is bounded.
-     *
-     * @return void
-     */
-    public function setViewboxFromBox(&$aViewBox, $bBounded)
-    {
-        $this->bViewboxBounded = $bBounded;
-        $this->sqlViewboxCentre = '';
-
-        $this->sqlViewboxSmall = sprintf(
-            'ST_SetSRID(ST_MakeBox2D(ST_Point(%F,%F),ST_Point(%F,%F)),4326)',
-            $aViewBox[0],
-            $aViewBox[1],
-            $aViewBox[2],
-            $aViewBox[3]
-        );
-
-        $fHeight = abs($aViewBox[0] - $aViewBox[2]);
-        $fWidth = abs($aViewBox[1] - $aViewBox[3]);
-
-        $this->sqlViewboxLarge = sprintf(
-            'ST_SetSRID(ST_MakeBox2D(ST_Point(%F,%F),ST_Point(%F,%F)),4326)',
-            max($aViewBox[0], $aViewBox[2]) + $fHeight,
-            max($aViewBox[1], $aViewBox[3]) + $fWidth,
-            min($aViewBox[0], $aViewBox[2]) - $fHeight,
-            min($aViewBox[1], $aViewBox[3]) - $fWidth
-        );
-    }
-
-    /**
-     * Set viewbox along a route.
-     *
-     * The viewbox may be bounded which means that no search results
-     * must be outside the viewbox.
-     *
-     * @param object   $oDB          Nominatim::DB instance to use for computing the box.
-     * @param string[] $aRoutePoints List of x,y coordinates along a route.
-     * @param float    $fRouteWidth  Buffer around the route to use.
-     * @param bool     $bBounded     True if the viewbox bounded.
-     *
-     * @return void
-     */
-    public function setViewboxFromRoute(&$oDB, $aRoutePoints, $fRouteWidth, $bBounded)
-    {
-        $this->bViewboxBounded = $bBounded;
-        $this->sqlViewboxCentre = "ST_SetSRID('LINESTRING(";
-        $sSep = '';
-        foreach ($aRoutePoints as $aPoint) {
-            $fPoint = (float)$aPoint;
-            $this->sqlViewboxCentre .= $sSep.$fPoint;
-            $sSep = ($sSep == ' ') ? ',' : ' ';
-        }
-        $this->sqlViewboxCentre .= ")'::geometry,4326)";
-
-        $sSQL = 'ST_BUFFER('.$this->sqlViewboxCentre.','.($fRouteWidth/69).')';
-        $sGeom = $oDB->getOne('select '.$sSQL, null, 'Could not get small viewbox');
-        $this->sqlViewboxSmall = "'".$sGeom."'::geometry";
-
-        $sSQL = 'ST_BUFFER('.$this->sqlViewboxCentre.','.($fRouteWidth/30).')';
-        $sGeom = $oDB->getOne('select '.$sSQL, null, 'Could not get large viewbox');
-        $this->sqlViewboxLarge = "'".$sGeom."'::geometry";
-    }
-
-    /**
-     * Set list of excluded place IDs.
-     *
-     * @param integer[] $aExcluded List of IDs.
-     *
-     * @return void
-     */
-    public function setExcludeList($aExcluded)
-    {
-        $this->sqlExcludeList = ' not in ('.join(',', $aExcluded).')';
-    }
-
-    /**
-     * Set list of countries to restrict search to.
-     *
-     * @param string[] $aCountries List of two-letter lower-case country codes.
-     *
-     * @return void
-     */
-    public function setCountryList($aCountries)
-    {
-        $this->sqlCountryList = '('.join(',', array_map('addQuotes', $aCountries)).')';
-        $this->aCountryList = $aCountries;
-    }
-
-    /**
-     * Extract a reference point from a query string.
-     *
-     * @param string $sQuery Query to scan.
-     *
-     * @return string The remaining query string.
-     */
-    public function setNearPointFromQuery($sQuery)
-    {
-        $aResult = parseLatLon($sQuery);
-
-        if ($aResult !== false
-            && $aResult[1] <= 90.1
-            && $aResult[1] >= -90.1
-            && $aResult[2] <= 180.1
-            && $aResult[2] >= -180.1
-        ) {
-            $this->setNearPoint($aResult[1], $aResult[2]);
-            $sQuery = trim(str_replace($aResult[0], ' ', $sQuery));
-        }
-
-        return $sQuery;
-    }
-
-    /**
-     * Get an SQL snippet for computing the distance from the reference point.
-     *
-     * @param string $sObj SQL variable name to compute the distance from.
-     *
-     * @return string An SQL string.
-     */
-    public function distanceSQL($sObj)
-    {
-        return 'ST_Distance('.$this->sqlNear.", $sObj)";
-    }
-
-    /**
-     * Get an SQL snippet for checking if something is within range of the
-     * reference point.
-     *
-     * @param string $sObj SQL variable name to compute if it is within range.
-     *
-     * @return string An SQL string.
-     */
-    public function withinSQL($sObj)
-    {
-        return sprintf('ST_DWithin(%s, %s, %F)', $sObj, $this->sqlNear, $this->fNearRadius);
-    }
-
-    /**
-     * Get an SQL snippet of the importance factor of the viewbox.
-     *
-     * The importance factor is computed by checking if an object is within
-     * the viewbox and/or the extended version of the viewbox.
-     *
-     * @param string $sObj SQL variable name of object to weight the importance
-     *
-     * @return string SQL snippet of the factor with a leading multiply sign.
-     */
-    public function viewboxImportanceSQL($sObj)
-    {
-        $sSQL = '';
-
-        if ($this->sqlViewboxSmall) {
-            $sSQL = " * CASE WHEN ST_Contains($this->sqlViewboxSmall, $sObj) THEN 1 ELSE 0.5 END";
-        }
-        if ($this->sqlViewboxLarge) {
-            $sSQL = " * CASE WHEN ST_Contains($this->sqlViewboxLarge, $sObj) THEN 1 ELSE 0.5 END";
-        }
-
-        return $sSQL;
-    }
-
-    /**
-     * SQL snippet checking if a place ID should be excluded.
-     *
-     * @param string $sVariable SQL variable name of place ID to check,
-     *                          potentially prefixed with more SQL.
-     *
-     * @return string SQL snippet.
-     */
-    public function excludeSQL($sVariable)
-    {
-        if ($this->sqlExcludeList) {
-            return $sVariable.$this->sqlExcludeList;
-        }
-
-        return '';
-    }
-
-    /**
-     * Check if the given country is covered by the search context.
-     *
-     * @param string $sCountryCode  Country code of the country to check.
-     *
-     * @return True, if no country code restrictions are set or the
-     *         country is included in the country list.
-     */
-    public function isCountryApplicable($sCountryCode)
-    {
-        return $this->aCountryList === null || in_array($sCountryCode, $this->aCountryList);
-    }
-
-    public function debugInfo()
-    {
-        return array(
-                'Near radius' => $this->fNearRadius,
-                'Near point (SQL)' => $this->sqlNear,
-                'Bounded viewbox' => $this->bViewboxBounded,
-                'Viewbox (SQL, small)' => $this->sqlViewboxSmall,
-                'Viewbox (SQL, large)' => $this->sqlViewboxLarge,
-                'Viewbox (SQL, centre)' => $this->sqlViewboxCentre,
-                'Countries (SQL)' => $this->sqlCountryList,
-                'Excluded IDs (SQL)' => $this->sqlExcludeList
-               );
-    }
-}
diff --git a/lib-php/SearchDescription.php b/lib-php/SearchDescription.php
deleted file mode 100644 (file)
index 5d2caf0..0000000
+++ /dev/null
@@ -1,985 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim;
-
-require_once(CONST_LibDir.'/SpecialSearchOperator.php');
-require_once(CONST_LibDir.'/SearchContext.php');
-require_once(CONST_LibDir.'/Result.php');
-
-/**
- * Description of a single interpretation of a search query.
- */
-class SearchDescription
-{
-    /// Ranking how well the description fits the query.
-    private $iSearchRank = 0;
-    /// Country code of country the result must belong to.
-    private $sCountryCode = '';
-    /// List of word ids making up the name of the object.
-    private $aName = array();
-    /// True if the name is rare enough to force index use on name.
-    private $bRareName = false;
-    /// True if the name requires to be accompanied by address terms.
-    private $bNameNeedsAddress = false;
-    /// List of word ids making up the address of the object.
-    private $aAddress = array();
-    /// List of word ids that appear in the name but should be ignored.
-    private $aNameNonSearch = array();
-    /// List of word ids that appear in the address but should be ignored.
-    private $aAddressNonSearch = array();
-    /// Kind of search for special searches, see Nominatim::Operator.
-    private $iOperator = Operator::NONE;
-    /// Class of special feature to search for.
-    private $sClass = '';
-    /// Type of special feature to search for.
-    private $sType = '';
-    /// Housenumber of the object.
-    private $sHouseNumber = '';
-    /// Postcode for the object.
-    private $sPostcode = '';
-    /// Global search constraints.
-    private $oContext;
-
-    // Temporary values used while creating the search description.
-
-    /// Index of phrase currently processed.
-    private $iNamePhrase = -1;
-
-    /**
-     * Create an empty search description.
-     *
-     * @param object $oContext Global context to use. Will be inherited by
-     *                         all derived search objects.
-     */
-    public function __construct($oContext)
-    {
-        $this->oContext = $oContext;
-    }
-
-    /**
-     * Get current search rank.
-     *
-     * The higher the search rank the lower the likelihood that the
-     * search is a correct interpretation of the search query.
-     *
-     * @return integer Search rank.
-     */
-    public function getRank()
-    {
-        return $this->iSearchRank;
-    }
-
-    /**
-     * Extract key/value pairs from a query.
-     *
-     * Key/value pairs are recognised if they are of the form [<key>=<value>].
-     * If multiple terms of this kind are found then all terms are removed
-     * but only the first is used for search.
-     *
-     * @param string $sQuery Original query string.
-     *
-     * @return string The query string with the special search patterns removed.
-     */
-    public function extractKeyValuePairs($sQuery)
-    {
-        // Search for terms of kind [<key>=<value>].
-        preg_match_all(
-            '/\\[([\\w_]*)=([\\w_]*)\\]/',
-            $sQuery,
-            $aSpecialTermsRaw,
-            PREG_SET_ORDER
-        );
-
-        foreach ($aSpecialTermsRaw as $aTerm) {
-            $sQuery = str_replace($aTerm[0], ' ', $sQuery);
-            if (!$this->hasOperator()) {
-                $this->setPoiSearch(Operator::TYPE, $aTerm[1], $aTerm[2]);
-            }
-        }
-
-        return $sQuery;
-    }
-
-    /**
-     * Check if the combination of parameters is sensible.
-     *
-     * @return bool True, if the search looks valid.
-     */
-    public function isValidSearch()
-    {
-        if (empty($this->aName)) {
-            if ($this->sHouseNumber) {
-                return false;
-            }
-            if (!$this->sClass && !$this->sCountryCode) {
-                return false;
-            }
-        }
-        if ($this->bNameNeedsAddress && empty($this->aAddress)) {
-            return false;
-        }
-
-        return true;
-    }
-
-    /////////// Search building functions
-
-    /**
-     * Create a copy of this search description adding to search rank.
-     *
-     * @param integer $iTermCost  Cost to add to the current search rank.
-     *
-     * @return object Cloned search description.
-     */
-    public function clone($iTermCost)
-    {
-        $oSearch = clone $this;
-        $oSearch->iSearchRank += $iTermCost;
-
-        return $oSearch;
-    }
-
-    /**
-     * Check if the search currently includes a name.
-     *
-     * @param bool bIncludeNonNames  If true stop-word tokens are taken into
-     *                               account, too.
-     *
-     * @return bool True, if search has a name.
-     */
-    public function hasName($bIncludeNonNames = false)
-    {
-        return !empty($this->aName)
-               || (!empty($this->aNameNonSearch) && $bIncludeNonNames);
-    }
-
-    /**
-     * Check if the search currently includes an address term.
-     *
-     * @return bool True, if any address term is included, including stop-word
-     *              terms.
-     */
-    public function hasAddress()
-    {
-        return !empty($this->aAddress) || !empty($this->aAddressNonSearch);
-    }
-
-    /**
-     * Check if a country restriction is currently included in the search.
-     *
-     * @return bool True, if a country restriction is set.
-     */
-    public function hasCountry()
-    {
-        return $this->sCountryCode !== '';
-    }
-
-    /**
-     * Check if a postcode is currently included in the search.
-     *
-     * @return bool True, if a postcode is set.
-     */
-    public function hasPostcode()
-    {
-        return $this->sPostcode !== '';
-    }
-
-    /**
-     * Check if a house number is set for the search.
-     *
-     * @return bool True, if a house number is set.
-     */
-    public function hasHousenumber()
-    {
-        return $this->sHouseNumber !== '';
-    }
-
-    /**
-     * Check if a special type of place is requested.
-     *
-     * param integer iOperator  When set, check for the particular
-     *                          operator used for the special type.
-     *
-     * @return bool True, if speial type is requested or, if requested,
-     *              a special type with the given operator.
-     */
-    public function hasOperator($iOperator = null)
-    {
-        return $iOperator === null ? $this->iOperator != Operator::NONE : $this->iOperator == $iOperator;
-    }
-
-    /**
-     * Add the given token to the list of terms to search for in the address.
-     *
-     * @param integer iID       ID of term to add.
-     * @param bool bSearchable  Term should be used to search for result
-     *                          (i.e. term is not a stop word).
-     */
-    public function addAddressToken($iId, $bSearchable = true)
-    {
-        if ($bSearchable) {
-            $this->aAddress[$iId] = $iId;
-        } else {
-            $this->aAddressNonSearch[$iId] = $iId;
-        }
-    }
-
-    /**
-     * Add the given full-word token to the list of terms to search for in the
-     * name.
-     *
-     * @param integer iId    ID of term to add.
-     * @param bool bRareName  True if the term is infrequent enough to not
-     *                        require other constraints for efficient search.
-     */
-    public function addNameToken($iId, $bRareName)
-    {
-        $this->aName[$iId] = $iId;
-        $this->bRareName = $bRareName;
-        $this->bNameNeedsAddress = false;
-    }
-
-    /**
-     * Add the given partial token to the list of terms to search for in
-     * the name.
-     *
-     * @param integer iID            ID of term to add.
-     * @param bool bSearchable       Term should be used to search for result
-     *                               (i.e. term is not a stop word).
-     * @param bool bNeedsAddress     True if the term is too unspecific to be used
-     *                               in a stand-alone search without an address
-     *                               to narrow down the search.
-     * @param integer iPhraseNumber  Index of phrase, where the partial term
-     *                               appears.
-     */
-    public function addPartialNameToken($iId, $bSearchable, $bNeedsAddress, $iPhraseNumber)
-    {
-        if (empty($this->aName)) {
-            $this->bNameNeedsAddress = $bNeedsAddress;
-        } elseif ($bSearchable && count($this->aName) >= 2) {
-            $this->bNameNeedsAddress = false;
-        } else {
-            $this->bNameNeedsAddress &= $bNeedsAddress;
-        }
-        if ($bSearchable) {
-            $this->aName[$iId] = $iId;
-        } else {
-            $this->aNameNonSearch[$iId] = $iId;
-        }
-        $this->iNamePhrase = $iPhraseNumber;
-    }
-
-    /**
-     * Set country restriction for the search.
-     *
-     * @param string sCountryCode  Country code of country to restrict search to.
-     */
-    public function setCountry($sCountryCode)
-    {
-        $this->sCountryCode = $sCountryCode;
-        $this->iNamePhrase = -1;
-    }
-
-    /**
-     * Set postcode search constraint.
-     *
-     * @param string sPostcode  Postcode the result should have.
-     */
-    public function setPostcode($sPostcode)
-    {
-        $this->sPostcode = $sPostcode;
-        $this->iNamePhrase = -1;
-    }
-
-    /**
-     * Make this search a search for a postcode object.
-     *
-     * @param integer iId       Token Id for the postcode.
-     * @param string sPostcode  Postcode to look for.
-     */
-    public function setPostcodeAsName($iId, $sPostcode)
-    {
-        $this->iOperator = Operator::POSTCODE;
-        $this->aAddress = array_merge($this->aAddress, $this->aName);
-        $this->aName = array($iId => $sPostcode);
-        $this->bRareName = true;
-        $this->iNamePhrase = -1;
-    }
-
-    /**
-     * Set house number search cnstraint.
-     *
-     * @param string sNumber  House number the result should have.
-     */
-    public function setHousenumber($sNumber)
-    {
-        $this->sHouseNumber = $sNumber;
-        $this->iNamePhrase = -1;
-    }
-
-    /**
-     * Make this search a search for a house number.
-     *
-     * @param integer iId  Token Id for the house number.
-     */
-    public function setHousenumberAsName($iId)
-    {
-        $this->aAddress = array_merge($this->aAddress, $this->aName);
-        $this->bRareName = false;
-        $this->bNameNeedsAddress = true;
-        $this->aName = array($iId => $iId);
-        $this->iNamePhrase = -1;
-    }
-
-    /**
-     * Make this search a POI search.
-     *
-     * In a POI search, objects are not (only) searched by their name
-     * but also by the primary OSM key/value pair (class and type in Nominatim).
-     *
-     * @param integer $iOperator Type of POI search
-     * @param string  $sClass    Class (or OSM tag key) of POI.
-     * @param string  $sType     Type (or OSM tag value) of POI.
-     *
-     * @return void
-     */
-    public function setPoiSearch($iOperator, $sClass, $sType)
-    {
-        $this->iOperator = $iOperator;
-        $this->sClass = $sClass;
-        $this->sType = $sType;
-        $this->iNamePhrase = -1;
-    }
-
-    public function getNamePhrase()
-    {
-        return $this->iNamePhrase;
-    }
-
-    /**
-     * Get the global search context.
-     *
-     * @return object  Objects of global search constraints.
-     */
-    public function getContext()
-    {
-        return $this->oContext;
-    }
-
-    /////////// Query functions
-
-
-    /**
-     * Query database for places that match this search.
-     *
-     * @param object  $oDB      Nominatim::DB instance to use.
-     * @param integer $iMinRank Minimum address rank to restrict search to.
-     * @param integer $iMaxRank Maximum address rank to restrict search to.
-     * @param integer $iLimit   Maximum number of results.
-     *
-     * @return mixed[] An array with two fields: IDs contains the list of
-     *                 matching place IDs and houseNumber the houseNumber
-     *                 if applicable or -1 if not.
-     */
-    public function query(&$oDB, $iMinRank, $iMaxRank, $iLimit)
-    {
-        $aResults = array();
-
-        if ($this->sCountryCode
-            && empty($this->aName)
-            && !$this->iOperator
-            && !$this->sClass
-            && !$this->oContext->hasNearPoint()
-        ) {
-            // Just looking for a country - look it up
-            if (4 >= $iMinRank && 4 <= $iMaxRank) {
-                $aResults = $this->queryCountry($oDB);
-            }
-        } elseif (empty($this->aName) && empty($this->aAddress)) {
-            // Neither name nor address? Then we must be
-            // looking for a POI in a geographic area.
-            if ($this->oContext->isBoundedSearch()) {
-                $aResults = $this->queryNearbyPoi($oDB, $iLimit);
-            }
-        } elseif ($this->iOperator == Operator::POSTCODE) {
-            // looking for postcode
-            $aResults = $this->queryPostcode($oDB, $iLimit);
-        } else {
-            // Ordinary search:
-            // First search for places according to name and address.
-            $aResults = $this->queryNamedPlace(
-                $oDB,
-                $iMinRank,
-                $iMaxRank,
-                $iLimit
-            );
-
-            // finally get POIs if requested
-            if ($this->sClass && !empty($aResults)) {
-                $aResults = $this->queryPoiByOperator($oDB, $aResults, $iLimit);
-            }
-        }
-
-        Debug::printDebugTable('Place IDs', $aResults);
-
-        if (!empty($aResults) && $this->sPostcode) {
-            $sPlaceIds = Result::joinIdsByTable($aResults, Result::TABLE_PLACEX);
-            if ($sPlaceIds) {
-                $sSQL = 'SELECT place_id FROM placex';
-                $sSQL .= ' WHERE place_id in ('.$sPlaceIds.')';
-                $sSQL .= " AND postcode != '".$this->sPostcode."'";
-                Debug::printSQL($sSQL);
-                $aFilteredPlaceIDs = $oDB->getCol($sSQL);
-                if ($aFilteredPlaceIDs) {
-                    foreach ($aFilteredPlaceIDs as $iPlaceId) {
-                        $aResults[$iPlaceId]->iResultRank++;
-                    }
-                }
-            }
-        }
-
-        return $aResults;
-    }
-
-
-    private function queryCountry(&$oDB)
-    {
-        $sSQL = 'SELECT place_id FROM placex ';
-        $sSQL .= "WHERE country_code='".$this->sCountryCode."'";
-        $sSQL .= ' AND rank_search = 4';
-        if ($this->oContext->bViewboxBounded) {
-            $sSQL .= ' AND ST_Intersects('.$this->oContext->sqlViewboxSmall.', geometry)';
-        }
-        $sSQL .= ' ORDER BY st_area(geometry) DESC LIMIT 1';
-
-        Debug::printSQL($sSQL);
-
-        $iPlaceId = $oDB->getOne($sSQL);
-
-        $aResults = array();
-        if ($iPlaceId) {
-            $aResults[$iPlaceId] = new Result($iPlaceId);
-        }
-
-        return $aResults;
-    }
-
-    private function queryNearbyPoi(&$oDB, $iLimit)
-    {
-        if (!$this->sClass) {
-            return array();
-        }
-
-        $aDBResults = array();
-        $sPoiTable = $this->poiTable();
-
-        if ($oDB->tableExists($sPoiTable)) {
-            $sSQL = 'SELECT place_id FROM '.$sPoiTable.' ct';
-            if ($this->oContext->sqlCountryList) {
-                $sSQL .= ' JOIN placex USING (place_id)';
-            }
-            if ($this->oContext->hasNearPoint()) {
-                $sSQL .= ' WHERE '.$this->oContext->withinSQL('ct.centroid');
-            } elseif ($this->oContext->bViewboxBounded) {
-                $sSQL .= ' WHERE ST_Contains('.$this->oContext->sqlViewboxSmall.', ct.centroid)';
-            }
-            if ($this->oContext->sqlCountryList) {
-                $sSQL .= ' AND country_code in '.$this->oContext->sqlCountryList;
-            }
-            $sSQL .= $this->oContext->excludeSQL(' AND place_id');
-            if ($this->oContext->sqlViewboxCentre) {
-                $sSQL .= ' ORDER BY ST_Distance(';
-                $sSQL .= $this->oContext->sqlViewboxCentre.', ct.centroid) ASC';
-            } elseif ($this->oContext->hasNearPoint()) {
-                $sSQL .= ' ORDER BY '.$this->oContext->distanceSQL('ct.centroid').' ASC';
-            }
-            $sSQL .= " LIMIT $iLimit";
-            Debug::printSQL($sSQL);
-            $aDBResults = $oDB->getCol($sSQL);
-        }
-
-        if ($this->oContext->hasNearPoint()) {
-            $sSQL = 'SELECT place_id FROM placex WHERE ';
-            $sSQL .= 'class = :class and type = :type';
-            $sSQL .= ' AND '.$this->oContext->withinSQL('geometry');
-            $sSQL .= ' AND linked_place_id is null';
-            if ($this->oContext->sqlCountryList) {
-                $sSQL .= ' AND country_code in '.$this->oContext->sqlCountryList;
-            }
-            $sSQL .= ' ORDER BY '.$this->oContext->distanceSQL('centroid').' ASC';
-            $sSQL .= " LIMIT $iLimit";
-            Debug::printSQL($sSQL);
-            $aDBResults = $oDB->getCol(
-                $sSQL,
-                array(':class' => $this->sClass, ':type' => $this->sType)
-            );
-        }
-
-        $aResults = array();
-        foreach ($aDBResults as $iPlaceId) {
-            $aResults[$iPlaceId] = new Result($iPlaceId);
-        }
-
-        return $aResults;
-    }
-
-    private function queryPostcode(&$oDB, $iLimit)
-    {
-        $sSQL = 'SELECT p.place_id FROM location_postcode p ';
-
-        if (!empty($this->aAddress)) {
-            $sSQL .= ', search_name s ';
-            $sSQL .= 'WHERE s.place_id = p.parent_place_id ';
-            $sSQL .= 'AND array_cat(s.nameaddress_vector, s.name_vector)';
-            $sSQL .= '      @> '.$oDB->getArraySQL($this->aAddress).' AND ';
-        } else {
-            $sSQL .= 'WHERE ';
-        }
-
-        $sSQL .= "p.postcode = '".reset($this->aName)."'";
-        $sSQL .= $this->countryCodeSQL(' AND p.country_code');
-        if ($this->oContext->bViewboxBounded) {
-            $sSQL .= ' AND ST_Intersects('.$this->oContext->sqlViewboxSmall.', geometry)';
-        }
-        $sSQL .= $this->oContext->excludeSQL(' AND p.place_id');
-        $sSQL .= " LIMIT $iLimit";
-
-        Debug::printSQL($sSQL);
-
-        $aResults = array();
-        foreach ($oDB->getCol($sSQL) as $iPlaceId) {
-            $aResults[$iPlaceId] = new Result($iPlaceId, Result::TABLE_POSTCODE);
-        }
-
-        return $aResults;
-    }
-
-    private function queryNamedPlace(&$oDB, $iMinAddressRank, $iMaxAddressRank, $iLimit)
-    {
-        $aTerms = array();
-        $aOrder = array();
-
-        if (!empty($this->aName)) {
-            $aTerms[] = 'name_vector @> '.$oDB->getArraySQL($this->aName);
-        }
-        if (!empty($this->aAddress)) {
-            // For infrequent name terms disable index usage for address
-            if ($this->bRareName) {
-                $aTerms[] = 'array_cat(nameaddress_vector,ARRAY[]::integer[]) @> '.$oDB->getArraySQL($this->aAddress);
-            } else {
-                $aTerms[] = 'nameaddress_vector @> '.$oDB->getArraySQL($this->aAddress);
-            }
-        }
-
-        $sCountryTerm = $this->countryCodeSQL('country_code');
-        if ($sCountryTerm) {
-            $aTerms[] = $sCountryTerm;
-        }
-
-        if ($this->sHouseNumber) {
-            $aTerms[] = 'address_rank between 16 and 30';
-        } elseif (!$this->sClass || $this->iOperator == Operator::NAME) {
-            if ($iMinAddressRank > 0) {
-                $aTerms[] = "((address_rank between $iMinAddressRank and $iMaxAddressRank) or (search_rank between $iMinAddressRank and $iMaxAddressRank))";
-            }
-        }
-
-        if ($this->oContext->hasNearPoint()) {
-            $aTerms[] = $this->oContext->withinSQL('centroid');
-            $aOrder[] = $this->oContext->distanceSQL('centroid');
-        } elseif ($this->sPostcode) {
-            if (empty($this->aAddress)) {
-                $aTerms[] = "EXISTS(SELECT place_id FROM location_postcode p WHERE p.postcode = '".$this->sPostcode."' AND ST_DWithin(search_name.centroid, p.geometry, 0.12))";
-            } else {
-                $aOrder[] = "(SELECT min(ST_Distance(search_name.centroid, p.geometry)) FROM location_postcode p WHERE p.postcode = '".$this->sPostcode."')";
-            }
-        }
-
-        $sExcludeSQL = $this->oContext->excludeSQL('place_id');
-        if ($sExcludeSQL) {
-            $aTerms[] = $sExcludeSQL;
-        }
-
-        if ($this->oContext->bViewboxBounded) {
-            $aTerms[] = 'centroid && '.$this->oContext->sqlViewboxSmall;
-        }
-
-        if ($this->sHouseNumber) {
-            $sImportanceSQL = '- abs(26 - address_rank) + 3';
-        } else {
-            $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";
-
-        $aFullNameAddress = $this->oContext->getFullNameTerms();
-        if (!empty($aFullNameAddress)) {
-            $sExactMatchSQL = ' ( ';
-            $sExactMatchSQL .= ' SELECT count(*) FROM ( ';
-            $sExactMatchSQL .= '  SELECT unnest('.$oDB->getArraySQL($aFullNameAddress).')';
-            $sExactMatchSQL .= '    INTERSECT ';
-            $sExactMatchSQL .= '  SELECT unnest(nameaddress_vector)';
-            $sExactMatchSQL .= ' ) s';
-            $sExactMatchSQL .= ') as exactmatch';
-            $aOrder[] = 'exactmatch DESC';
-        } else {
-            $sExactMatchSQL = '0::int as exactmatch';
-        }
-
-        if (empty($aTerms)) {
-            return array();
-        }
-
-        if ($this->hasHousenumber()) {
-            $sHouseNumberRegex = $oDB->getDBQuoted('\\\\m'.$this->sHouseNumber.'\\\\M');
-
-            // Housenumbers on streets and places.
-            $sPlacexSql = 'SELECT array_agg(place_id) FROM placex';
-            $sPlacexSql .= ' WHERE parent_place_id = sin.place_id AND sin.address_rank < 30';
-            $sPlacexSql .= $this->oContext->excludeSQL(' AND place_id');
-            $sPlacexSql .= '       and housenumber ~* E'.$sHouseNumberRegex;
-
-            // Interpolations on streets and places.
-            $sInterpolSql = 'null';
-            $sTigerSql = 'null';
-            if (preg_match('/^[0-9]+$/', $this->sHouseNumber)) {
-                $sIpolHnr = 'WHERE parent_place_id = sin.place_id ';
-                $sIpolHnr .= '  AND startnumber is not NULL AND sin.address_rank < 30';
-                $sIpolHnr .= '  AND '.$this->sHouseNumber.' between startnumber and endnumber';
-                $sIpolHnr .= '  AND ('.$this->sHouseNumber.' - startnumber) % step = 0';
-
-                $sInterpolSql = 'SELECT array_agg(place_id) FROM location_property_osmline '.$sIpolHnr;
-                if (CONST_Use_US_Tiger_Data) {
-                    $sTigerSql = 'SELECT array_agg(place_id) FROM location_property_tiger '.$sIpolHnr;
-                    $sTigerSql .= "      and sin.country_code = 'us'";
-                }
-            }
-
-            if ($this->sClass) {
-                $iLimit = 40;
-            }
-
-            $sSelfHnr = 'SELECT * FROM placex WHERE place_id = search_name.place_id';
-            $sSelfHnr .= '    AND housenumber ~* E'.$sHouseNumberRegex;
-
-            $aTerms[] = '(address_rank < 30 or exists('.$sSelfHnr.'))';
-
-
-            $sSQL = 'SELECT sin.*, ';
-            $sSQL .=        '('.$sPlacexSql.') as placex_hnr, ';
-            $sSQL .=        '('.$sInterpolSql.') as interpol_hnr, ';
-            $sSQL .=        '('.$sTigerSql.') as tiger_hnr ';
-            $sSQL .= ' FROM (';
-            $sSQL .= '    SELECT place_id, address_rank, country_code,'.$sExactMatchSQL.',';
-            $sSQL .= '            CASE WHEN importance = 0 OR importance IS NULL';
-            $sSQL .= '               THEN 0.75001-(search_rank::float/40) ELSE importance END as importance';
-            $sSQL .= '     FROM search_name';
-            $sSQL .= '     WHERE '.join(' and ', $aTerms);
-            $sSQL .= '     ORDER BY '.join(', ', $aOrder);
-            $sSQL .= '     LIMIT 40000';
-            $sSQL .= ') as sin';
-            $sSQL .= ' ORDER BY address_rank = 30 desc, placex_hnr, interpol_hnr, tiger_hnr,';
-            $sSQL .= '          importance';
-            $sSQL .= ' LIMIT '.$iLimit;
-        } else {
-            if ($this->sClass) {
-                $iLimit = 40;
-            }
-
-            $sSQL = 'SELECT place_id, address_rank, '.$sExactMatchSQL;
-            $sSQL .= ' FROM search_name';
-            $sSQL .= ' WHERE '.join(' and ', $aTerms);
-            $sSQL .= ' ORDER BY '.join(', ', $aOrder);
-            $sSQL .= ' LIMIT '.$iLimit;
-        }
-
-        Debug::printSQL($sSQL);
-
-        $aDBResults = $oDB->getAll($sSQL, null, 'Could not get places for search terms.');
-
-        $aResults = array();
-
-        foreach ($aDBResults as $aResult) {
-            $oResult = new Result($aResult['place_id']);
-            $oResult->iExactMatches = $aResult['exactmatch'];
-            $oResult->iAddressRank = $aResult['address_rank'];
-
-            $bNeedResult = true;
-            if ($this->hasHousenumber() && $aResult['address_rank'] < 30) {
-                if ($aResult['placex_hnr']) {
-                    foreach (explode(',', substr($aResult['placex_hnr'], 1, -1)) as $sPlaceID) {
-                        $iPlaceID = intval($sPlaceID);
-                        $oHnrResult = new Result($iPlaceID);
-                        $oHnrResult->iExactMatches = $aResult['exactmatch'];
-                        $oHnrResult->iAddressRank = 30;
-                        $aResults[$iPlaceID] = $oHnrResult;
-                        $bNeedResult = false;
-                    }
-                }
-                if ($aResult['interpol_hnr']) {
-                    foreach (explode(',', substr($aResult['interpol_hnr'], 1, -1)) as $sPlaceID) {
-                        $iPlaceID = intval($sPlaceID);
-                        $oHnrResult = new Result($iPlaceID, Result::TABLE_OSMLINE);
-                        $oHnrResult->iExactMatches = $aResult['exactmatch'];
-                        $oHnrResult->iAddressRank = 30;
-                        $oHnrResult->iHouseNumber = intval($this->sHouseNumber);
-                        $aResults[$iPlaceID] = $oHnrResult;
-                        $bNeedResult = false;
-                    }
-                }
-                if ($aResult['tiger_hnr']) {
-                    foreach (explode(',', substr($aResult['tiger_hnr'], 1, -1)) as $sPlaceID) {
-                        $iPlaceID = intval($sPlaceID);
-                        $oHnrResult = new Result($iPlaceID, Result::TABLE_TIGER);
-                        $oHnrResult->iExactMatches = $aResult['exactmatch'];
-                        $oHnrResult->iAddressRank = 30;
-                        $oHnrResult->iHouseNumber = intval($this->sHouseNumber);
-                        $aResults[$iPlaceID] = $oHnrResult;
-                        $bNeedResult = false;
-                    }
-                }
-
-                if ($aResult['address_rank'] < 26) {
-                    $oResult->iResultRank += 2;
-                } else {
-                    $oResult->iResultRank++;
-                }
-            }
-
-            if ($bNeedResult) {
-                $aResults[$aResult['place_id']] = $oResult;
-            }
-        }
-
-        return $aResults;
-    }
-
-
-    private function queryPoiByOperator(&$oDB, $aParentIDs, $iLimit)
-    {
-        $aResults = array();
-        $sPlaceIDs = Result::joinIdsByTable($aParentIDs, Result::TABLE_PLACEX);
-
-        if (!$sPlaceIDs) {
-            return $aResults;
-        }
-
-        if ($this->iOperator == Operator::TYPE || $this->iOperator == Operator::NAME) {
-            // If they were searching for a named class (i.e. 'Kings Head pub')
-            // then we might have an extra match
-            $sSQL = 'SELECT place_id FROM placex ';
-            $sSQL .= " WHERE place_id in ($sPlaceIDs)";
-            $sSQL .= "   AND class='".$this->sClass."' ";
-            $sSQL .= "   AND type='".$this->sType."'";
-            $sSQL .= '   AND linked_place_id is null';
-            $sSQL .= $this->oContext->excludeSQL(' AND place_id');
-            $sSQL .= ' ORDER BY rank_search ASC ';
-            $sSQL .= " LIMIT $iLimit";
-
-            Debug::printSQL($sSQL);
-
-            foreach ($oDB->getCol($sSQL) as $iPlaceId) {
-                $aResults[$iPlaceId] = new Result($iPlaceId);
-            }
-        }
-
-        // NEAR and IN are handled the same
-        if ($this->iOperator == Operator::TYPE || $this->iOperator == Operator::NEAR) {
-            $sClassTable = $this->poiTable();
-            $bCacheTable = $oDB->tableExists($sClassTable);
-
-            $sSQL = "SELECT min(rank_search) FROM placex WHERE place_id in ($sPlaceIDs)";
-            Debug::printSQL($sSQL);
-            $iMaxRank = (int) $oDB->getOne($sSQL);
-
-            // For state / country level searches the normal radius search doesn't work very well
-            $sPlaceGeom = false;
-            if ($iMaxRank < 9 && $bCacheTable) {
-                // Try and get a polygon to search in instead
-                $sSQL = 'SELECT geometry FROM placex';
-                $sSQL .= " WHERE place_id in ($sPlaceIDs)";
-                $sSQL .= "   AND rank_search < $iMaxRank + 5";
-                $sSQL .= '   AND ST_Area(Box2d(geometry)) < 20';
-                $sSQL .= "   AND ST_GeometryType(geometry) in ('ST_Polygon','ST_MultiPolygon')";
-                $sSQL .= ' ORDER BY rank_search ASC ';
-                $sSQL .= ' LIMIT 1';
-                Debug::printSQL($sSQL);
-                $sPlaceGeom = $oDB->getOne($sSQL);
-            }
-
-            if ($sPlaceGeom) {
-                $sPlaceIDs = false;
-            } else {
-                $iMaxRank += 5;
-                $sSQL = 'SELECT place_id FROM placex';
-                $sSQL .= " WHERE place_id in ($sPlaceIDs) and rank_search < $iMaxRank";
-                Debug::printSQL($sSQL);
-                $aPlaceIDs = $oDB->getCol($sSQL);
-                $sPlaceIDs = join(',', $aPlaceIDs);
-            }
-
-            if ($sPlaceIDs || $sPlaceGeom) {
-                $fRange = 0.01;
-                if ($bCacheTable) {
-                    // More efficient - can make the range bigger
-                    $fRange = 0.05;
-
-                    $sOrderBySQL = '';
-                    if ($this->oContext->hasNearPoint()) {
-                        $sOrderBySQL = $this->oContext->distanceSQL('l.centroid');
-                    } elseif ($sPlaceIDs) {
-                        $sOrderBySQL = 'ST_Distance(l.centroid, f.geometry)';
-                    } elseif ($sPlaceGeom) {
-                        $sOrderBySQL = "ST_Distance(st_centroid('".$sPlaceGeom."'), l.centroid)";
-                    }
-
-                    $sSQL = 'SELECT distinct i.place_id';
-                    if ($sOrderBySQL) {
-                        $sSQL .= ', i.order_term';
-                    }
-                    $sSQL .= ' from (SELECT l.place_id';
-                    if ($sOrderBySQL) {
-                        $sSQL .= ','.$sOrderBySQL.' as order_term';
-                    }
-                    $sSQL .= ' from '.$sClassTable.' as l';
-
-                    if ($sPlaceIDs) {
-                        $sSQL .= ',placex as f WHERE ';
-                        $sSQL .= "f.place_id in ($sPlaceIDs) ";
-                        $sSQL .= " AND ST_DWithin(l.centroid, f.centroid, $fRange)";
-                    } elseif ($sPlaceGeom) {
-                        $sSQL .= " WHERE ST_Contains('$sPlaceGeom', l.centroid)";
-                    }
-
-                    $sSQL .= $this->oContext->excludeSQL(' AND l.place_id');
-                    $sSQL .= 'limit 300) i ';
-                    if ($sOrderBySQL) {
-                        $sSQL .= 'order by order_term asc';
-                    }
-                    $sSQL .= " limit $iLimit";
-
-                    Debug::printSQL($sSQL);
-
-                    foreach ($oDB->getCol($sSQL) as $iPlaceId) {
-                        $aResults[$iPlaceId] = new Result($iPlaceId);
-                    }
-                } else {
-                    if ($this->oContext->hasNearPoint()) {
-                        $fRange = $this->oContext->nearRadius();
-                    }
-
-                    $sOrderBySQL = '';
-                    if ($this->oContext->hasNearPoint()) {
-                        $sOrderBySQL = $this->oContext->distanceSQL('l.geometry');
-                    } else {
-                        $sOrderBySQL = 'ST_Distance(l.geometry, f.geometry)';
-                    }
-
-                    $sSQL = 'SELECT distinct l.place_id';
-                    if ($sOrderBySQL) {
-                        $sSQL .= ','.$sOrderBySQL.' as orderterm';
-                    }
-                    $sSQL .= ' FROM placex as l, placex as f';
-                    $sSQL .= " WHERE f.place_id in ($sPlaceIDs)";
-                    $sSQL .= "  AND ST_DWithin(l.geometry, f.centroid, $fRange)";
-                    $sSQL .= "  AND l.class='".$this->sClass."'";
-                    $sSQL .= "  AND l.type='".$this->sType."'";
-                    $sSQL .= $this->oContext->excludeSQL(' AND l.place_id');
-                    if ($sOrderBySQL) {
-                        $sSQL .= 'ORDER BY orderterm ASC';
-                    }
-                    $sSQL .= " limit $iLimit";
-
-                    Debug::printSQL($sSQL);
-
-                    foreach ($oDB->getCol($sSQL) as $iPlaceId) {
-                        $aResults[$iPlaceId] = new Result($iPlaceId);
-                    }
-                }
-            }
-        }
-
-        return $aResults;
-    }
-
-    private function poiTable()
-    {
-        return 'place_classtype_'.$this->sClass.'_'.$this->sType;
-    }
-
-    private function countryCodeSQL($sVar)
-    {
-        if ($this->sCountryCode) {
-            return $sVar.' = \''.$this->sCountryCode."'";
-        }
-        if ($this->oContext->sqlCountryList) {
-            return $sVar.' in '.$this->oContext->sqlCountryList;
-        }
-
-        return '';
-    }
-
-    /////////// Sort functions
-
-
-    public static function bySearchRank($a, $b)
-    {
-        if ($a->iSearchRank == $b->iSearchRank) {
-            return $a->iOperator + strlen($a->sHouseNumber)
-                     - $b->iOperator - strlen($b->sHouseNumber);
-        }
-
-        return $a->iSearchRank < $b->iSearchRank ? -1 : 1;
-    }
-
-    //////////// Debugging functions
-
-
-    public function debugInfo()
-    {
-        return array(
-                'Search rank' => $this->iSearchRank,
-                'Country code' => $this->sCountryCode,
-                'Name terms' => $this->aName,
-                'Name terms (stop words)' => $this->aNameNonSearch,
-                'Address terms' => $this->aAddress,
-                'Address terms (stop words)' => $this->aAddressNonSearch,
-                'Address terms (full words)' => $this->aFullNameAddress ?? '',
-                'Special search' => $this->iOperator,
-                'Class' => $this->sClass,
-                'Type' => $this->sType,
-                'House number' => $this->sHouseNumber,
-                'Postcode' => $this->sPostcode
-               );
-    }
-
-    public function dumpAsHtmlTableRow(&$aWordIDs)
-    {
-        $kf = function ($k) use (&$aWordIDs) {
-            return $aWordIDs[$k] ?? '['.$k.']';
-        };
-
-        echo '<tr>';
-        echo "<td>$this->iSearchRank</td>";
-        echo '<td>'.join(', ', array_map($kf, $this->aName)).'</td>';
-        echo '<td>'.join(', ', array_map($kf, $this->aNameNonSearch)).'</td>';
-        echo '<td>'.join(', ', array_map($kf, $this->aAddress)).'</td>';
-        echo '<td>'.join(', ', array_map($kf, $this->aAddressNonSearch)).'</td>';
-        echo '<td>'.$this->sCountryCode.'</td>';
-        echo '<td>'.Operator::toString($this->iOperator).'</td>';
-        echo '<td>'.$this->sClass.'</td>';
-        echo '<td>'.$this->sType.'</td>';
-        echo '<td>'.$this->sPostcode.'</td>';
-        echo '<td>'.$this->sHouseNumber.'</td>';
-
-        echo '</tr>';
-    }
-}
diff --git a/lib-php/SearchPosition.php b/lib-php/SearchPosition.php
deleted file mode 100644 (file)
index aeeeb2c..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim;
-
-/**
- * Description of the position of a token within a query.
- */
-class SearchPosition
-{
-    private $sPhraseType;
-
-    private $iPhrase;
-    private $iNumPhrases;
-
-    private $iToken;
-    private $iNumTokens;
-
-
-    public function __construct($sPhraseType, $iPhrase, $iNumPhrases)
-    {
-        $this->sPhraseType = $sPhraseType;
-        $this->iPhrase = $iPhrase;
-        $this->iNumPhrases = $iNumPhrases;
-    }
-
-    public function setTokenPosition($iToken, $iNumTokens)
-    {
-        $this->iToken = $iToken;
-        $this->iNumTokens = $iNumTokens;
-    }
-
-    /**
-     * Check if the phrase can be of the given type.
-     *
-     * @param string  $sType  Type of phrse requested.
-     *
-     * @return True if the phrase is untyped or of the given type.
-     */
-    public function maybePhrase($sType)
-    {
-        return $this->sPhraseType == '' || $this->sPhraseType == $sType;
-    }
-
-    /**
-     * Check if the phrase is exactly of the given type.
-     *
-     * @param string  $sType  Type of phrse requested.
-     *
-     * @return True if the phrase of the given type.
-     */
-    public function isPhrase($sType)
-    {
-        return $this->sPhraseType == $sType;
-    }
-
-    /**
-     * Return true if the token is the very first in the query.
-     */
-    public function isFirstToken()
-    {
-        return $this->iPhrase == 0 && $this->iToken == 0;
-    }
-
-    /**
-     * Check if the token is the final one in the query.
-     */
-    public function isLastToken()
-    {
-        return $this->iToken + 1 == $this->iNumTokens && $this->iPhrase + 1 == $this->iNumPhrases;
-    }
-
-    /**
-     * Check if the current token is part of the first phrase in the query.
-     */
-    public function isFirstPhrase()
-    {
-        return $this->iPhrase == 0;
-    }
-
-    /**
-     * Get the phrase position in the query.
-     */
-    public function getPhrase()
-    {
-        return $this->iPhrase;
-    }
-}
diff --git a/lib-php/Shell.php b/lib-php/Shell.php
deleted file mode 100644 (file)
index 4be1323..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim;
-
-class Shell
-{
-    public function __construct($sBaseCmd, ...$aParams)
-    {
-        if (!$sBaseCmd) {
-            throw new \Exception('Command missing in new() call');
-        }
-        $this->baseCmd = $sBaseCmd;
-        $this->aParams = array();
-        $this->aEnv = null; // null = use the same environment as the current PHP process
-
-        $this->stdoutString = null;
-
-        foreach ($aParams as $sParam) {
-            $this->addParams($sParam);
-        }
-    }
-
-    public function addParams(...$aParams)
-    {
-        foreach ($aParams as $sParam) {
-            if (isset($sParam) && $sParam !== null && $sParam !== '') {
-                array_push($this->aParams, $sParam);
-            }
-        }
-        return $this;
-    }
-
-    public function addEnvPair($sKey, $sVal)
-    {
-        if (isset($sKey) && $sKey && isset($sVal)) {
-            if (!isset($this->aEnv)) {
-                $this->aEnv = $_ENV;
-            }
-            $this->aEnv = array_merge($this->aEnv, array($sKey => $sVal), $_ENV);
-        }
-        return $this;
-    }
-
-    public function escapedCmd()
-    {
-        $aEscaped = array_map(function ($sParam) {
-            return $this->escapeParam($sParam);
-        }, array_merge(array($this->baseCmd), $this->aParams));
-
-        return join(' ', $aEscaped);
-    }
-
-    public function run($bExitOnFail = false)
-    {
-        $sCmd = $this->escapedCmd();
-        // $aEnv does not need escaping, proc_open seems to handle it fine
-
-        $aFDs = array(
-                 0 => array('pipe', 'r'),
-                 1 => STDOUT,
-                 2 => STDERR
-                );
-        $aPipes = null;
-        $hProc = @proc_open($sCmd, $aFDs, $aPipes, null, $this->aEnv);
-        if (!is_resource($hProc)) {
-            throw new \Exception('Unable to run command: ' . $sCmd);
-        }
-
-        fclose($aPipes[0]); // no stdin
-
-        $iStat = proc_close($hProc);
-
-        if ($iStat != 0 && $bExitOnFail) {
-            exit($iStat);
-        }
-
-        return $iStat;
-    }
-
-    private function escapeParam($sParam)
-    {
-        return (preg_match('/^-*\w+$/', $sParam)) ? $sParam : escapeshellarg($sParam);
-    }
-}
diff --git a/lib-php/SimpleWordList.php b/lib-php/SimpleWordList.php
deleted file mode 100644 (file)
index 7009d37..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim;
-
-/**
- * A word list creator based on simple splitting by space.
- *
- * Creates possible permutations of split phrases by finding all combination
- * of splitting the phrase on space boundaries.
- */
-class SimpleWordList
-{
-    const MAX_WORDSET_LEN = 20;
-    const MAX_WORDSETS = 100;
-
-    // The phrase as a list of simple terms (without spaces).
-    private $aWords;
-
-    /**
-     * Create a new word list
-     *
-     * @param string sPhrase  Phrase to create the word list from. The phrase is
-     *                        expected to be normalised, so that there are no
-     *                        subsequent spaces.
-     */
-    public function __construct($sPhrase)
-    {
-        if (strlen($sPhrase) > 0) {
-            $this->aWords = explode(' ', $sPhrase);
-        } else {
-            $this->aWords = array();
-        }
-    }
-
-    /**
-     * Get all possible tokens that are present in this word list.
-     *
-     * @return array The list of string tokens in the word list.
-     */
-    public function getTokens()
-    {
-        $aTokens = array();
-        $iNumWords = count($this->aWords);
-
-        for ($i = 0; $i < $iNumWords; $i++) {
-            $sPhrase = $this->aWords[$i];
-            $aTokens[$sPhrase] = $sPhrase;
-
-            for ($j = $i + 1; $j < $iNumWords; $j++) {
-                $sPhrase .= ' '.$this->aWords[$j];
-                $aTokens[$sPhrase] = $sPhrase;
-            }
-        }
-
-        return $aTokens;
-    }
-
-    /**
-     * Compute all possible permutations of phrase splits that result in
-     * words which are in the token list.
-     */
-    public function getWordSets($oTokens)
-    {
-        $iNumWords = count($this->aWords);
-
-        if ($iNumWords == 0) {
-            return null;
-        }
-
-        // Caches the word set for the partial phrase up to word i.
-        $aSetCache = array_fill(0, $iNumWords, array());
-
-        // Initialise first element of cache. There can only be the word.
-        if ($oTokens->containsAny($this->aWords[0])) {
-            $aSetCache[0][] = array($this->aWords[0]);
-        }
-
-        // Now do the next elements using what we already have.
-        for ($i = 1; $i < $iNumWords; $i++) {
-            for ($j = $i; $j > 0; $j--) {
-                $sPartial = $j == $i ? $this->aWords[$j] : $this->aWords[$j].' '.$sPartial;
-                if (!empty($aSetCache[$j - 1]) && $oTokens->containsAny($sPartial)) {
-                    $aPartial = array($sPartial);
-                    foreach ($aSetCache[$j - 1] as $aSet) {
-                        if (count($aSet) < SimpleWordList::MAX_WORDSET_LEN) {
-                            $aSetCache[$i][] = array_merge($aSet, $aPartial);
-                        }
-                    }
-                    if (count($aSetCache[$i]) > 2 * SimpleWordList::MAX_WORDSETS) {
-                        usort(
-                            $aSetCache[$i],
-                            array('\Nominatim\SimpleWordList', 'cmpByArraylen')
-                        );
-                        $aSetCache[$i] = array_slice(
-                            $aSetCache[$i],
-                            0,
-                            SimpleWordList::MAX_WORDSETS
-                        );
-                    }
-                }
-            }
-
-            // finally the current full phrase
-            $sPartial = $this->aWords[0].' '.$sPartial;
-            if ($oTokens->containsAny($sPartial)) {
-                $aSetCache[$i][] = array($sPartial);
-            }
-        }
-
-        $aWordSets = $aSetCache[$iNumWords - 1];
-        usort($aWordSets, array('\Nominatim\SimpleWordList', 'cmpByArraylen'));
-        return array_slice($aWordSets, 0, SimpleWordList::MAX_WORDSETS);
-    }
-
-    /**
-     * Custom search routine which takes two arrays. The array with the fewest
-     * items wins. If same number of items then the one with the longest first
-     * element wins.
-     */
-    public static function cmpByArraylen($aA, $aB)
-    {
-        $iALen = count($aA);
-        $iBLen = count($aB);
-
-        if ($iALen == $iBLen) {
-            return strlen($aB[0]) <=> strlen($aA[0]);
-        }
-
-        return ($iALen < $iBLen) ? -1 : 1;
-    }
-
-    public function debugInfo()
-    {
-        return $this->aWords;
-    }
-}
diff --git a/lib-php/SpecialSearchOperator.php b/lib-php/SpecialSearchOperator.php
deleted file mode 100644 (file)
index 94df59e..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim;
-
-/**
- * Operators describing special searches.
- */
-abstract class Operator
-{
-    /// No operator selected.
-    const NONE = 0;
-    /// Search for POI of the given type.
-    const TYPE = 1;
-    /// Search for POIs near the given place.
-    const NEAR = 2;
-    /// Search for POIS in the given place.
-    const IN = 3;
-    /// Search for POIS named as given.
-    const NAME = 4;
-    /// Search for postcodes.
-    const POSTCODE = 5;
-
-    private static $aConstantNames = null;
-
-
-    public static function toString($iOperator)
-    {
-        if ($iOperator == Operator::NONE) {
-            return '';
-        }
-
-        if (Operator::$aConstantNames === null) {
-            $oReflector = new \ReflectionClass('Nominatim\Operator');
-            $aConstants = $oReflector->getConstants();
-
-            Operator::$aConstantNames = array();
-            foreach ($aConstants as $sName => $iValue) {
-                Operator::$aConstantNames[$iValue] = $sName;
-            }
-        }
-
-        return Operator::$aConstantNames[$iOperator];
-    }
-}
diff --git a/lib-php/Status.php b/lib-php/Status.php
deleted file mode 100644 (file)
index 4f1555c..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim;
-
-require_once(CONST_TokenizerDir.'/tokenizer.php');
-
-use Exception;
-
-class Status
-{
-    protected $oDB;
-
-    public function __construct(&$oDB)
-    {
-        $this->oDB =& $oDB;
-    }
-
-    public function status()
-    {
-        if (!$this->oDB) {
-            throw new Exception('No database', 700);
-        }
-
-        try {
-            $this->oDB->connect();
-        } catch (\Nominatim\DatabaseError $e) {
-            throw new Exception('Database connection failed', 700);
-        }
-
-        $oTokenizer = new \Nominatim\Tokenizer($this->oDB);
-        $oTokenizer->checkStatus();
-    }
-
-    public function dataDate()
-    {
-        $sSQL = 'SELECT EXTRACT(EPOCH FROM lastimportdate) FROM import_status LIMIT 1';
-        $iDataDateEpoch = $this->oDB->getOne($sSQL);
-
-        if ($iDataDateEpoch === false) {
-            throw new Exception('Import date is not available', 705);
-        }
-
-        return $iDataDateEpoch;
-    }
-
-    public function databaseVersion()
-    {
-        $sSQL = 'SELECT value FROM nominatim_properties WHERE property = \'database_version\'';
-        return $this->oDB->getOne($sSQL);
-    }
-}
diff --git a/lib-php/TokenCountry.php b/lib-php/TokenCountry.php
deleted file mode 100644 (file)
index 3f93f45..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim\Token;
-
-/**
- * A country token.
- */
-class Country
-{
-    /// Database word id, if available.
-    private $iId;
-    /// Two-letter country code (lower-cased).
-    private $sCountryCode;
-
-    public function __construct($iId, $sCountryCode)
-    {
-        $this->iId = $iId;
-        $this->sCountryCode = $sCountryCode;
-    }
-
-    public function getId()
-    {
-        return $this->iId;
-    }
-
-    /**
-     * Check if the token can be added to the given search.
-     * Derive new searches by adding this token to an existing search.
-     *
-     * @param object  $oSearch      Partial search description derived so far.
-     * @param object  $oPosition    Description of the token position within
-                                    the query.
-     *
-     * @return True if the token is compatible with the search configuration
-     *         given the position.
-     */
-    public function isExtendable($oSearch, $oPosition)
-    {
-        return !$oSearch->hasCountry()
-               && $oPosition->maybePhrase('country')
-               && $oSearch->getContext()->isCountryApplicable($this->sCountryCode);
-    }
-
-    /**
-     * Derive new searches by adding this token to an existing search.
-     *
-     * @param object  $oSearch      Partial search description derived so far.
-     * @param object  $oPosition    Description of the token position within
-                                    the query.
-     *
-     * @return SearchDescription[] List of derived search descriptions.
-     */
-    public function extendSearch($oSearch, $oPosition)
-    {
-        $oNewSearch = $oSearch->clone($oPosition->isLastToken() ? 1 : 6);
-        $oNewSearch->setCountry($this->sCountryCode);
-
-        return array($oNewSearch);
-    }
-
-    public function debugInfo()
-    {
-        return array(
-                'ID' => $this->iId,
-                'Type' => 'country',
-                'Info' => $this->sCountryCode
-               );
-    }
-
-    public function debugCode()
-    {
-        return 'C';
-    }
-}
diff --git a/lib-php/TokenHousenumber.php b/lib-php/TokenHousenumber.php
deleted file mode 100644 (file)
index 62c2a62..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim\Token;
-
-/**
- * A house number token.
- */
-class HouseNumber
-{
-    /// Database word id, if available.
-    private $iId;
-    /// Normalized house number.
-    private $sToken;
-
-    public function __construct($iId, $sToken)
-    {
-        $this->iId = $iId;
-        $this->sToken = $sToken;
-    }
-
-    public function getId()
-    {
-        return $this->iId;
-    }
-
-    /**
-     * Check if the token can be added to the given search.
-     * Derive new searches by adding this token to an existing search.
-     *
-     * @param object  $oSearch      Partial search description derived so far.
-     * @param object  $oPosition    Description of the token position within
-                                    the query.
-     *
-     * @return True if the token is compatible with the search configuration
-     *         given the position.
-     */
-    public function isExtendable($oSearch, $oPosition)
-    {
-        return !$oSearch->hasHousenumber()
-               && !$oSearch->hasOperator(\Nominatim\Operator::POSTCODE)
-               && $oPosition->maybePhrase('street');
-    }
-
-    /**
-     * Derive new searches by adding this token to an existing search.
-     *
-     * @param object  $oSearch      Partial search description derived so far.
-     * @param object  $oPosition    Description of the token position within
-                                    the query.
-     *
-     * @return SearchDescription[] List of derived search descriptions.
-     */
-    public function extendSearch($oSearch, $oPosition)
-    {
-        $aNewSearches = array();
-
-        // sanity check: if the housenumber is not mainly made
-        // up of numbers, add a penalty
-        $iSearchCost = 1;
-        if (preg_match('/\\d/', $this->sToken) === 0
-            || preg_match_all('/[^0-9 ]/', $this->sToken, $aMatches) > 3) {
-            $iSearchCost += strlen($this->sToken) - 1;
-        }
-        if (!$oSearch->hasOperator(\Nominatim\Operator::NONE)) {
-            $iSearchCost++;
-        }
-        if (empty($this->iId)) {
-            $iSearchCost++;
-        }
-        // also must not appear in the middle of the address
-        if ($oSearch->hasAddress() || $oSearch->hasPostcode()) {
-            $iSearchCost++;
-        }
-
-        $oNewSearch = $oSearch->clone($iSearchCost);
-        $oNewSearch->setHousenumber($this->sToken);
-        $aNewSearches[] = $oNewSearch;
-
-        // Housenumbers may appear in the name when the place has its own
-        // address terms.
-        if ($this->iId !== null
-            && ($oSearch->getNamePhrase() >= 0 || !$oSearch->hasName())
-            && !$oSearch->hasAddress()
-        ) {
-            $oNewSearch = $oSearch->clone($iSearchCost);
-            $oNewSearch->setHousenumberAsName($this->iId);
-
-            $aNewSearches[] = $oNewSearch;
-        }
-
-        return $aNewSearches;
-    }
-
-
-    public function debugInfo()
-    {
-        return array(
-                'ID' => $this->iId,
-                'Type' => 'house number',
-                'Info' => array('nr' => $this->sToken)
-               );
-    }
-
-    public function debugCode()
-    {
-        return 'H';
-    }
-}
diff --git a/lib-php/TokenList.php b/lib-php/TokenList.php
deleted file mode 100644 (file)
index 9a3950a..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim;
-
-require_once(CONST_LibDir.'/TokenCountry.php');
-require_once(CONST_LibDir.'/TokenHousenumber.php');
-require_once(CONST_LibDir.'/TokenPostcode.php');
-require_once(CONST_LibDir.'/TokenSpecialTerm.php');
-require_once(CONST_LibDir.'/TokenWord.php');
-require_once(CONST_LibDir.'/TokenPartial.php');
-require_once(CONST_LibDir.'/SpecialSearchOperator.php');
-
-/**
- * Saves information about the tokens that appear in a search query.
- *
- * Tokens are sorted by their normalized form, the token word. There are different
- * kinds of tokens, represented by different Token* classes. Note that
- * tokens do not have a common base class. All tokens need to have a field
- * with the word id that points to an entry in the `word` database table
- * but otherwise the information saved about a token can be very different.
- */
-class TokenList
-{
-    // List of list of tokens indexed by their word_token.
-    private $aTokens = array();
-
-
-    /**
-     * Return total number of tokens.
-     *
-     * @return Integer
-     */
-    public function count()
-    {
-        return count($this->aTokens);
-    }
-
-    /**
-     * Check if there are tokens for the given token word.
-     *
-     * @param string $sWord Token word to look for.
-     *
-     * @return bool True if there is one or more token for the token word.
-     */
-    public function contains($sWord)
-    {
-        return isset($this->aTokens[$sWord]);
-    }
-
-    /**
-     * Check if there are partial or full tokens for the given word.
-     *
-     * @param string $sWord Token word to look for.
-     *
-     * @return bool True if there is one or more token for the token word.
-     */
-    public function containsAny($sWord)
-    {
-        return isset($this->aTokens[$sWord]);
-    }
-
-    /**
-     * Get the list of tokens for the given token word.
-     *
-     * @param string $sWord Token word to look for.
-     *
-     * @return object[] Array of tokens for the given token word or an
-     *                  empty array if no tokens could be found.
-     */
-    public function get($sWord)
-    {
-        return isset($this->aTokens[$sWord]) ? $this->aTokens[$sWord] : array();
-    }
-
-    public function getFullWordIDs()
-    {
-        $ids = array();
-
-        foreach ($this->aTokens as $aTokenList) {
-            foreach ($aTokenList as $oToken) {
-                if (is_a($oToken, '\Nominatim\Token\Word')) {
-                    $ids[$oToken->getId()] = $oToken->getId();
-                }
-            }
-        }
-
-        return $ids;
-    }
-
-    /**
-     * Add a new token for the given word.
-     *
-     * @param string $sWord  Word the token describes.
-     * @param object $oToken Token object to add.
-     *
-     * @return void
-     */
-    public function addToken($sWord, $oToken)
-    {
-        if (isset($this->aTokens[$sWord])) {
-            $this->aTokens[$sWord][] = $oToken;
-        } else {
-            $this->aTokens[$sWord] = array($oToken);
-        }
-    }
-
-    public function debugTokenByWordIdList()
-    {
-        $aWordsIDs = array();
-        foreach ($this->aTokens as $sToken => $aWords) {
-            foreach ($aWords as $aToken) {
-                $iId = $aToken->getId();
-                if ($iId !== null) {
-                    $aWordsIDs[$iId] = '#'.$sToken.'('.$aToken->debugCode().' '.$iId.')#';
-                }
-            }
-        }
-
-        return $aWordsIDs;
-    }
-
-    public function debugInfo()
-    {
-        return $this->aTokens;
-    }
-}
diff --git a/lib-php/TokenPartial.php b/lib-php/TokenPartial.php
deleted file mode 100644 (file)
index 3dc6f30..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim\Token;
-
-/**
- * A standard word token.
- */
-class Partial
-{
-    /// Database word id, if applicable.
-    private $iId;
-    /// Number of appearances in the database.
-    private $iSearchNameCount;
-    /// True, if the token consists exclusively of digits and spaces.
-    private $bNumberToken;
-
-    public function __construct($iId, $sToken, $iSearchNameCount)
-    {
-        $this->iId = $iId;
-        $this->bNumberToken = (bool) preg_match('#^[0-9 ]+$#', $sToken);
-        $this->iSearchNameCount = $iSearchNameCount;
-    }
-
-    public function getId()
-    {
-        return $this->iId;
-    }
-
-    /**
-     * Check if the token can be added to the given search.
-     * Derive new searches by adding this token to an existing search.
-     *
-     * @param object  $oSearch      Partial search description derived so far.
-     * @param object  $oPosition    Description of the token position within
-                                    the query.
-     *
-     * @return True if the token is compatible with the search configuration
-     *         given the position.
-     */
-    public function isExtendable($oSearch, $oPosition)
-    {
-        return !$oPosition->isPhrase('country');
-    }
-
-    /**
-     * Derive new searches by adding this token to an existing search.
-     *
-     * @param object  $oSearch      Partial search description derived so far.
-     * @param object  $oPosition    Description of the token position within
-                                    the query.
-     *
-     * @return SearchDescription[] List of derived search descriptions.
-     */
-    public function extendSearch($oSearch, $oPosition)
-    {
-        $aNewSearches = array();
-
-        // Partial token in Address.
-        if (($oPosition->isPhrase('') || !$oPosition->isFirstPhrase())
-            && $oSearch->hasName()
-        ) {
-            $iSearchCost = $this->bNumberToken ? 2 : 1;
-            if ($this->iSearchNameCount >= CONST_Max_Word_Frequency) {
-                $iSearchCost += 1;
-            }
-
-            $oNewSearch = $oSearch->clone($iSearchCost);
-            $oNewSearch->addAddressToken(
-                $this->iId,
-                $this->iSearchNameCount < CONST_Max_Word_Frequency
-            );
-
-            $aNewSearches[] = $oNewSearch;
-        }
-
-        // Partial token in Name.
-        if ((!$oSearch->hasPostcode() && !$oSearch->hasAddress())
-            && (!$oSearch->hasName(true)
-                || $oSearch->getNamePhrase() == $oPosition->getPhrase())
-        ) {
-            $iSearchCost = 1;
-            if (!$oSearch->hasName(true)) {
-                $iSearchCost += 1;
-            }
-            if ($this->bNumberToken) {
-                $iSearchCost += 1;
-            }
-
-            $oNewSearch = $oSearch->clone($iSearchCost);
-            $oNewSearch->addPartialNameToken(
-                $this->iId,
-                $this->iSearchNameCount < CONST_Max_Word_Frequency,
-                $this->iSearchNameCount > CONST_Search_NameOnlySearchFrequencyThreshold,
-                $oPosition->getPhrase()
-            );
-
-            $aNewSearches[] = $oNewSearch;
-        }
-
-        return $aNewSearches;
-    }
-
-
-    public function debugInfo()
-    {
-        return array(
-                'ID' => $this->iId,
-                'Type' => 'partial',
-                'Info' => array(
-                           'count' => $this->iSearchNameCount
-                          )
-               );
-    }
-
-    public function debugCode()
-    {
-        return 'w';
-    }
-}
diff --git a/lib-php/TokenPostcode.php b/lib-php/TokenPostcode.php
deleted file mode 100644 (file)
index 0ff9292..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim\Token;
-
-/**
- * A postcode token.
- */
-class Postcode
-{
-    /// Database word id, if available.
-    private $iId;
-    /// Full normalized postcode (upper cased).
-    private $sPostcode;
-    // Optional country code the postcode belongs to (currently unused).
-    private $sCountryCode;
-
-    public function __construct($iId, $sPostcode, $sCountryCode = '')
-    {
-        $this->iId = $iId;
-        $iSplitPos = strpos($sPostcode, '@');
-        if ($iSplitPos === false) {
-            $this->sPostcode = $sPostcode;
-        } else {
-            $this->sPostcode = substr($sPostcode, 0, $iSplitPos);
-        }
-        $this->sCountryCode = empty($sCountryCode) ? '' : $sCountryCode;
-    }
-
-    public function getId()
-    {
-        return $this->iId;
-    }
-
-    /**
-     * Check if the token can be added to the given search.
-     * Derive new searches by adding this token to an existing search.
-     *
-     * @param object  $oSearch      Partial search description derived so far.
-     * @param object  $oPosition    Description of the token position within
-                                    the query.
-     *
-     * @return True if the token is compatible with the search configuration
-     *         given the position.
-     */
-    public function isExtendable($oSearch, $oPosition)
-    {
-        return !$oSearch->hasPostcode() && $oPosition->maybePhrase('postalcode');
-    }
-
-    /**
-     * Derive new searches by adding this token to an existing search.
-     *
-     * @param object  $oSearch      Partial search description derived so far.
-     * @param object  $oPosition    Description of the token position within
-                                    the query.
-     *
-     * @return SearchDescription[] List of derived search descriptions.
-     */
-    public function extendSearch($oSearch, $oPosition)
-    {
-        $aNewSearches = array();
-
-        // If we have structured search or this is the first term,
-        // make the postcode the primary search element.
-        if ($oSearch->hasOperator(\Nominatim\Operator::NONE) && $oPosition->isFirstToken()) {
-            $oNewSearch = $oSearch->clone(1);
-            $oNewSearch->setPostcodeAsName($this->iId, $this->sPostcode);
-
-            $aNewSearches[] = $oNewSearch;
-        }
-
-        // If we have a structured search or this is not the first term,
-        // add the postcode as an addendum.
-        if (!$oSearch->hasOperator(\Nominatim\Operator::POSTCODE)
-            && ($oPosition->isPhrase('postalcode') || $oSearch->hasName())
-        ) {
-            $iPenalty = 1;
-            if (strlen($this->sPostcode) < 4) {
-                $iPenalty += 4 - strlen($this->sPostcode);
-            }
-            $oNewSearch = $oSearch->clone($iPenalty);
-            $oNewSearch->setPostcode($this->sPostcode);
-
-            $aNewSearches[] = $oNewSearch;
-        }
-
-        return $aNewSearches;
-    }
-
-    public function debugInfo()
-    {
-        return array(
-                'ID' => $this->iId,
-                'Type' => 'postcode',
-                'Info' => $this->sPostcode.'('.$this->sCountryCode.')'
-               );
-    }
-
-    public function debugCode()
-    {
-        return 'P';
-    }
-}
diff --git a/lib-php/TokenSpecialTerm.php b/lib-php/TokenSpecialTerm.php
deleted file mode 100644 (file)
index 475ae71..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim\Token;
-
-require_once(CONST_LibDir.'/SpecialSearchOperator.php');
-
-/**
- * A word token describing a place type.
- */
-class SpecialTerm
-{
-    /// Database word id, if applicable.
-    private $iId;
-    /// Class (or OSM tag key) of the place to look for.
-    private $sClass;
-    /// Type (or OSM tag value) of the place to look for.
-    private $sType;
-    /// Relationship of the operator to the object (see Operator class).
-    private $iOperator;
-
-    public function __construct($iID, $sClass, $sType, $iOperator)
-    {
-        $this->iId = $iID;
-        $this->sClass = $sClass;
-        $this->sType = $sType;
-        $this->iOperator = $iOperator;
-    }
-
-    public function getId()
-    {
-        return $this->iId;
-    }
-
-    /**
-     * Check if the token can be added to the given search.
-     * Derive new searches by adding this token to an existing search.
-     *
-     * @param object  $oSearch      Partial search description derived so far.
-     * @param object  $oPosition    Description of the token position within
-                                    the query.
-     *
-     * @return True if the token is compatible with the search configuration
-     *         given the position.
-     */
-    public function isExtendable($oSearch, $oPosition)
-    {
-        return !$oSearch->hasOperator()
-               && $oPosition->isPhrase('')
-               && ($this->iOperator != \Nominatim\Operator::NONE
-                  || (!$oSearch->hasAddress() && !$oSearch->hasHousenumber() && !$oSearch->hasCountry()));
-    }
-
-    /**
-     * Derive new searches by adding this token to an existing search.
-     *
-     * @param object  $oSearch      Partial search description derived so far.
-     * @param object  $oPosition    Description of the token position within
-                                    the query.
-     *
-     * @return SearchDescription[] List of derived search descriptions.
-     */
-    public function extendSearch($oSearch, $oPosition)
-    {
-        $iSearchCost = 0;
-
-        $iOp = $this->iOperator;
-        if ($iOp == \Nominatim\Operator::NONE) {
-            if ($oPosition->isFirstToken()
-                || $oSearch->hasName()
-                || $oSearch->getContext()->isBoundedSearch()
-            ) {
-                $iOp = \Nominatim\Operator::NAME;
-                $iSearchCost += 3;
-            } else {
-                $iOp = \Nominatim\Operator::NEAR;
-                $iSearchCost += 4;
-                if (!$oPosition->isFirstToken()) {
-                    $iSearchCost += 3;
-                }
-            }
-        } elseif ($oPosition->isFirstToken()) {
-            $iSearchCost += 2;
-        } elseif ($oPosition->isLastToken()) {
-            $iSearchCost += 4;
-        } else {
-            $iSearchCost += 6;
-        }
-
-        if ($oSearch->hasHousenumber()) {
-            $iSearchCost ++;
-        }
-
-        $oNewSearch = $oSearch->clone($iSearchCost);
-        $oNewSearch->setPoiSearch($iOp, $this->sClass, $this->sType);
-
-        return array($oNewSearch);
-    }
-
-
-    public function debugInfo()
-    {
-        return array(
-                'ID' => $this->iId,
-                'Type' => 'special term',
-                'Info' => array(
-                           'class' => $this->sClass,
-                           'type' => $this->sType,
-                           'operator' => \Nominatim\Operator::toString($this->iOperator)
-                          )
-               );
-    }
-
-    public function debugCode()
-    {
-        return 'S';
-    }
-}
diff --git a/lib-php/TokenWord.php b/lib-php/TokenWord.php
deleted file mode 100644 (file)
index a7557d3..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim\Token;
-
-/**
- * A standard word token.
- */
-class Word
-{
-    /// Database word id, if applicable.
-    private $iId;
-    /// Number of appearances in the database.
-    private $iSearchNameCount;
-    /// Number of terms in the word.
-    private $iTermCount;
-
-    public function __construct($iId, $iSearchNameCount, $iTermCount)
-    {
-        $this->iId = $iId;
-        $this->iSearchNameCount = $iSearchNameCount;
-        $this->iTermCount = $iTermCount;
-    }
-
-    public function getId()
-    {
-        return $this->iId;
-    }
-
-    /**
-     * Check if the token can be added to the given search.
-     * Derive new searches by adding this token to an existing search.
-     *
-     * @param object  $oSearch      Partial search description derived so far.
-     * @param object  $oPosition    Description of the token position within
-                                    the query.
-     *
-     * @return True if the token is compatible with the search configuration
-     *         given the position.
-     */
-    public function isExtendable($oSearch, $oPosition)
-    {
-        return !$oPosition->isPhrase('country');
-    }
-
-    /**
-     * Derive new searches by adding this token to an existing search.
-     *
-     * @param object  $oSearch      Partial search description derived so far.
-     * @param object  $oPosition    Description of the token position within
-                                    the query.
-     *
-     * @return SearchDescription[] List of derived search descriptions.
-     */
-    public function extendSearch($oSearch, $oPosition)
-    {
-        // Full words can only be a name if they appear at the beginning
-        // of the phrase. In structured search the name must forcibly in
-        // the first phrase. In unstructured search it may be in a later
-        // phrase when the first phrase is a house number.
-        if ($oSearch->hasName()
-            || !($oPosition->isFirstPhrase() || $oPosition->isPhrase(''))
-        ) {
-            if ($this->iTermCount > 1
-                && ($oPosition->isPhrase('') || !$oPosition->isFirstPhrase())
-            ) {
-                $oNewSearch = $oSearch->clone(1);
-                $oNewSearch->addAddressToken($this->iId);
-
-                return array($oNewSearch);
-            }
-        } elseif (!$oSearch->hasName(true)) {
-            $oNewSearch = $oSearch->clone(1);
-            $oNewSearch->addNameToken(
-                $this->iId,
-                CONST_Search_NameOnlySearchFrequencyThreshold
-                && $this->iSearchNameCount
-                          < CONST_Search_NameOnlySearchFrequencyThreshold
-            );
-
-            return array($oNewSearch);
-        }
-
-        return array();
-    }
-
-    public function debugInfo()
-    {
-        return array(
-                'ID' => $this->iId,
-                'Type' => 'word',
-                'Info' => array(
-                           'count' => $this->iSearchNameCount,
-                           'terms' => $this->iTermCount
-                          )
-               );
-    }
-
-    public function debugCode()
-    {
-        return 'W';
-    }
-}
diff --git a/lib-php/cmd.php b/lib-php/cmd.php
deleted file mode 100644 (file)
index 6f1299d..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-require_once(CONST_LibDir.'/Shell.php');
-
-function getCmdOpt($aArg, $aSpec, &$aResult, $bExitOnError = false, $bExitOnUnknown = false)
-{
-    $aQuick = array();
-    $aCounts = array();
-
-    foreach ($aSpec as $aLine) {
-        if (is_array($aLine)) {
-            if ($aLine[0]) {
-                $aQuick['--'.$aLine[0]] = $aLine;
-            }
-            if ($aLine[1]) {
-                $aQuick['-'.$aLine[1]] = $aLine;
-            }
-            $aCounts[$aLine[0]] = 0;
-        }
-    }
-
-    $aResult = array();
-    $bUnknown = false;
-    $iSize = count($aArg);
-    for ($i = 1; $i < $iSize; $i++) {
-        if (isset($aQuick[$aArg[$i]])) {
-            $aLine = $aQuick[$aArg[$i]];
-            $aCounts[$aLine[0]]++;
-            $xVal = null;
-            if ($aLine[4] == $aLine[5]) {
-                if ($aLine[4]) {
-                    $xVal = array();
-                    for ($n = $aLine[4]; $i < $iSize && $n; $n--) {
-                        $i++;
-                        if ($i >= $iSize || $aArg[$i][0] == '-') {
-                            showUsage($aSpec, $bExitOnError, 'Parameter of  \''.$aLine[0].'\' is missing');
-                        }
-
-                        switch ($aLine[6]) {
-                            case 'realpath':
-                                $xVal[] = realpath($aArg[$i]);
-                                break;
-                            case 'realdir':
-                                $sPath = realpath(dirname($aArg[$i]));
-                                if ($sPath) {
-                                    $xVal[] = $sPath . '/' . basename($aArg[$i]);
-                                } else {
-                                    $xVal[] = $sPath;
-                                }
-                                break;
-                            case 'bool':
-                                $xVal[] = (bool)$aArg[$i];
-                                break;
-                            case 'int':
-                                $xVal[] = (int)$aArg[$i];
-                                break;
-                            case 'float':
-                                $xVal[] = (float)$aArg[$i];
-                                break;
-                            default:
-                                $xVal[] = $aArg[$i];
-                                break;
-                        }
-                    }
-                    if ($aLine[4] == 1) {
-                        $xVal = $xVal[0];
-                    }
-                } else {
-                    $xVal = true;
-                }
-            } else {
-                fail('Variable numbers of params not yet supported');
-            }
-
-            if ($aLine[3] > 1) {
-                if (!array_key_exists($aLine[0], $aResult)) {
-                    $aResult[$aLine[0]] = array();
-                }
-                $aResult[$aLine[0]][] = $xVal;
-            } else {
-                $aResult[$aLine[0]] = $xVal;
-            }
-        } else {
-            $bUnknown = $aArg[$i];
-        }
-    }
-
-    if (array_key_exists('help', $aResult)) {
-        showUsage($aSpec);
-    }
-    if ($bUnknown && $bExitOnUnknown) {
-        showUsage($aSpec, $bExitOnError, 'Unknown option \''.$bUnknown.'\'');
-    }
-
-    foreach ($aSpec as $aLine) {
-        if (is_array($aLine)) {
-            if ($aCounts[$aLine[0]] < $aLine[2]) {
-                showUsage($aSpec, $bExitOnError, 'Option \''.$aLine[0].'\' is missing');
-            }
-            if ($aCounts[$aLine[0]] > $aLine[3]) {
-                showUsage($aSpec, $bExitOnError, 'Option \''.$aLine[0].'\' is present too many times');
-            }
-            if ($aLine[6] == 'bool' && !array_key_exists($aLine[0], $aResult)) {
-                $aResult[$aLine[0]] = false;
-            }
-        }
-    }
-    return $bUnknown;
-}
-
-function showUsage($aSpec, $bExit = false, $sError = false)
-{
-    if ($sError) {
-        echo basename($_SERVER['argv'][0]).': '.$sError."\n";
-        echo 'Try `'.basename($_SERVER['argv'][0]).' --help` for more information.'."\n";
-        exit;
-    }
-    echo 'Usage: '.basename($_SERVER['argv'][0])."\n";
-    $bFirst = true;
-    foreach ($aSpec as $aLine) {
-        if (is_array($aLine)) {
-            if ($bFirst) {
-                $bFirst = false;
-                echo "\n";
-            }
-            $aNames = array();
-            if ($aLine[1]) {
-                $aNames[] = '-'.$aLine[1];
-            }
-            if ($aLine[0]) {
-                $aNames[] = '--'.$aLine[0];
-            }
-            $sName = join(', ', $aNames);
-            echo '  '.$sName.str_repeat(' ', 30-strlen($sName)).$aLine[7]."\n";
-        } else {
-            echo $aLine."\n";
-        }
-    }
-    echo "\n";
-    exit;
-}
-
-function info($sMsg)
-{
-    echo date('Y-m-d H:i:s == ').$sMsg."\n";
-}
-
-$aWarnings = array();
-
-
-function warn($sMsg)
-{
-    $GLOBALS['aWarnings'][] = $sMsg;
-    echo date('Y-m-d H:i:s == ').'WARNING: '.$sMsg."\n";
-}
-
-
-function repeatWarnings()
-{
-    foreach ($GLOBALS['aWarnings'] as $sMsg) {
-        echo '  * ',$sMsg."\n";
-    }
-}
-
-
-function setupHTTPProxy()
-{
-    if (!getSettingBool('HTTP_PROXY')) {
-        return;
-    }
-
-    $sProxy = 'tcp://'.getSetting('HTTP_PROXY_HOST').':'.getSetting('HTTP_PROXY_PROT');
-    $aHeaders = array();
-
-    $sLogin = getSetting('HTTP_PROXY_LOGIN');
-    $sPassword = getSetting('HTTP_PROXY_PASSWORD');
-
-    if ($sLogin && $sPassword) {
-        $sAuth = base64_encode($sLogin.':'.$sPassword);
-        $aHeaders = array('Proxy-Authorization: Basic '.$sAuth);
-    }
-
-    $aProxyHeader = array(
-                     'proxy' => $sProxy,
-                     'request_fulluri' => true,
-                     'header' => $aHeaders
-                    );
-
-    $aContext = array('http' => $aProxyHeader, 'https' => $aProxyHeader);
-    stream_context_set_default($aContext);
-}
diff --git a/lib-php/dotenv_loader.php b/lib-php/dotenv_loader.php
deleted file mode 100644 (file)
index bcddf00..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-require('Symfony/Component/Dotenv/autoload.php');
-
-function loadDotEnv()
-{
-    $dotenv = new \Symfony\Component\Dotenv\Dotenv();
-    $dotenv->load(CONST_ConfigDir.'/env.defaults');
-
-    if (file_exists('.env')) {
-        $dotenv->load('.env');
-    }
-}
diff --git a/lib-php/init-cmd.php b/lib-php/init-cmd.php
deleted file mode 100644 (file)
index 44e7adb..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-require_once('init.php');
-require_once('cmd.php');
-require_once('DebugNone.php');
diff --git a/lib-php/init-website.php b/lib-php/init-website.php
deleted file mode 100644 (file)
index 6036750..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-require_once('init.php');
-require_once('ParameterParser.php');
-require_once(CONST_Debug ? 'DebugHtml.php' : 'DebugNone.php');
-
-/***************************************************************************
- *
- * Error handling functions
- *
- */
-
-function userError($sMsg)
-{
-    throw new \Exception($sMsg, 400);
-}
-
-
-function exception_handler_json($exception)
-{
-    http_response_code($exception->getCode() == 0 ? 500 : $exception->getCode());
-    header('Content-type: application/json; charset=utf-8');
-    include(CONST_LibDir.'/template/error-json.php');
-    exit();
-}
-
-function exception_handler_xml($exception)
-{
-    http_response_code($exception->getCode() == 0 ? 500 : $exception->getCode());
-    header('Content-type: text/xml; charset=utf-8');
-    echo '<?xml version="1.0" encoding="UTF-8" ?>'."\n";
-    include(CONST_LibDir.'/template/error-xml.php');
-    exit();
-}
-
-function shutdown_exception_handler_xml()
-{
-    $error = error_get_last();
-    if ($error !== null && $error['type'] === E_ERROR) {
-        exception_handler_xml(new \Exception($error['message'], 500));
-    }
-}
-
-function shutdown_exception_handler_json()
-{
-    $error = error_get_last();
-    if ($error !== null && $error['type'] === E_ERROR) {
-        exception_handler_json(new \Exception($error['message'], 500));
-    }
-}
-
-
-function set_exception_handler_by_format($sFormat = null)
-{
-    // Multiple calls to register_shutdown_function will cause multiple callbacks
-    // to be executed, we only want the last executed. Thus we don't want to register
-    // one by default without an explicit $sFormat set.
-
-    if (!isset($sFormat)) {
-        set_exception_handler('exception_handler_json');
-    } elseif ($sFormat == 'xml') {
-        set_exception_handler('exception_handler_xml');
-        register_shutdown_function('shutdown_exception_handler_xml');
-    } else {
-        set_exception_handler('exception_handler_json');
-        register_shutdown_function('shutdown_exception_handler_json');
-    }
-}
-// set a default
-set_exception_handler_by_format();
-
-
-/***************************************************************************
- * HTTP Reply header setup
- */
-
-if (CONST_NoAccessControl) {
-    header('Access-Control-Allow-Origin: *');
-    header('Access-Control-Allow-Methods: OPTIONS,GET');
-    if (!empty($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) {
-        header('Access-Control-Allow-Headers: '.$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']);
-    }
-}
-if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
-    exit;
-}
-
-if (CONST_Debug) {
-    header('Content-type: text/html; charset=utf-8');
-}
diff --git a/lib-php/init.php b/lib-php/init.php
deleted file mode 100644 (file)
index 9e71a76..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-require_once(CONST_LibDir.'/lib.php');
-require_once(CONST_LibDir.'/DB.php');
diff --git a/lib-php/lib.php b/lib-php/lib.php
deleted file mode 100644 (file)
index f7c6e55..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-function loadSettings($sProjectDir)
-{
-    @define('CONST_InstallDir', $sProjectDir);
-    // Temporary hack to set the directory via environment instead of
-    // the installed scripts. Neither setting is part of the official
-    // set of settings.
-    defined('CONST_ConfigDir') or define('CONST_ConfigDir', $_SERVER['NOMINATIM_CONFIGDIR']);
-}
-
-function getSetting($sConfName, $sDefault = null)
-{
-    $sValue = $_SERVER['NOMINATIM_'.$sConfName];
-
-    if ($sDefault !== null && !$sValue) {
-        return $sDefault;
-    }
-
-    return $sValue;
-}
-
-function getSettingBool($sConfName)
-{
-    $sVal = strtolower(getSetting($sConfName));
-
-    return strcmp($sVal, 'yes') == 0
-           || strcmp($sVal, 'true') == 0
-           || strcmp($sVal, '1') == 0;
-}
-
-function fail($sError, $sUserError = false)
-{
-    if (!$sUserError) {
-        $sUserError = $sError;
-    }
-    error_log('ERROR: '.$sError);
-    var_dump($sUserError);
-    echo "\n";
-    exit(-1);
-}
-
-
-function getProcessorCount()
-{
-    $sCPU = file_get_contents('/proc/cpuinfo');
-    preg_match_all('#processor\s+: [0-9]+#', $sCPU, $aMatches);
-    return count($aMatches[0]);
-}
-
-
-function getTotalMemoryMB()
-{
-    $sCPU = file_get_contents('/proc/meminfo');
-    preg_match('#MemTotal: +([0-9]+) kB#', $sCPU, $aMatches);
-    return (int)($aMatches[1]/1024);
-}
-
-
-function getCacheMemoryMB()
-{
-    $sCPU = file_get_contents('/proc/meminfo');
-    preg_match('#Cached: +([0-9]+) kB#', $sCPU, $aMatches);
-    return (int)($aMatches[1]/1024);
-}
-
-function getDatabaseDate(&$oDB)
-{
-    // Find the newest node in the DB
-    $iLastOSMID = $oDB->getOne("select max(osm_id) from place where osm_type = 'N'");
-    // Lookup the timestamp that node was created
-    $sLastNodeURL = 'https://www.openstreetmap.org/api/0.6/node/'.$iLastOSMID.'/1';
-    $sLastNodeXML = file_get_contents($sLastNodeURL);
-
-    if ($sLastNodeXML === false) {
-        return false;
-    }
-
-    preg_match('#timestamp="(([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})Z)"#', $sLastNodeXML, $aLastNodeDate);
-
-    return $aLastNodeDate[1];
-}
-
-
-function byImportance($a, $b)
-{
-    if ($a['importance'] != $b['importance']) {
-        return ($a['importance'] > $b['importance']?-1:1);
-    }
-
-    return $a['foundorder'] <=> $b['foundorder'];
-}
-
-
-function javascript_renderData($xVal, $iOptions = 0)
-{
-    $sCallback = isset($_GET['json_callback']) ? $_GET['json_callback'] : '';
-    if ($sCallback && !preg_match('/^[$_\p{L}][$_\p{L}\p{Nd}.[\]]*$/u', $sCallback)) {
-        // Unset, we call javascript_renderData again during exception handling
-        unset($_GET['json_callback']);
-        throw new Exception('Invalid json_callback value', 400);
-    }
-
-    $iOptions |= JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
-    if (isset($_GET['pretty']) && in_array(strtolower($_GET['pretty']), array('1', 'true'))) {
-        $iOptions |= JSON_PRETTY_PRINT;
-    }
-
-    $jsonout = json_encode($xVal, $iOptions);
-
-    if ($sCallback) {
-        header('Content-Type: application/javascript; charset=UTF-8');
-        echo $_GET['json_callback'].'('.$jsonout.')';
-    } else {
-        header('Content-Type: application/json; charset=UTF-8');
-        echo $jsonout;
-    }
-}
-
-function addQuotes($s)
-{
-    return "'".$s."'";
-}
-
-function parseLatLon($sQuery)
-{
-    $sFound    = null;
-    $fQueryLat = null;
-    $fQueryLon = null;
-
-    if (preg_match('/\\s*([NS])[\s]+([0-9]+[0-9.]*)[°\s]+([0-9.]+)?[′\']*[,\s]+([EW])[\s]+([0-9]+)[°\s]+([0-9]+[0-9.]*)[′\']*\\s*/', $sQuery, $aData)) {
-        /*               1          2                    3                     4          5             6
-         * degrees decimal minutes
-         * N 40 26.767, W 79 58.933
-         * N 40°26.767′, W 79°58.933′
-         */
-        $sFound    = $aData[0];
-        $fQueryLat = ($aData[1]=='N'?1:-1) * ($aData[2] + $aData[3]/60);
-        $fQueryLon = ($aData[4]=='E'?1:-1) * ($aData[5] + $aData[6]/60);
-    } elseif (preg_match('/\\s*([0-9]+)[°\s]+([0-9]+[0-9.]*)?[′\']*[\s]+([NS])[,\s]+([0-9]+)[°\s]+([0-9]+[0-9.]*)?[′\'\s]+([EW])\\s*/', $sQuery, $aData)) {
-        /*                     1             2                          3           4             5                       6
-         * degrees decimal minutes
-         * 40 26.767 N, 79 58.933 W
-         * 40° 26.767′ N 79° 58.933′ W
-         */
-        $sFound    = $aData[0];
-        $fQueryLat = ($aData[3]=='N'?1:-1) * ($aData[1] + $aData[2]/60);
-        $fQueryLon = ($aData[6]=='E'?1:-1) * ($aData[4] + $aData[5]/60);
-    } elseif (preg_match('/\\s*([NS])[\s]+([0-9]+)[°\s]+([0-9]+)[′\'\s]+([0-9]+)[″"]*[,\s]+([EW])[\s]+([0-9]+)[°\s]+([0-9]+)[′\'\s]+([0-9]+)[″"]*\\s*/', $sQuery, $aData)) {
-        /*                     1          2             3               4                  5          6             7               8
-         * degrees decimal seconds
-         * N 40 26 46 W 79 58 56
-         * N 40° 26′ 46″, W 79° 58′ 56″
-         */
-        $sFound    = $aData[0];
-        $fQueryLat = ($aData[1]=='N'?1:-1) * ($aData[2] + $aData[3]/60 + $aData[4]/3600);
-        $fQueryLon = ($aData[5]=='E'?1:-1) * ($aData[6] + $aData[7]/60 + $aData[8]/3600);
-    } elseif (preg_match('/\\s*([0-9]+)[°\s]+([0-9]+)[′\'\s]+([0-9]+[0-9.]*)[″"\s]+([NS])[,\s]+([0-9]+)[°\s]+([0-9]+)[′\'\s]+([0-9]+[0-9.]*)[″"\s]+([EW])\\s*/', $sQuery, $aData)) {
-        /*                     1             2               3                     4           5             6               7                     8
-         * degrees decimal seconds
-         * 40 26 46 N 79 58 56 W
-         * 40° 26′ 46″ N, 79° 58′ 56″ W
-         * 40° 26′ 46.78″ N, 79° 58′ 56.89″ W
-         */
-        $sFound    = $aData[0];
-        $fQueryLat = ($aData[4]=='N'?1:-1) * ($aData[1] + $aData[2]/60 + $aData[3]/3600);
-        $fQueryLon = ($aData[8]=='E'?1:-1) * ($aData[5] + $aData[6]/60 + $aData[7]/3600);
-    } elseif (preg_match('/\\s*([NS])[\s]+([0-9]+[0-9]*\\.[0-9]+)[°]*[,\s]+([EW])[\s]+([0-9]+[0-9]*\\.[0-9]+)[°]*\\s*/', $sQuery, $aData)) {
-        /*                     1          2                                3          4
-         * degrees decimal
-         * N 40.446° W 79.982°
-         */
-        $sFound    = $aData[0];
-        $fQueryLat = ($aData[1]=='N'?1:-1) * ($aData[2]);
-        $fQueryLon = ($aData[3]=='E'?1:-1) * ($aData[4]);
-    } elseif (preg_match('/\\s*([0-9]+[0-9]*\\.[0-9]+)[°\s]+([NS])[,\s]+([0-9]+[0-9]*\\.[0-9]+)[°\s]+([EW])\\s*/', $sQuery, $aData)) {
-        /*                     1                            2           3                            4
-         * degrees decimal
-         * 40.446° N 79.982° W
-         */
-        $sFound    = $aData[0];
-        $fQueryLat = ($aData[2]=='N'?1:-1) * ($aData[1]);
-        $fQueryLon = ($aData[4]=='E'?1:-1) * ($aData[3]);
-    } elseif (preg_match('/(\\s*\\[|^\\s*|\\s*)(-?[0-9]+[0-9]*\\.[0-9]+)[,\s]+(-?[0-9]+[0-9]*\\.[0-9]+)(\\]\\s*|\\s*$|\\s*)/', $sQuery, $aData)) {
-        /*                 1                   2                              3                        4
-         * degrees decimal
-         * 12.34, 56.78
-         * 12.34 56.78
-         * [12.456,-78.90]
-         */
-        $sFound    = $aData[0];
-        $fQueryLat = $aData[2];
-        $fQueryLon = $aData[3];
-    } else {
-        return false;
-    }
-
-    return array($sFound, $fQueryLat, $fQueryLon);
-}
-
-function addressRankToGeocodeJsonType($iAddressRank)
-{
-    if ($iAddressRank >= 29 && $iAddressRank <= 30) {
-        return 'house';
-    }
-    if ($iAddressRank >= 26 && $iAddressRank < 28) {
-        return 'street';
-    }
-    if ($iAddressRank >= 22 && $iAddressRank < 26) {
-        return 'locality';
-    }
-    if ($iAddressRank >= 17 && $iAddressRank < 22) {
-        return 'district';
-    }
-    if ($iAddressRank >= 13 && $iAddressRank < 17) {
-        return 'city';
-    }
-    if ($iAddressRank >= 10 && $iAddressRank < 13) {
-        return 'county';
-    }
-    if ($iAddressRank >= 5 && $iAddressRank < 10) {
-        return 'state';
-    }
-    if ($iAddressRank >= 4 && $iAddressRank < 5) {
-        return 'country';
-    }
-
-    return 'locality';
-}
-
-if (!function_exists('array_key_last')) {
-    function array_key_last(array $array)
-    {
-        if (!empty($array)) {
-            return key(array_slice($array, -1, 1, true));
-        }
-    }
-}
diff --git a/lib-php/log.php b/lib-php/log.php
deleted file mode 100644 (file)
index 1d56773..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-
-function logStart(&$oDB, $sType = '', $sQuery = '', $aLanguageList = array())
-{
-    $fStartTime = microtime(true);
-    $aStartTime = explode('.', $fStartTime);
-    if (!isset($aStartTime[1])) {
-        $aStartTime[1] = '0';
-    }
-
-    $sOutputFormat = '';
-    if (isset($_GET['format'])) {
-        $sOutputFormat = $_GET['format'];
-    }
-
-    if ($sType == 'reverse') {
-        $sOutQuery = (isset($_GET['lat'])?$_GET['lat']:'').'/';
-        if (isset($_GET['lon'])) {
-            $sOutQuery .= $_GET['lon'];
-        }
-        if (isset($_GET['zoom'])) {
-            $sOutQuery .= '/'.$_GET['zoom'];
-        }
-    } else {
-        $sOutQuery = $sQuery;
-    }
-
-    $hLog = array(
-             date('Y-m-d H:i:s', $aStartTime[0]).'.'.$aStartTime[1],
-             $_SERVER['REMOTE_ADDR'],
-             $_SERVER['QUERY_STRING'],
-             $sOutQuery,
-             $sType,
-             $fStartTime
-            );
-
-    if (CONST_Log_DB) {
-        if (isset($_GET['email'])) {
-            $sUserAgent = $_GET['email'];
-        } elseif (isset($_SERVER['HTTP_REFERER'])) {
-            $sUserAgent = $_SERVER['HTTP_REFERER'];
-        } elseif (isset($_SERVER['HTTP_USER_AGENT'])) {
-            $sUserAgent = $_SERVER['HTTP_USER_AGENT'];
-        } else {
-            $sUserAgent = '';
-        }
-        $sSQL = 'insert into new_query_log (type,starttime,query,ipaddress,useragent,language,format,searchterm)';
-        $sSQL .= ' values (';
-        $sSQL .= join(',', $oDB->getDBQuotedList(array(
-            $sType,
-            $hLog[0],
-            $hLog[2],
-            $hLog[1],
-            $sUserAgent,
-            join(',', $aLanguageList),
-            $sOutputFormat,
-            $hLog[3]
-        )));
-        $sSQL .= ')';
-        $oDB->exec($sSQL);
-    }
-
-    return $hLog;
-}
-
-function logEnd(&$oDB, $hLog, $iNumResults)
-{
-    $fEndTime = microtime(true);
-
-    if (CONST_Log_DB) {
-        $aEndTime = explode('.', $fEndTime);
-        if (!isset($aEndTime[1])) {
-            $aEndTime[1] = '0';
-        }
-        $sEndTime = date('Y-m-d H:i:s', $aEndTime[0]).'.'.$aEndTime[1];
-
-        $sSQL = 'update new_query_log set endtime = '.$oDB->getDBQuoted($sEndTime).', results = '.$iNumResults;
-        $sSQL .= ' where starttime = '.$oDB->getDBQuoted($hLog[0]);
-        $sSQL .= ' and ipaddress = '.$oDB->getDBQuoted($hLog[1]);
-        $sSQL .= ' and query = '.$oDB->getDBQuoted($hLog[2]);
-        $oDB->exec($sSQL);
-    }
-
-    if (CONST_Log_File) {
-        $aOutdata = sprintf(
-            "[%s] %.4f %d %s \"%s\"\n",
-            $hLog[0],
-            $fEndTime-$hLog[5],
-            $iNumResults,
-            $hLog[4],
-            $hLog[2]
-        );
-        file_put_contents(CONST_Log_File, $aOutdata, FILE_APPEND | LOCK_EX);
-    }
-}
diff --git a/lib-php/output.php b/lib-php/output.php
deleted file mode 100644 (file)
index 44c4dde..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-
-function formatOSMType($sType, $bIncludeExternal = true)
-{
-    if ($sType == 'N') {
-        return 'node';
-    }
-    if ($sType == 'W') {
-        return 'way';
-    }
-    if ($sType == 'R') {
-        return 'relation';
-    }
-
-    if (!$bIncludeExternal) {
-        return '';
-    }
-
-    if ($sType == 'T') {
-        return 'way';
-    }
-    if ($sType == 'I') {
-        return 'way';
-    }
-
-    // not handled: P, L
-
-    return '';
-}
diff --git a/lib-php/setup_functions.php b/lib-php/setup_functions.php
deleted file mode 100755 (executable)
index 400834d..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-function getOsm2pgsqlBinary()
-{
-    $sBinary = getSetting('OSM2PGSQL_BINARY');
-
-    return $sBinary ? $sBinary : CONST_Default_Osm2pgsql;
-}
-
-function getImportStyle()
-{
-    $sStyle = getSetting('IMPORT_STYLE');
-
-    if (in_array($sStyle, array('admin', 'street', 'address', 'full', 'extratags'))) {
-        return CONST_ConfigDir.'/import-'.$sStyle.'.style';
-    }
-
-    return $sStyle;
-}
diff --git a/lib-php/template/address-geocodejson.php b/lib-php/template/address-geocodejson.php
deleted file mode 100644 (file)
index 28c605f..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-// https://github.com/geocoders/geocodejson-spec/
-
-$aFilteredPlaces = array();
-
-if (empty($aPlace)) {
-    if (isset($sError)) {
-        $aFilteredPlaces['error'] = $sError;
-    } else {
-        $aFilteredPlaces['error'] = 'Unable to geocode';
-    }
-    javascript_renderData($aFilteredPlaces);
-} else {
-    $aFilteredPlaces = array(
-                        'type' => 'Feature',
-                        'properties' => array(
-                                         'geocoding' => array()
-                                        )
-                       );
-
-    if (isset($aPlace['place_id'])) {
-        $aFilteredPlaces['properties']['geocoding']['place_id'] = $aPlace['place_id'];
-    }
-    $sOSMType = formatOSMType($aPlace['osm_type']);
-    if ($sOSMType) {
-        $aFilteredPlaces['properties']['geocoding']['osm_type'] = $sOSMType;
-        $aFilteredPlaces['properties']['geocoding']['osm_id'] = $aPlace['osm_id'];
-    }
-
-    $aFilteredPlaces['properties']['geocoding']['osm_key'] = $aPlace['class'];
-    $aFilteredPlaces['properties']['geocoding']['osm_value'] = $aPlace['type'];
-
-    $aFilteredPlaces['properties']['geocoding']['type'] = addressRankToGeocodeJsonType($aPlace['rank_address']);
-
-    $aFilteredPlaces['properties']['geocoding']['accuracy'] = (int) $fDistance;
-
-    $aFilteredPlaces['properties']['geocoding']['label'] = $aPlace['langaddress'];
-
-    if ($aPlace['placename'] !== null) {
-        $aFilteredPlaces['properties']['geocoding']['name'] = $aPlace['placename'];
-    }
-
-    if (isset($aPlace['address'])) {
-        $aPlace['address']->addGeocodeJsonAddressParts(
-            $aFilteredPlaces['properties']['geocoding']
-        );
-
-        $aFilteredPlaces['properties']['geocoding']['admin']
-            = $aPlace['address']->getAdminLevels();
-    }
-
-    if (isset($aPlace['asgeojson'])) {
-        $aFilteredPlaces['geometry'] = json_decode($aPlace['asgeojson'], true);
-    } else {
-        $aFilteredPlaces['geometry'] = array(
-                                        'type' => 'Point',
-                                        'coordinates' => array(
-                                                          (float) $aPlace['lon'],
-                                                          (float) $aPlace['lat']
-                                                         )
-                                       );
-    }
-
-    javascript_renderData(array(
-                           'type' => 'FeatureCollection',
-                           'geocoding' => array(
-                                           'version' => '0.1.0',
-                                           'attribution' => 'Data Â© OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright',
-                                           'licence' => 'ODbL',
-                                           'query' => $sQuery
-                                          ),
-                           'features' => array($aFilteredPlaces)
-                          ));
-}
diff --git a/lib-php/template/address-geojson.php b/lib-php/template/address-geojson.php
deleted file mode 100644 (file)
index dc3c383..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-$aFilteredPlaces = array();
-
-if (empty($aPlace)) {
-    if (isset($sError)) {
-        $aFilteredPlaces['error'] = $sError;
-    } else {
-        $aFilteredPlaces['error'] = 'Unable to geocode';
-    }
-    javascript_renderData($aFilteredPlaces);
-} else {
-    $aFilteredPlaces = array(
-                        'type' => 'Feature',
-                        'properties' => array()
-                       );
-
-    if (isset($aPlace['place_id'])) {
-        $aFilteredPlaces['properties']['place_id'] = $aPlace['place_id'];
-    }
-    $sOSMType = formatOSMType($aPlace['osm_type']);
-    if ($sOSMType) {
-        $aFilteredPlaces['properties']['osm_type'] = $sOSMType;
-        $aFilteredPlaces['properties']['osm_id'] = $aPlace['osm_id'];
-    }
-
-    $aFilteredPlaces['properties']['place_rank'] = $aPlace['rank_search'];
-
-    $aFilteredPlaces['properties']['category'] = $aPlace['class'];
-    $aFilteredPlaces['properties']['type'] = $aPlace['type'];
-
-    $aFilteredPlaces['properties']['importance'] = $aPlace['importance'];
-
-    $aFilteredPlaces['properties']['addresstype'] = strtolower($aPlace['addresstype']);
-
-    $aFilteredPlaces['properties']['name'] = $aPlace['placename'];
-
-    $aFilteredPlaces['properties']['display_name'] = $aPlace['langaddress'];
-
-    if (isset($aPlace['address'])) {
-        $aFilteredPlaces['properties']['address'] = $aPlace['address']->getAddressNames();
-    }
-    if (isset($aPlace['sExtraTags'])) {
-        $aFilteredPlaces['properties']['extratags'] = $aPlace['sExtraTags'];
-    }
-    if (isset($aPlace['sNameDetails'])) {
-        $aFilteredPlaces['properties']['namedetails'] = $aPlace['sNameDetails'];
-    }
-
-    if (isset($aPlace['aBoundingBox'])) {
-        $aFilteredPlaces['bbox'] = array(
-                                    (float) $aPlace['aBoundingBox'][2], // minlon
-                                    (float) $aPlace['aBoundingBox'][0], // minlat
-                                    (float) $aPlace['aBoundingBox'][3], // maxlon
-                                    (float) $aPlace['aBoundingBox'][1]  // maxlat
-                                   );
-    }
-
-    if (isset($aPlace['asgeojson'])) {
-        $aFilteredPlaces['geometry'] = json_decode($aPlace['asgeojson'], true);
-    } else {
-        $aFilteredPlaces['geometry'] = array(
-                                        'type' => 'Point',
-                                        'coordinates' => array(
-                                                          (float) $aPlace['lon'],
-                                                          (float) $aPlace['lat']
-                                                         )
-                                       );
-    }
-
-
-    javascript_renderData(array(
-                           'type' => 'FeatureCollection',
-                           'licence' => 'Data Â© OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright',
-                           'features' => array($aFilteredPlaces)
-                          ));
-}
diff --git a/lib-php/template/address-json.php b/lib-php/template/address-json.php
deleted file mode 100644 (file)
index 0766eaf..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-$aFilteredPlaces = array();
-
-if (empty($aPlace)) {
-    if (isset($sError)) {
-        $aFilteredPlaces['error'] = $sError;
-    } 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';
-    $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'];
-    }
-
-    if ($sOutputFormat == 'jsonv2' || $sOutputFormat == 'geojson') {
-        $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['address'])) {
-        $aFilteredPlaces['address'] = $aPlace['address']->getAddressNames();
-    }
-    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'], true);
-    }
-
-    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);
diff --git a/lib-php/template/address-xml.php b/lib-php/template/address-xml.php
deleted file mode 100644 (file)
index c418a4c..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-header('content-type: text/xml; charset=UTF-8');
-
-echo '<';
-echo '?xml version="1.0" encoding="UTF-8" ?';
-echo ">\n";
-
-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 (empty($aPlace)) {
-    if (isset($sError)) {
-        echo "<error>$sError</error>";
-    } 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'])) {
-        echo ' boundingbox="';
-        echo join(',', $aPlace['aBoundingBox']);
-        echo '"';
-    }
-    echo " place_rank='".$aPlace['rank_search']."'";
-    echo " address_rank='".$aPlace['rank_address']."'";
-
-
-    if (isset($aPlace['asgeojson'])) {
-        echo ' geojson=\'';
-        echo $aPlace['asgeojson'];
-        echo '\'';
-    }
-
-    if (isset($aPlace['assvg'])) {
-        echo ' geosvg=\'';
-        echo $aPlace['assvg'];
-        echo '\'';
-    }
-
-    if (isset($aPlace['astext'])) {
-        echo ' geotext=\'';
-        echo $aPlace['astext'];
-        echo '\'';
-    }
-    echo '>'.htmlspecialchars($aPlace['langaddress']).'</result>';
-
-    if (isset($aPlace['address'])) {
-        echo '<addressparts>';
-        foreach ($aPlace['address']->getAddressNames() as $sKey => $sValue) {
-            $sKey = str_replace(' ', '_', $sKey);
-            echo "<$sKey>";
-            echo htmlspecialchars($sValue);
-            echo "</$sKey>";
-        }
-        echo '</addressparts>';
-    }
-
-    if (isset($aPlace['sExtraTags'])) {
-        echo '<extratags>';
-        foreach ($aPlace['sExtraTags'] as $sKey => $sValue) {
-            echo '<tag key="'.htmlspecialchars($sKey).'" value="'.htmlspecialchars($sValue).'"/>';
-        }
-        echo '</extratags>';
-    }
-
-    if (isset($aPlace['sNameDetails'])) {
-        echo '<namedetails>';
-        foreach ($aPlace['sNameDetails'] as $sKey => $sValue) {
-            echo '<name desc="'.htmlspecialchars($sKey).'">';
-            echo htmlspecialchars($sValue);
-            echo '</name>';
-        }
-        echo '</namedetails>';
-    }
-
-    if (isset($aPlace['askml'])) {
-        echo "\n<geokml>";
-        echo $aPlace['askml'];
-        echo '</geokml>';
-    }
-}
-
-echo '</reversegeocode>';
diff --git a/lib-php/template/details-json.php b/lib-php/template/details-json.php
deleted file mode 100644 (file)
index ae80a85..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-$aPlaceDetails = array();
-
-$aPlaceDetails['place_id'] = (int) $aPointDetails['place_id'];
-$aPlaceDetails['parent_place_id'] = (int) $aPointDetails['parent_place_id'];
-
-$aPlaceDetails['osm_type'] = $aPointDetails['osm_type'];
-$aPlaceDetails['osm_id'] = (int) $aPointDetails['osm_id'];
-
-$aPlaceDetails['category'] = $aPointDetails['class'];
-$aPlaceDetails['type'] = $aPointDetails['type'];
-$aPlaceDetails['admin_level'] = $aPointDetails['admin_level'];
-
-$aPlaceDetails['localname'] = $aPointDetails['localname'];
-$aPlaceDetails['names'] = $aPointDetails['aNames'];
-
-$aPlaceDetails['addresstags'] = $aPointDetails['aAddressTags'];
-$aPlaceDetails['housenumber'] = $aPointDetails['housenumber'];
-$aPlaceDetails['calculated_postcode'] = $aPointDetails['postcode'];
-$aPlaceDetails['country_code'] = $aPointDetails['country_code'];
-
-$aPlaceDetails['indexed_date'] = (new DateTime('@'.$aPointDetails['indexed_epoch']))->format(DateTime::RFC3339);
-$aPlaceDetails['importance'] = (float) $aPointDetails['importance'];
-$aPlaceDetails['calculated_importance'] = (float) $aPointDetails['calculated_importance'];
-
-$aPlaceDetails['extratags'] = $aPointDetails['aExtraTags'];
-$aPlaceDetails['calculated_wikipedia'] = $aPointDetails['wikipedia'];
-$sIcon = Nominatim\ClassTypes\getIconFile($aPointDetails);
-if (isset($sIcon)) {
-    $aPlaceDetails['icon'] = $sIcon;
-}
-
-$aPlaceDetails['rank_address'] = (int) $aPointDetails['rank_address'];
-$aPlaceDetails['rank_search'] = (int) $aPointDetails['rank_search'];
-
-$aPlaceDetails['isarea'] = $aPointDetails['isarea'];
-$aPlaceDetails['centroid'] = array(
-                              'type' => 'Point',
-                              'coordinates' => array( (float) $aPointDetails['lon'], (float) $aPointDetails['lat'] )
-                             );
-
-$aPlaceDetails['geometry'] = json_decode($aPointDetails['asgeojson'], true);
-
-$funcMapAddressLine = function ($aFull) {
-    return array(
-            'localname' => $aFull['localname'],
-            'place_id' => isset($aFull['place_id']) ? (int) $aFull['place_id'] : null,
-            'osm_id' => isset($aFull['osm_id']) ? (int) $aFull['osm_id'] : null,
-            'osm_type' => isset($aFull['osm_type']) ? $aFull['osm_type'] : null,
-            'place_type' => isset($aFull['place_type']) ? $aFull['place_type'] : null,
-            'class' => $aFull['class'],
-            'type' => $aFull['type'],
-            'admin_level' => isset($aFull['admin_level']) ? (int) $aFull['admin_level'] : null,
-            'rank_address' => $aFull['rank_address'] ? (int) $aFull['rank_address'] : null,
-            'distance' => (float) $aFull['distance'],
-            'isaddress' => isset($aFull['isaddress']) ? (bool) $aFull['isaddress'] : null
-           );
-};
-
-$funcMapKeyword = function ($aFull) {
-    return array(
-            'id' => (int) $aFull['word_id'],
-            'token' => $aFull['word_token']
-           );
-};
-
-if ($aAddressLines) {
-    $aPlaceDetails['address'] = array_map($funcMapAddressLine, $aAddressLines);
-}
-
-if ($aLinkedLines) {
-    $aPlaceDetails['linked_places'] = array_map($funcMapAddressLine, $aLinkedLines);
-}
-
-if ($bIncludeKeywords) {
-    $aPlaceDetails['keywords'] = array();
-
-    if ($aPlaceSearchNameKeywords) {
-        $aPlaceDetails['keywords']['name'] = array_map($funcMapKeyword, $aPlaceSearchNameKeywords);
-    } else {
-        $aPlaceDetails['keywords']['name'] = array();
-    }
-
-    if ($aPlaceSearchAddressKeywords) {
-        $aPlaceDetails['keywords']['address'] = array_map($funcMapKeyword, $aPlaceSearchAddressKeywords);
-    } else {
-        $aPlaceDetails['keywords']['address'] = array();
-    }
-}
-
-if ($bIncludeHierarchy) {
-    if ($bGroupHierarchy) {
-        $aPlaceDetails['hierarchy'] = array();
-        foreach ($aHierarchyLines as $aAddressLine) {
-            if ($aAddressLine['type'] == 'yes') {
-                $sType = $aAddressLine['class'];
-            } else {
-                $sType = $aAddressLine['type'];
-            }
-
-            if (!isset($aPlaceDetails['hierarchy'][$sType])) {
-                $aPlaceDetails['hierarchy'][$sType] = array();
-            }
-            $aPlaceDetails['hierarchy'][$sType][] = $funcMapAddressLine($aAddressLine);
-        }
-    } else {
-        $aPlaceDetails['hierarchy'] = array_map($funcMapAddressLine, $aHierarchyLines);
-    }
-}
-
-javascript_renderData($aPlaceDetails);
diff --git a/lib-php/template/error-json.php b/lib-php/template/error-json.php
deleted file mode 100644 (file)
index fea7d5c..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-    $error = array(
-              'code' => $exception->getCode(),
-              'message' => $exception->getMessage()
-             );
-
-    if (CONST_Debug) {
-        $error['details'] = $exception->getFile() . '('. $exception->getLine() . ')';
-    }
-
-    javascript_renderData(array('error' => $error));
diff --git a/lib-php/template/error-xml.php b/lib-php/template/error-xml.php
deleted file mode 100644 (file)
index a21ac19..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<error>
-    <code><?php echo $exception->getCode() ?></code>
-    <message><?php echo $exception->getMessage() ?></message>
-    <?php if (CONST_Debug) { ?>
-    <details><?php echo $exception->getFile() . '('. $exception->getLine() . ')' ?></details>
-    <?php } ?>
-</error>
\ No newline at end of file
diff --git a/lib-php/template/search-batch-json.php b/lib-php/template/search-batch-json.php
deleted file mode 100644 (file)
index 430237a..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-$aOutput = array();
-$aOutput['licence'] = 'Data Â© OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright';
-$aOutput['batch'] = array();
-
-foreach ($aBatchResults as $aSearchResults) {
-    if (!$aSearchResults) {
-        $aSearchResults = array();
-    }
-    $aFilteredPlaces = array();
-    foreach ($aSearchResults as $iResNum => $aPointDetails) {
-        $aPlace = array(
-                   'place_id'=>$aPointDetails['place_id'],
-                  );
-
-        $sOSMType = formatOSMType($aPointDetails['osm_type']);
-        if ($sOSMType) {
-            $aPlace['osm_type'] = $sOSMType;
-            $aPlace['osm_id'] = $aPointDetails['osm_id'];
-        }
-
-        if (isset($aPointDetails['aBoundingBox'])) {
-            $aPlace['boundingbox'] = array(
-                                      $aPointDetails['aBoundingBox'][0],
-                                      $aPointDetails['aBoundingBox'][1],
-                                      $aPointDetails['aBoundingBox'][2],
-                $aPointDetails['aBoundingBox'][3]
-                                     );
-        }
-
-        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'])) {
-            $aPlace['address'] = $aPointDetails['address']->getAddressNames();
-        }
-
-        if (isset($aPointDetails['asgeojson'])) {
-            $aPlace['geojson'] = json_decode($aPointDetails['asgeojson'], true);
-        }
-
-        if (isset($aPointDetails['assvg'])) {
-            $aPlace['svg'] = $aPointDetails['assvg'];
-        }
-
-        if (isset($aPointDetails['astext'])) {
-            $aPlace['geotext'] = $aPointDetails['astext'];
-        }
-
-        if (isset($aPointDetails['askml'])) {
-            $aPlace['geokml'] = $aPointDetails['askml'];
-        }
-
-        $aFilteredPlaces[] = $aPlace;
-    }
-    $aOutput['batch'][] = $aFilteredPlaces;
-}
-
-javascript_renderData($aOutput, array('geojson'));
diff --git a/lib-php/template/search-geocodejson.php b/lib-php/template/search-geocodejson.php
deleted file mode 100644 (file)
index bba41a0..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-$aFilteredPlaces = array();
-foreach ($aSearchResults as $iResNum => $aPointDetails) {
-    $aPlace = array(
-               'type' => 'Feature',
-               'properties' => array(
-                                'geocoding' => array()
-                               )
-              );
-
-    if (isset($aPointDetails['place_id'])) {
-        $aPlace['properties']['geocoding']['place_id'] = $aPointDetails['place_id'];
-    }
-    $sOSMType = formatOSMType($aPointDetails['osm_type']);
-    if ($sOSMType) {
-        $aPlace['properties']['geocoding']['osm_type'] = $sOSMType;
-        $aPlace['properties']['geocoding']['osm_id'] = $aPointDetails['osm_id'];
-    }
-    $aPlace['properties']['geocoding']['osm_key'] = $aPointDetails['class'];
-    $aPlace['properties']['geocoding']['osm_value'] = $aPointDetails['type'];
-
-    $aPlace['properties']['geocoding']['type'] = addressRankToGeocodeJsonType($aPointDetails['rank_address']);
-
-    $aPlace['properties']['geocoding']['label'] = $aPointDetails['langaddress'];
-
-    if ($aPointDetails['placename'] !== null) {
-        $aPlace['properties']['geocoding']['name'] = $aPointDetails['placename'];
-    }
-
-    if (isset($aPointDetails['address'])) {
-        $aPointDetails['address']->addGeocodeJsonAddressParts(
-            $aPlace['properties']['geocoding']
-        );
-
-        $aPlace['properties']['geocoding']['admin']
-            = $aPointDetails['address']->getAdminLevels();
-    }
-
-    if (isset($aPointDetails['asgeojson'])) {
-        $aPlace['geometry'] = json_decode($aPointDetails['asgeojson'], true);
-    } else {
-        $aPlace['geometry'] = array(
-                               'type' => 'Point',
-                               'coordinates' => array(
-                                                 (float) $aPointDetails['lon'],
-                                                 (float) $aPointDetails['lat']
-                                                )
-                              );
-    }
-    $aFilteredPlaces[] = $aPlace;
-}
-
-
-javascript_renderData(array(
-                       'type' => 'FeatureCollection',
-                       'geocoding' => array(
-                                       'version' => '0.1.0',
-                                       'attribution' => 'Data Â© OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright',
-                                       'licence' => 'ODbL',
-                                       'query' => $sQuery
-                                      ),
-                       'features' => $aFilteredPlaces
-                      ));
diff --git a/lib-php/template/search-geojson.php b/lib-php/template/search-geojson.php
deleted file mode 100644 (file)
index 7665700..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-$aFilteredPlaces = array();
-foreach ($aSearchResults as $iResNum => $aPointDetails) {
-    $aPlace = array(
-               'type' => 'Feature',
-               'properties' => array(
-                                'place_id'=>$aPointDetails['place_id'],
-                               )
-              );
-
-    $sOSMType = formatOSMType($aPointDetails['osm_type']);
-    if ($sOSMType) {
-        $aPlace['properties']['osm_type'] = $sOSMType;
-        $aPlace['properties']['osm_id'] = $aPointDetails['osm_id'];
-    }
-
-    if (isset($aPointDetails['aBoundingBox'])) {
-        $aPlace['bbox'] = array(
-                           (float) $aPointDetails['aBoundingBox'][2], // minlon
-                           (float) $aPointDetails['aBoundingBox'][0], // minlat
-                           (float) $aPointDetails['aBoundingBox'][3], // maxlon
-                           (float) $aPointDetails['aBoundingBox'][1]  // maxlat
-                          );
-    }
-
-    if (isset($aPointDetails['zoom'])) {
-        $aPlace['properties']['zoom'] = $aPointDetails['zoom'];
-    }
-
-    $aPlace['properties']['display_name'] = $aPointDetails['name'];
-
-    $aPlace['properties']['place_rank'] = $aPointDetails['rank_search'];
-    $aPlace['properties']['category'] = $aPointDetails['class'];
-
-    $aPlace['properties']['type'] = $aPointDetails['type'];
-
-    $aPlace['properties']['importance'] = $aPointDetails['importance'];
-
-    if (isset($aPointDetails['icon']) && $aPointDetails['icon']) {
-        $aPlace['properties']['icon'] = $aPointDetails['icon'];
-    }
-
-    if (isset($aPointDetails['address'])) {
-        $aPlace['properties']['address'] = $aPointDetails['address']->getAddressNames();
-    }
-
-    if (isset($aPointDetails['asgeojson'])) {
-        $aPlace['geometry'] = json_decode($aPointDetails['asgeojson'], true);
-    } else {
-        $aPlace['geometry'] = array(
-                               'type' => 'Point',
-                               'coordinates' => array(
-                                                 (float) $aPointDetails['lon'],
-                                                 (float) $aPointDetails['lat']
-                                                )
-                              );
-    }
-
-
-    if (isset($aPointDetails['sExtraTags'])) {
-        $aPlace['properties']['extratags'] = $aPointDetails['sExtraTags'];
-    }
-    if (isset($aPointDetails['sNameDetails'])) {
-        $aPlace['properties']['namedetails'] = $aPointDetails['sNameDetails'];
-    }
-
-    $aFilteredPlaces[] = $aPlace;
-}
-
-javascript_renderData(array(
-                       'type' => 'FeatureCollection',
-                       'licence' => 'Data Â© OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright',
-                       'features' => $aFilteredPlaces
-                      ));
diff --git a/lib-php/template/search-json.php b/lib-php/template/search-json.php
deleted file mode 100644 (file)
index 5fb1302..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-$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['zoom'])) {
-        $aPlace['zoom'] = $aPointDetails['zoom'];
-    }
-
-    $aPlace['lat'] = $aPointDetails['lat'];
-    $aPlace['lon'] = $aPointDetails['lon'];
-
-    $aPlace['display_name'] = $aPointDetails['name'];
-
-    if ($sOutputFormat == 'jsonv2' || $sOutputFormat == 'geojson') {
-        $aPlace['place_rank'] = $aPointDetails['rank_search'];
-        $aPlace['category'] = $aPointDetails['class'];
-    } else {
-        $aPlace['class'] = $aPointDetails['class'];
-    }
-    $aPlace['type'] = $aPointDetails['type'];
-
-    $aPlace['importance'] = $aPointDetails['importance'];
-
-    if (isset($aPointDetails['icon']) && $aPointDetails['icon']) {
-        $aPlace['icon'] = $aPointDetails['icon'];
-    }
-
-    if (isset($aPointDetails['address'])) {
-        $aPlace['address'] = $aPointDetails['address']->getAddressNames();
-    }
-
-    if (isset($aPointDetails['asgeojson'])) {
-        $aPlace['geojson'] = json_decode($aPointDetails['asgeojson'], true);
-    }
-
-    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);
diff --git a/lib-php/template/search-xml.php b/lib-php/template/search-xml.php
deleted file mode 100644 (file)
index 8dda65e..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-header('content-type: text/xml; charset=UTF-8');
-
-echo '<';
-echo '?xml version="1.0" encoding="UTF-8" ?';
-echo ">\n";
-
-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)."'";
-}
-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) {
-    echo "<place place_id='".$aResult['place_id']."'";
-    $sOSMType = formatOSMType($aResult['osm_type']);
-    if ($sOSMType) {
-        echo " osm_type='$sOSMType'";
-        echo " osm_id='".$aResult['osm_id']."'";
-    }
-    echo " place_rank='".$aResult['rank_search']."'";
-    echo " address_rank='".$aResult['rank_address']."'";
-
-    if (isset($aResult['aBoundingBox'])) {
-        echo ' boundingbox="';
-        echo join(',', $aResult['aBoundingBox']);
-        echo '"';
-    }
-
-    if (isset($aResult['asgeojson'])) {
-        echo ' geojson=\'';
-        echo $aResult['asgeojson'];
-        echo '\'';
-    }
-
-    if (isset($aResult['assvg'])) {
-        echo ' geosvg=\'';
-        echo $aResult['assvg'];
-        echo '\'';
-    }
-
-    if (isset($aResult['astext'])) {
-        echo ' geotext=\'';
-        echo $aResult['astext'];
-        echo '\'';
-    }
-
-    if (isset($aResult['zoom'])) {
-        echo " zoom='".$aResult['zoom']."'";
-    }
-
-    echo " lat='".$aResult['lat']."'";
-    echo " lon='".$aResult['lon']."'";
-    echo " display_name='".htmlspecialchars($aResult['name'], ENT_QUOTES)."'";
-
-    echo " class='".htmlspecialchars($aResult['class'])."'";
-    echo " type='".htmlspecialchars($aResult['type'], ENT_QUOTES)."'";
-    echo " importance='".htmlspecialchars($aResult['importance'])."'";
-    if (isset($aResult['icon']) && $aResult['icon']) {
-        echo " icon='".htmlspecialchars($aResult['icon'], ENT_QUOTES)."'";
-    }
-
-    $bHasDelim = false;
-
-    if (isset($aResult['askml'])) {
-        if (!$bHasDelim) {
-            $bHasDelim = true;
-            echo '>';
-        }
-        echo "\n<geokml>";
-        echo $aResult['askml'];
-        echo '</geokml>';
-    }
-
-    if (isset($aResult['sExtraTags'])) {
-        if (!$bHasDelim) {
-            $bHasDelim = true;
-            echo '>';
-        }
-        echo "\n<extratags>";
-        foreach ($aResult['sExtraTags'] as $sKey => $sValue) {
-            echo '<tag key="'.htmlspecialchars($sKey).'" value="'.htmlspecialchars($sValue).'"/>';
-        }
-        echo '</extratags>';
-    }
-
-    if (isset($aResult['sNameDetails'])) {
-        if (!$bHasDelim) {
-            $bHasDelim = true;
-            echo '>';
-        }
-        echo "\n<namedetails>";
-        foreach ($aResult['sNameDetails'] as $sKey => $sValue) {
-            echo '<name desc="'.htmlspecialchars($sKey).'">';
-            echo htmlspecialchars($sValue);
-            echo '</name>';
-        }
-        echo '</namedetails>';
-    }
-
-    if (isset($aResult['address'])) {
-        if (!$bHasDelim) {
-            $bHasDelim = true;
-            echo '>';
-        }
-        echo "\n";
-        foreach ($aResult['address']->getAddressNames() as $sKey => $sValue) {
-            $sKey = str_replace(' ', '_', $sKey);
-            echo "<$sKey>";
-            echo htmlspecialchars($sValue);
-            echo "</$sKey>";
-        }
-    }
-
-    if ($bHasDelim) {
-        echo '</place>';
-    } else {
-        echo '/>';
-    }
-}
-
-echo '</' . (isset($sXmlRootTag)?$sXmlRootTag:'searchresults') . '>';
diff --git a/lib-php/tokenizer/icu_tokenizer.php b/lib-php/tokenizer/icu_tokenizer.php
deleted file mode 100644 (file)
index e45d076..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim;
-
-require_once(CONST_LibDir.'/SimpleWordList.php');
-
-class Tokenizer
-{
-    private $oDB;
-
-    private $oNormalizer;
-    private $oTransliterator;
-
-    public function __construct(&$oDB)
-    {
-        $this->oDB =& $oDB;
-        $this->oNormalizer = \Transliterator::createFromRules(CONST_Term_Normalization_Rules);
-        $this->oTransliterator = \Transliterator::createFromRules(CONST_Transliteration);
-    }
-
-    public function checkStatus()
-    {
-        $sSQL = 'SELECT word_id FROM word WHERE word_id is not null limit 1';
-        $iWordID = $this->oDB->getOne($sSQL);
-        if ($iWordID === false) {
-            throw new \Exception('Query failed', 703);
-        }
-        if (!$iWordID) {
-            throw new \Exception('No value', 704);
-        }
-    }
-
-
-    public function normalizeString($sTerm)
-    {
-        if ($this->oNormalizer === null) {
-            return $sTerm;
-        }
-
-        return $this->oNormalizer->transliterate($sTerm);
-    }
-
-
-    public function mostFrequentWords($iNum)
-    {
-        $sSQL = "SELECT word FROM word WHERE type = 'W'";
-        $sSQL .= "ORDER BY info->'count' DESC LIMIT ".$iNum;
-        return $this->oDB->getCol($sSQL);
-    }
-
-
-    private function makeStandardWord($sTerm)
-    {
-        return trim($this->oTransliterator->transliterate(' '.$sTerm.' '));
-    }
-
-
-    public function tokensForSpecialTerm($sTerm)
-    {
-        $aResults = array();
-
-        $sSQL = "SELECT word_id, info->>'class' as class, info->>'type' as type ";
-        $sSQL .= '   FROM word WHERE word_token = :term and type = \'S\'';
-
-        Debug::printVar('Term', $sTerm);
-        Debug::printSQL($sSQL);
-        $aSearchWords = $this->oDB->getAll($sSQL, array(':term' => $this->makeStandardWord($sTerm)));
-
-        Debug::printVar('Results', $aSearchWords);
-
-        foreach ($aSearchWords as $aSearchTerm) {
-            $aResults[] = new \Nominatim\Token\SpecialTerm(
-                $aSearchTerm['word_id'],
-                $aSearchTerm['class'],
-                $aSearchTerm['type'],
-                \Nominatim\Operator::TYPE
-            );
-        }
-
-        Debug::printVar('Special term tokens', $aResults);
-
-        return $aResults;
-    }
-
-
-    public function extractTokensFromPhrases(&$aPhrases)
-    {
-        $sNormQuery = '';
-        $aWordLists = array();
-        $aTokens = array();
-        foreach ($aPhrases as $iPhrase => $oPhrase) {
-            $sNormQuery .= ','.$this->normalizeString($oPhrase->getPhrase());
-            $sPhrase = $this->makeStandardWord($oPhrase->getPhrase());
-            Debug::printVar('Phrase', $sPhrase);
-
-            $oWordList = new SimpleWordList($sPhrase);
-            $aTokens = array_merge($aTokens, $oWordList->getTokens());
-            $aWordLists[] = $oWordList;
-        }
-
-        Debug::printVar('Tokens', $aTokens);
-        Debug::printVar('WordLists', $aWordLists);
-
-        $oValidTokens = $this->computeValidTokens($aTokens, $sNormQuery);
-
-        foreach ($aPhrases as $iPhrase => $oPhrase) {
-            $oPhrase->setWordSets($aWordLists[$iPhrase]->getWordSets($oValidTokens));
-        }
-
-        return $oValidTokens;
-    }
-
-
-    private function computeValidTokens($aTokens, $sNormQuery)
-    {
-        $oValidTokens = new TokenList();
-
-        if (!empty($aTokens)) {
-            $this->addTokensFromDB($oValidTokens, $aTokens, $sNormQuery);
-
-            // Try more interpretations for Tokens that could not be matched.
-            foreach ($aTokens as $sToken) {
-                if ($sToken[0] != ' ' && !$oValidTokens->contains($sToken)) {
-                    if (preg_match('/^([0-9]{5}) [0-9]{4}$/', $sToken, $aData)) {
-                        // US ZIP+4 codes - merge in the 5-digit ZIP code
-                        $oValidTokens->addToken(
-                            $sToken,
-                            new Token\Postcode(null, $aData[1], 'us')
-                        );
-                    } elseif (preg_match('/^[0-9]+$/', $sToken)) {
-                        // Unknown single word token with a number.
-                        // Assume it is a house number.
-                        $oValidTokens->addToken(
-                            $sToken,
-                            new Token\HouseNumber(null, trim($sToken))
-                        );
-                    }
-                }
-            }
-        }
-
-        return $oValidTokens;
-    }
-
-
-    private function addTokensFromDB(&$oValidTokens, $aTokens, $sNormQuery)
-    {
-        // Check which tokens we have, get the ID numbers
-        $sSQL = 'SELECT word_id, word_token, type, word,';
-        $sSQL .= "      info->>'op' as operator,";
-        $sSQL .= "      info->>'class' as class, info->>'type' as ctype,";
-        $sSQL .= "      info->>'count' as count,";
-        $sSQL .= "      info->>'lookup' as lookup";
-        $sSQL .= ' FROM word WHERE word_token in (';
-        $sSQL .= join(',', $this->oDB->getDBQuotedList($aTokens)).')';
-
-        Debug::printSQL($sSQL);
-
-        $aDBWords = $this->oDB->getAll($sSQL, null, 'Could not get word tokens.');
-
-        foreach ($aDBWords as $aWord) {
-            $iId = (int) $aWord['word_id'];
-            $sTok = $aWord['word_token'];
-
-            switch ($aWord['type']) {
-                case 'C':  // country name tokens
-                    if ($aWord['word'] !== null) {
-                        $oValidTokens->addToken(
-                            $sTok,
-                            new Token\Country($iId, $aWord['word'])
-                        );
-                    }
-                    break;
-                case 'H':  // house number tokens
-                    $sLookup = $aWord['lookup'] ?? $aWord['word_token'];
-                    $oValidTokens->addToken($sTok, new Token\HouseNumber($iId, $sLookup));
-                    break;
-                case 'P':  // postcode tokens
-                    // Postcodes are not normalized, so they may have content
-                    // that makes SQL injection possible. Reject postcodes
-                    // that would need special escaping.
-                    if ($aWord['word'] !== null
-                        && pg_escape_string($aWord['word']) == $aWord['word']
-                    ) {
-                        $iSplitPos = strpos($aWord['word'], '@');
-                        if ($iSplitPos === false) {
-                            $sPostcode = $aWord['word'];
-                        } else {
-                            $sPostcode = substr($aWord['word'], 0, $iSplitPos);
-                        }
-
-                        $oValidTokens->addToken(
-                            $sTok,
-                            new Token\Postcode($iId, $sPostcode, null)
-                        );
-                    }
-                    break;
-                case 'S':  // tokens for classification terms (special phrases)
-                    if ($aWord['class'] !== null && $aWord['ctype'] !== null) {
-                        $oValidTokens->addToken($sTok, new Token\SpecialTerm(
-                            $iId,
-                            $aWord['class'],
-                            $aWord['ctype'],
-                            (isset($aWord['operator'])) ? Operator::NEAR : Operator::NONE
-                        ));
-                    }
-                    break;
-                case 'W': // full-word tokens
-                    $oValidTokens->addToken($sTok, new Token\Word(
-                        $iId,
-                        (int) $aWord['count'],
-                        substr_count($aWord['word_token'], ' ')
-                    ));
-                    break;
-                case 'w':  // partial word terms
-                    $oValidTokens->addToken($sTok, new Token\Partial(
-                        $iId,
-                        $aWord['word_token'],
-                        (int) $aWord['count']
-                    ));
-                    break;
-                default:
-                    break;
-            }
-        }
-    }
-}
diff --git a/lib-php/tokenizer/legacy_tokenizer.php b/lib-php/tokenizer/legacy_tokenizer.php
deleted file mode 100644 (file)
index 6f3d230..0000000
+++ /dev/null
@@ -1,265 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-namespace Nominatim;
-
-require_once(CONST_LibDir.'/SimpleWordList.php');
-
-class Tokenizer
-{
-    private $oDB;
-
-    private $oNormalizer = null;
-
-    public function __construct(&$oDB)
-    {
-        $this->oDB =& $oDB;
-        $this->oNormalizer = \Transliterator::createFromRules(CONST_Term_Normalization_Rules);
-    }
-
-    public function checkStatus()
-    {
-        $sStandardWord = $this->oDB->getOne("SELECT make_standard_name('a')");
-        if ($sStandardWord === false) {
-            throw new \Exception('Module failed', 701);
-        }
-
-        if ($sStandardWord != 'a') {
-            throw new \Exception('Module call failed', 702);
-        }
-
-        $sSQL = "SELECT word_id FROM word WHERE word_token IN (' a')";
-        $iWordID = $this->oDB->getOne($sSQL);
-        if ($iWordID === false) {
-            throw new \Exception('Query failed', 703);
-        }
-        if (!$iWordID) {
-            throw new \Exception('No value', 704);
-        }
-    }
-
-
-    public function normalizeString($sTerm)
-    {
-        if ($this->oNormalizer === null) {
-            return $sTerm;
-        }
-
-        return $this->oNormalizer->transliterate($sTerm);
-    }
-
-
-    public function mostFrequentWords($iNum)
-    {
-        $sSQL = 'SELECT word FROM word WHERE word is not null ';
-        $sSQL .= 'ORDER BY search_name_count DESC LIMIT '.$iNum;
-        return $this->oDB->getCol($sSQL);
-    }
-
-
-    public function tokensForSpecialTerm($sTerm)
-    {
-        $aResults = array();
-
-        $sSQL = 'SELECT word_id, class, type FROM word ';
-        $sSQL .= '   WHERE word_token = \' \' || make_standard_name(:term)';
-        $sSQL .= '   AND class is not null AND class not in (\'place\')';
-
-        Debug::printVar('Term', $sTerm);
-        Debug::printSQL($sSQL);
-        $aSearchWords = $this->oDB->getAll($sSQL, array(':term' => $sTerm));
-
-        Debug::printVar('Results', $aSearchWords);
-
-        foreach ($aSearchWords as $aSearchTerm) {
-            $aResults[] = new \Nominatim\Token\SpecialTerm(
-                $aSearchTerm['word_id'],
-                $aSearchTerm['class'],
-                $aSearchTerm['type'],
-                \Nominatim\Operator::TYPE
-            );
-        }
-
-        Debug::printVar('Special term tokens', $aResults);
-
-        return $aResults;
-    }
-
-
-    public function extractTokensFromPhrases(&$aPhrases)
-    {
-        // First get the normalized version of all phrases
-        $sNormQuery = '';
-        $sSQL = 'SELECT ';
-        $aParams = array();
-        foreach ($aPhrases as $iPhrase => $oPhrase) {
-            $sNormQuery .= ','.$this->normalizeString($oPhrase->getPhrase());
-            $sSQL .= 'make_standard_name(:' .$iPhrase.') as p'.$iPhrase.',';
-            $aParams[':'.$iPhrase] = $oPhrase->getPhrase();
-
-            // Conflicts between US state abbreviations and various words
-            // for 'the' in different languages
-            switch (strtolower($oPhrase->getPhrase())) {
-                case 'il':
-                    $aParams[':'.$iPhrase] = 'illinois';
-                    break;
-                case 'al':
-                    $aParams[':'.$iPhrase] = 'alabama';
-                    break;
-                case 'la':
-                    $aParams[':'.$iPhrase] = 'louisiana';
-                    break;
-                default:
-                    $aParams[':'.$iPhrase] = $oPhrase->getPhrase();
-                    break;
-            }
-        }
-        $sSQL = substr($sSQL, 0, -1);
-
-        Debug::printSQL($sSQL);
-        Debug::printVar('SQL parameters', $aParams);
-
-        $aNormPhrases = $this->oDB->getRow($sSQL, $aParams);
-
-        Debug::printVar('SQL result', $aNormPhrases);
-
-        // now compute all possible tokens
-        $aWordLists = array();
-        $aTokens = array();
-        foreach ($aNormPhrases as $sPhrase) {
-            $oWordList = new SimpleWordList($sPhrase);
-
-            foreach ($oWordList->getTokens() as $sToken) {
-                $aTokens[' '.$sToken] = ' '.$sToken;
-                $aTokens[$sToken] = $sToken;
-            }
-
-            $aWordLists[] = $oWordList;
-        }
-
-        Debug::printVar('Tokens', $aTokens);
-        Debug::printVar('WordLists', $aWordLists);
-
-        $oValidTokens = $this->computeValidTokens($aTokens, $sNormQuery);
-
-        foreach ($aPhrases as $iPhrase => $oPhrase) {
-            $oPhrase->setWordSets($aWordLists[$iPhrase]->getWordSets($oValidTokens));
-        }
-
-        return $oValidTokens;
-    }
-
-
-    private function computeValidTokens($aTokens, $sNormQuery)
-    {
-        $oValidTokens = new TokenList();
-
-        if (!empty($aTokens)) {
-            $this->addTokensFromDB($oValidTokens, $aTokens, $sNormQuery);
-
-            // Try more interpretations for Tokens that could not be matched.
-            foreach ($aTokens as $sToken) {
-                if ($sToken[0] != ' ' && !$oValidTokens->contains($sToken)) {
-                    if (preg_match('/^([0-9]{5}) [0-9]{4}$/', $sToken, $aData)) {
-                        // US ZIP+4 codes - merge in the 5-digit ZIP code
-                        $oValidTokens->addToken(
-                            $sToken,
-                            new Token\Postcode(null, $aData[1], 'us')
-                        );
-                    } elseif (preg_match('/^[0-9]+$/', $sToken)) {
-                        // Unknown single word token with a number.
-                        // Assume it is a house number.
-                        $oValidTokens->addToken(
-                            $sToken,
-                            new Token\HouseNumber(null, trim($sToken))
-                        );
-                    }
-                }
-            }
-        }
-
-        return $oValidTokens;
-    }
-
-
-    private function addTokensFromDB(&$oValidTokens, $aTokens, $sNormQuery)
-    {
-        // Check which tokens we have, get the ID numbers
-        $sSQL = 'SELECT word_id, word_token, word, class, type, country_code,';
-        $sSQL .= ' operator, coalesce(search_name_count, 0) as count';
-        $sSQL .= ' FROM word WHERE word_token in (';
-        $sSQL .= join(',', $this->oDB->getDBQuotedList($aTokens)).')';
-
-        Debug::printSQL($sSQL);
-
-        $aDBWords = $this->oDB->getAll($sSQL, null, 'Could not get word tokens.');
-
-        foreach ($aDBWords as $aWord) {
-            $oToken = null;
-            $iId = (int) $aWord['word_id'];
-
-            if ($aWord['class']) {
-                // Special terms need to appear in their normalized form.
-                // (postcodes are not normalized in the word table)
-                $sNormWord = $this->normalizeString($aWord['word']);
-                if ($aWord['word'] && strpos($sNormQuery, $sNormWord) === false) {
-                    continue;
-                }
-
-                if ($aWord['class'] == 'place' && $aWord['type'] == 'house') {
-                    $oToken = new Token\HouseNumber($iId, trim($aWord['word_token']));
-                } elseif ($aWord['class'] == 'place' && $aWord['type'] == 'postcode') {
-                    if ($aWord['word']
-                        && pg_escape_string($aWord['word']) == $aWord['word']
-                    ) {
-                        $oToken = new Token\Postcode(
-                            $iId,
-                            $aWord['word'],
-                            $aWord['country_code']
-                        );
-                    }
-                } else {
-                    // near and in operator the same at the moment
-                    $oToken = new Token\SpecialTerm(
-                        $iId,
-                        $aWord['class'],
-                        $aWord['type'],
-                        $aWord['operator'] ? Operator::NEAR : Operator::NONE
-                    );
-                }
-            } elseif ($aWord['country_code']) {
-                $oToken = new Token\Country($iId, $aWord['country_code']);
-            } elseif ($aWord['word_token'][0] == ' ') {
-                $oToken = new Token\Word(
-                    $iId,
-                    (int) $aWord['count'],
-                    substr_count($aWord['word_token'], ' ')
-                );
-            // For backward compatibility: ignore all partial tokens with more
-            // than one word.
-            } elseif (strpos($aWord['word_token'], ' ') === false) {
-                $oToken = new Token\Partial(
-                    $iId,
-                    $aWord['word_token'],
-                    (int) $aWord['count']
-                );
-            }
-
-            if ($oToken) {
-                // remove any leading spaces
-                if ($aWord['word_token'][0] == ' ') {
-                    $oValidTokens->addToken(substr($aWord['word_token'], 1), $oToken);
-                } else {
-                    $oValidTokens->addToken($aWord['word_token'], $oToken);
-                }
-            }
-        }
-    }
-}
diff --git a/lib-php/website/deletable.php b/lib-php/website/deletable.php
deleted file mode 100644 (file)
index ffb202f..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-require_once(CONST_LibDir.'/init-website.php');
-require_once(CONST_LibDir.'/log.php');
-require_once(CONST_LibDir.'/output.php');
-ini_set('memory_limit', '200M');
-
-$oParams = new Nominatim\ParameterParser();
-$sOutputFormat = $oParams->getSet('format', array('json'), 'json');
-set_exception_handler_by_format($sOutputFormat);
-
-$oDB = new Nominatim\DB(CONST_Database_DSN);
-$oDB->connect();
-
-$sSQL = 'select placex.place_id, country_code,';
-$sSQL .= " name->'name' as name, i.* from placex, import_polygon_delete i";
-$sSQL .= ' where placex.osm_id = i.osm_id and placex.osm_type = i.osm_type';
-$sSQL .= ' and placex.class = i.class and placex.type = i.type';
-$aPolygons = $oDB->getAll($sSQL, null, 'Could not get list of deleted OSM elements.');
-
-if (CONST_Debug) {
-    var_dump($aPolygons);
-    exit;
-}
-
-if ($sOutputFormat == 'json') {
-    javascript_renderData($aPolygons);
-}
diff --git a/lib-php/website/details.php b/lib-php/website/details.php
deleted file mode 100644 (file)
index 98fb6ef..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-require_once(CONST_LibDir.'/init-website.php');
-require_once(CONST_LibDir.'/log.php');
-require_once(CONST_LibDir.'/output.php');
-require_once(CONST_LibDir.'/AddressDetails.php');
-ini_set('memory_limit', '200M');
-
-$oParams = new Nominatim\ParameterParser();
-
-$sOutputFormat = $oParams->getSet('format', array('json'), 'json');
-set_exception_handler_by_format($sOutputFormat);
-
-$aLangPrefOrder = $oParams->getPreferredLanguages();
-
-$sPlaceId = $oParams->getString('place_id');
-$sOsmType = $oParams->getSet('osmtype', array('N', 'W', 'R'));
-$iOsmId = $oParams->getInt('osmid', 0);
-$sClass = $oParams->getString('class');
-
-$bIncludeKeywords = $oParams->getBool('keywords', false);
-$bIncludeAddressDetails = $oParams->getBool('addressdetails', false);
-$bIncludeLinkedPlaces = $oParams->getBool('linkedplaces', true);
-$bIncludeHierarchy = $oParams->getBool('hierarchy', false);
-$bGroupHierarchy = $oParams->getBool('group_hierarchy', false);
-$bIncludePolygonAsGeoJSON = $oParams->getBool('polygon_geojson', false);
-
-$oDB = new Nominatim\DB(CONST_Database_DSN);
-$oDB->connect();
-
-$sLanguagePrefArraySQL = $oDB->getArraySQL($oDB->getDBQuotedList($aLangPrefOrder));
-
-if ($sOsmType && $iOsmId !== 0) {
-    $sSQL = 'SELECT place_id FROM placex WHERE osm_type = :type AND osm_id = :id';
-    $aSQLParams = array(':type' => $sOsmType, ':id' => $iOsmId);
-    // osm_type and osm_id are not unique enough
-    if ($sClass) {
-        $sSQL .= ' AND class= :class';
-        $aSQLParams[':class'] = $sClass;
-    }
-    $sSQL .= ' ORDER BY class ASC';
-    $sPlaceId = $oDB->getOne($sSQL, $aSQLParams);
-
-
-    // Nothing? Maybe it's an interpolation.
-    // XXX Simply returns the first parent street it finds. It should
-    //     get a house number and get the right interpolation.
-    if (!$sPlaceId && $sOsmType == 'W' && (!$sClass || $sClass == 'place')) {
-        $sSQL = 'SELECT place_id FROM location_property_osmline'
-                .' WHERE osm_id = :id LIMIT 1';
-        $sPlaceId = $oDB->getOne($sSQL, array(':id' => $iOsmId));
-    }
-
-    // Be nice about our error messages for broken geometry
-
-    if (!$sPlaceId && $oDB->tableExists('import_polygon_error')) {
-        $sSQL = 'SELECT ';
-        $sSQL .= '    osm_type, ';
-        $sSQL .= '    osm_id, ';
-        $sSQL .= '    errormessage, ';
-        $sSQL .= '    class, ';
-        $sSQL .= '    type, ';
-        $sSQL .= "    get_name_by_language(name,$sLanguagePrefArraySQL) AS localname,";
-        $sSQL .= '    ST_AsText(prevgeometry) AS prevgeom, ';
-        $sSQL .= '    ST_AsText(newgeometry) AS newgeom';
-        $sSQL .= ' FROM import_polygon_error ';
-        $sSQL .= ' WHERE osm_type = :type';
-        $sSQL .= '   AND osm_id = :id';
-        $sSQL .= ' ORDER BY updated DESC';
-        $sSQL .= ' LIMIT 1';
-        $aPointDetails = $oDB->getRow($sSQL, array(':type' => $sOsmType, ':id' => $iOsmId));
-        if ($aPointDetails) {
-            if (preg_match('/\[(-?\d+\.\d+) (-?\d+\.\d+)\]/', $aPointDetails['errormessage'], $aMatches)) {
-                $aPointDetails['error_x'] = $aMatches[1];
-                $aPointDetails['error_y'] = $aMatches[2];
-            } else {
-                $aPointDetails['error_x'] = 0;
-                $aPointDetails['error_y'] = 0;
-            }
-            include(CONST_LibDir.'/template/details-error-'.$sOutputFormat.'.php');
-            exit;
-        }
-    }
-
-    if ($sPlaceId === false) {
-        throw new \Exception('No place with that OSM ID found.', 404);
-    }
-} else {
-    if ($sPlaceId === false) {
-        userError('Required parameters missing. Need either osmtype/osmid or place_id.');
-    }
-}
-
-$iPlaceID = (int)$sPlaceId;
-
-if (CONST_Use_US_Tiger_Data) {
-    $iParentPlaceID = $oDB->getOne('SELECT parent_place_id FROM location_property_tiger WHERE place_id = '.$iPlaceID);
-    if ($iParentPlaceID) {
-        $iPlaceID = $iParentPlaceID;
-    }
-}
-
-// interpolated house numbers
-$iParentPlaceID = $oDB->getOne('SELECT parent_place_id FROM location_property_osmline WHERE place_id = '.$iPlaceID);
-if ($iParentPlaceID) {
-    $iPlaceID = $iParentPlaceID;
-}
-
-// artificial postcodes
-$iParentPlaceID = $oDB->getOne('SELECT parent_place_id FROM location_postcode WHERE place_id = '.$iPlaceID);
-if ($iParentPlaceID) {
-    $iPlaceID = $iParentPlaceID;
-}
-
-$hLog = logStart($oDB, 'details', $_SERVER['QUERY_STRING'], $aLangPrefOrder);
-
-// Get the details for this point
-$sSQL = 'SELECT place_id, osm_type, osm_id, class, type, name, admin_level,';
-$sSQL .= '    housenumber, postcode, country_code,';
-$sSQL .= '    importance, wikipedia,';
-$sSQL .= '    ROUND(EXTRACT(epoch FROM indexed_date)) AS indexed_epoch,';
-$sSQL .= '    parent_place_id, ';
-$sSQL .= '    rank_address, ';
-$sSQL .= '    rank_search, ';
-$sSQL .= "    get_name_by_language(name,$sLanguagePrefArraySQL) AS localname, ";
-$sSQL .= "    ST_GeometryType(geometry) in ('ST_Polygon','ST_MultiPolygon') AS isarea, ";
-$sSQL .= '    ST_y(centroid) AS lat, ';
-$sSQL .= '    ST_x(centroid) AS lon, ';
-$sSQL .= '    CASE ';
-$sSQL .= '       WHEN importance = 0 OR importance IS NULL ';
-$sSQL .= '       THEN 0.75-(rank_search::float/40) ';
-$sSQL .= '       ELSE importance ';
-$sSQL .= '       END as calculated_importance, ';
-if ($bIncludePolygonAsGeoJSON) {
-    $sSQL .= '    ST_AsGeoJSON(CASE ';
-    $sSQL .= '                WHEN ST_NPoints(geometry) > 5000 ';
-    $sSQL .= '                THEN ST_SimplifyPreserveTopology(geometry, 0.0001) ';
-    $sSQL .= '                ELSE geometry ';
-    $sSQL .= '                END) as asgeojson';
-} else {
-    $sSQL .= '    ST_AsGeoJSON(centroid) as asgeojson';
-}
-$sSQL .= ' FROM placex ';
-$sSQL .= " WHERE place_id = $iPlaceID";
-
-$aPointDetails = $oDB->getRow($sSQL, null, 'Could not get details of place object.');
-
-if (!$aPointDetails) {
-    throw new \Exception('No place with that place ID found.', 404);
-}
-
-$aPointDetails['localname'] = $aPointDetails['localname']?$aPointDetails['localname']:$aPointDetails['housenumber'];
-
-// Get all alternative names (languages, etc)
-$sSQL = 'SELECT (each(name)).key,(each(name)).value FROM placex ';
-$sSQL .= "WHERE place_id = $iPlaceID ORDER BY (each(name)).key";
-$aPointDetails['aNames'] = $oDB->getAssoc($sSQL);
-
-// Address tags
-$sSQL = 'SELECT (each(address)).key as key,(each(address)).value FROM placex ';
-$sSQL .= "WHERE place_id = $iPlaceID ORDER BY key";
-$aPointDetails['aAddressTags'] = $oDB->getAssoc($sSQL);
-
-// Extra tags
-$sSQL = 'SELECT (each(extratags)).key,(each(extratags)).value FROM placex ';
-$sSQL .= "WHERE place_id = $iPlaceID ORDER BY (each(extratags)).key";
-$aPointDetails['aExtraTags'] = $oDB->getAssoc($sSQL);
-
-// Address
-$aAddressLines = false;
-if ($bIncludeAddressDetails) {
-    $oDetails = new Nominatim\AddressDetails($oDB, $iPlaceID, -1, $sLanguagePrefArraySQL);
-    $aAddressLines = $oDetails->getAddressDetails(true);
-}
-
-// Linked places
-$aLinkedLines = false;
-if ($bIncludeLinkedPlaces) {
-    $sSQL = 'SELECT placex.place_id, osm_type, osm_id, class, type, housenumber,';
-    $sSQL .= ' admin_level, rank_address, ';
-    $sSQL .= " ST_GeometryType(geometry) in ('ST_Polygon','ST_MultiPolygon') AS isarea,";
-    $sSQL .= " ST_DistanceSpheroid(geometry, placegeometry, 'SPHEROID[\"WGS 84\",6378137,298.257223563, AUTHORITY[\"EPSG\",\"7030\"]]') AS distance, ";
-    $sSQL .= " get_name_by_language(name,$sLanguagePrefArraySQL) AS localname, ";
-    $sSQL .= ' length(name::text) AS namelength ';
-    $sSQL .= ' FROM ';
-    $sSQL .= '    placex, ';
-    $sSQL .= '    ( ';
-    $sSQL .= '      SELECT centroid AS placegeometry ';
-    $sSQL .= '      FROM placex ';
-    $sSQL .= "      WHERE place_id = $iPlaceID ";
-    $sSQL .= '    ) AS x';
-    $sSQL .= " WHERE linked_place_id = $iPlaceID";
-    $sSQL .= ' ORDER BY ';
-    $sSQL .= '   rank_address ASC, ';
-    $sSQL .= '   rank_search ASC, ';
-    $sSQL .= "   get_name_by_language(name, $sLanguagePrefArraySQL), ";
-    $sSQL .= '   housenumber';
-    $aLinkedLines = $oDB->getAll($sSQL);
-}
-
-// All places this is an immediate parent of
-$aHierarchyLines = false;
-if ($bIncludeHierarchy) {
-    $sSQL = 'SELECT obj.place_id, osm_type, osm_id, class, type, housenumber,';
-    $sSQL .= " admin_level, rank_address, ST_GeometryType(geometry) in ('ST_Polygon','ST_MultiPolygon') AS isarea,";
-    $sSQL .= " ST_DistanceSpheroid(geometry, placegeometry, 'SPHEROID[\"WGS 84\",6378137,298.257223563, AUTHORITY[\"EPSG\",\"7030\"]]') AS distance, ";
-    $sSQL .= " get_name_by_language(name,$sLanguagePrefArraySQL) AS localname, ";
-    $sSQL .= ' length(name::text) AS namelength ';
-    $sSQL .= ' FROM ';
-    $sSQL .= '    ( ';
-    $sSQL .= '      SELECT placex.place_id, osm_type, osm_id, class, type, housenumber, admin_level, rank_address, rank_search, geometry, name ';
-    $sSQL .= '      FROM placex ';
-    $sSQL .= "      WHERE parent_place_id = $iPlaceID ";
-    $sSQL .= '      ORDER BY ';
-    $sSQL .= '         rank_address ASC, ';
-    $sSQL .= '         rank_search ASC ';
-    $sSQL .= '      LIMIT 500 ';
-    $sSQL .= '    ) AS obj,';
-    $sSQL .= '    ( ';
-    $sSQL .= '      SELECT centroid AS placegeometry ';
-    $sSQL .= '      FROM placex ';
-    $sSQL .= "      WHERE place_id = $iPlaceID ";
-    $sSQL .= '    ) AS x';
-    $sSQL .= ' ORDER BY ';
-    $sSQL .= '    rank_address ASC, ';
-    $sSQL .= '    rank_search ASC, ';
-    $sSQL .= '    localname, ';
-    $sSQL .= '    housenumber';
-    $aHierarchyLines = $oDB->getAll($sSQL);
-}
-
-$aPlaceSearchNameKeywords = false;
-$aPlaceSearchAddressKeywords = false;
-if ($bIncludeKeywords) {
-    $sSQL = "SELECT * FROM search_name WHERE place_id = $iPlaceID";
-    $aPlaceSearchName = $oDB->getRow($sSQL);
-
-    if (!empty($aPlaceSearchName)) {
-        $sWordIds = substr($aPlaceSearchName['name_vector'], 1, -1);
-        if (!empty($sWordIds)) {
-            $sSQL = 'SELECT * FROM word WHERE word_id in ('.$sWordIds.')';
-            $aPlaceSearchNameKeywords = $oDB->getAll($sSQL);
-        }
-
-        $sWordIds = substr($aPlaceSearchName['nameaddress_vector'], 1, -1);
-        if (!empty($sWordIds)) {
-            $sSQL = 'SELECT * FROM word WHERE word_id in ('.$sWordIds.')';
-            $aPlaceSearchAddressKeywords = $oDB->getAll($sSQL);
-        }
-    }
-}
-
-logEnd($oDB, $hLog, 1);
-
-include(CONST_LibDir.'/template/details-'.$sOutputFormat.'.php');
diff --git a/lib-php/website/lookup.php b/lib-php/website/lookup.php
deleted file mode 100644 (file)
index 3a7ddb8..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-require_once(CONST_LibDir.'/init-website.php');
-require_once(CONST_LibDir.'/log.php');
-require_once(CONST_LibDir.'/PlaceLookup.php');
-require_once(CONST_LibDir.'/output.php');
-ini_set('memory_limit', '200M');
-
-$oParams = new Nominatim\ParameterParser();
-
-// Format for output
-$sOutputFormat = $oParams->getSet('format', array('xml', 'json', 'jsonv2', 'geojson', 'geocodejson'), 'xml');
-set_exception_handler_by_format($sOutputFormat);
-
-// Preferred language
-$aLangPrefOrder = $oParams->getPreferredLanguages();
-
-$oDB = new Nominatim\DB(CONST_Database_DSN);
-$oDB->connect();
-
-$hLog = logStart($oDB, 'place', $_SERVER['QUERY_STRING'], $aLangPrefOrder);
-
-$aSearchResults = array();
-$aCleanedQueryParts = array();
-
-$oPlaceLookup = new Nominatim\PlaceLookup($oDB);
-$oPlaceLookup->loadParamArray($oParams);
-$oPlaceLookup->setIncludeAddressDetails($oParams->getBool('addressdetails', true));
-
-$aOsmIds = explode(',', $oParams->getString('osm_ids', ''));
-
-if (count($aOsmIds) > CONST_Places_Max_ID_count) {
-    userError('Bulk User: Only ' . CONST_Places_Max_ID_count . ' ids are allowed in one request.');
-}
-
-foreach ($aOsmIds as $sItem) {
-    // Skip empty sItem
-    if (empty($sItem)) {
-        continue;
-    }
-
-    $sType = $sItem[0];
-    $iId = (int) substr($sItem, 1);
-    if ($iId > 0 && ($sType == 'N' || $sType == 'W' || $sType == 'R')) {
-        $aCleanedQueryParts[] = $sType . $iId;
-        $oPlace = $oPlaceLookup->lookupOSMID($sType, $iId);
-        if ($oPlace) {
-            // we want to use the search-* output templates, so we need to fill
-            // $aSearchResults and slightly change the (reverse search) oPlace
-            // key names
-            $oResult = $oPlace;
-            unset($oResult['aAddress']);
-            if (isset($oPlace['aAddress'])) {
-                $oResult['address'] = $oPlace['aAddress'];
-            }
-            if ($sOutputFormat != 'geocodejson') {
-                unset($oResult['langaddress']);
-                $oResult['name'] = $oPlace['langaddress'];
-            }
-
-            $aOutlineResult = $oPlaceLookup->getOutlines(
-                $oPlace['place_id'],
-                $oPlace['lon'],
-                $oPlace['lat'],
-                Nominatim\ClassTypes\getDefRadius($oPlace)
-            );
-
-            if ($aOutlineResult) {
-                $oResult = array_merge($oResult, $aOutlineResult);
-            }
-
-            $aSearchResults[] = $oResult;
-        }
-    }
-}
-
-
-if (CONST_Debug) {
-    exit;
-}
-
-$sXmlRootTag = 'lookupresults';
-$sQuery = join(',', $aCleanedQueryParts);
-// we initialize these to avoid warnings in our logfile
-$sViewBox = '';
-$bShowPolygons = '';
-$aExcludePlaceIDs = array();
-$sMoreURL = '';
-
-logEnd($oDB, $hLog, 1);
-
-$sOutputTemplate = ($sOutputFormat == 'jsonv2') ? 'json' : $sOutputFormat;
-include(CONST_LibDir.'/template/search-'.$sOutputTemplate.'.php');
diff --git a/lib-php/website/polygons.php b/lib-php/website/polygons.php
deleted file mode 100644 (file)
index 5a90abe..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-require_once(CONST_LibDir.'/init-website.php');
-require_once(CONST_LibDir.'/log.php');
-require_once(CONST_LibDir.'/output.php');
-ini_set('memory_limit', '200M');
-
-$oParams = new Nominatim\ParameterParser();
-$sOutputFormat = $oParams->getSet('format', array('json'), 'json');
-set_exception_handler_by_format($sOutputFormat);
-
-$iDays = $oParams->getInt('days', false);
-$bReduced = $oParams->getBool('reduced', false);
-$sClass = $oParams->getString('class', false);
-
-$oDB = new Nominatim\DB(CONST_Database_DSN);
-$oDB->connect();
-
-$iTotalBroken = (int) $oDB->getOne('SELECT count(*) FROM import_polygon_error');
-
-$aPolygons = array();
-while ($iTotalBroken && empty($aPolygons)) {
-    $sSQL = 'SELECT osm_type, osm_id, class, type, name->\'name\' as "name",';
-    $sSQL .= 'country_code, errormessage, updated';
-    $sSQL .= ' FROM import_polygon_error';
-
-    $aWhere = array();
-    if ($iDays) {
-        $aWhere[] = "updated > 'now'::timestamp - '".$iDays." day'::interval";
-        $iDays++;
-    }
-
-    if ($bReduced) {
-        $aWhere[] = "errormessage like 'Area reduced%'";
-    }
-    if ($sClass) {
-        $sWhere[] = "class = '".pg_escape_string($sClass)."'";
-    }
-
-    if (!empty($aWhere)) {
-        $sSQL .= ' WHERE '.join(' and ', $aWhere);
-    }
-
-    $sSQL .= ' ORDER BY updated desc LIMIT 1000';
-    $aPolygons = $oDB->getAll($sSQL);
-}
-
-if (CONST_Debug) {
-    var_dump($aPolygons);
-    exit;
-}
-
-if ($sOutputFormat == 'json') {
-    javascript_renderData($aPolygons);
-}
diff --git a/lib-php/website/reverse-only-search.php b/lib-php/website/reverse-only-search.php
deleted file mode 100644 (file)
index 43cbd26..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-require_once(CONST_LibDir.'/init-website.php');
-require_once(CONST_LibDir.'/ParameterParser.php');
-
-$oParams = new Nominatim\ParameterParser();
-
-// Format for output
-$sOutputFormat = $oParams->getSet('format', array('xml', 'json', 'jsonv2', 'geojson', 'geocodejson'), 'jsonv2');
-set_exception_handler_by_format($sOutputFormat);
-
-throw new Exception('Reverse-only import does not support forward searching.', 404);
diff --git a/lib-php/website/reverse.php b/lib-php/website/reverse.php
deleted file mode 100644 (file)
index f24c655..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-require_once(CONST_LibDir.'/init-website.php');
-require_once(CONST_LibDir.'/log.php');
-require_once(CONST_LibDir.'/PlaceLookup.php');
-require_once(CONST_LibDir.'/ReverseGeocode.php');
-require_once(CONST_LibDir.'/output.php');
-ini_set('memory_limit', '200M');
-
-$oParams = new Nominatim\ParameterParser();
-
-// Format for output
-$sOutputFormat = $oParams->getSet('format', array('xml', 'json', 'jsonv2', 'geojson', 'geocodejson'), 'xml');
-set_exception_handler_by_format($sOutputFormat);
-
-// Preferred language
-$aLangPrefOrder = $oParams->getPreferredLanguages();
-
-$oDB = new Nominatim\DB(CONST_Database_DSN);
-$oDB->connect();
-
-$hLog = logStart($oDB, 'reverse', $_SERVER['QUERY_STRING'], $aLangPrefOrder);
-
-$oPlaceLookup = new Nominatim\PlaceLookup($oDB);
-$oPlaceLookup->loadParamArray($oParams);
-$oPlaceLookup->setIncludeAddressDetails($oParams->getBool('addressdetails', true));
-
-$sOsmType = $oParams->getSet('osm_type', array('N', 'W', 'R'));
-$iOsmId = $oParams->getInt('osm_id', -1);
-$fLat = $oParams->getFloat('lat');
-$fLon = $oParams->getFloat('lon');
-$iZoom = $oParams->getInt('zoom', 18);
-
-if ($sOsmType && $iOsmId > 0) {
-    $aPlace = $oPlaceLookup->lookupOSMID($sOsmType, $iOsmId);
-} elseif ($fLat !== false && $fLon !== false) {
-    $oReverseGeocode = new Nominatim\ReverseGeocode($oDB);
-    $oReverseGeocode->setZoom($iZoom);
-
-    $oLookup = $oReverseGeocode->lookup($fLat, $fLon);
-
-    if ($oLookup) {
-        $aPlaces = $oPlaceLookup->lookup(array($oLookup->iId => $oLookup));
-        if (!empty($aPlaces)) {
-            $aPlace = reset($aPlaces);
-        }
-    }
-} else {
-    userError('Need coordinates or OSM object to lookup.');
-}
-
-if (isset($aPlace)) {
-    $aOutlineResult = $oPlaceLookup->getOutlines(
-        $aPlace['place_id'],
-        $aPlace['lon'],
-        $aPlace['lat'],
-        Nominatim\ClassTypes\getDefRadius($aPlace),
-        $fLat,
-        $fLon
-    );
-
-    if ($aOutlineResult) {
-        $aPlace = array_merge($aPlace, $aOutlineResult);
-    }
-} else {
-    $aPlace = array();
-}
-
-logEnd($oDB, $hLog, count($aPlace) ? 1 : 0);
-
-if (CONST_Debug) {
-    var_dump($aPlace);
-    exit;
-}
-
-if ($sOutputFormat == 'geocodejson') {
-    $sQuery = $fLat.','.$fLon;
-    if (isset($aPlace['place_id'])) {
-        $fDistance = $oDB->getOne(
-            'SELECT ST_Distance(ST_SetSRID(ST_Point(:lon,:lat),4326), centroid) FROM placex where place_id = :placeid',
-            array(':lon' => $fLon, ':lat' => $fLat, ':placeid' => $aPlace['place_id'])
-        );
-    }
-}
-
-$sOutputTemplate = ($sOutputFormat == 'jsonv2') ? 'json' : $sOutputFormat;
-include(CONST_LibDir.'/template/address-'.$sOutputTemplate.'.php');
diff --git a/lib-php/website/search.php b/lib-php/website/search.php
deleted file mode 100644 (file)
index e8f2398..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-require_once(CONST_LibDir.'/init-website.php');
-require_once(CONST_LibDir.'/log.php');
-require_once(CONST_LibDir.'/Geocode.php');
-require_once(CONST_LibDir.'/output.php');
-ini_set('memory_limit', '200M');
-
-$oDB = new Nominatim\DB(CONST_Database_DSN);
-$oDB->connect();
-$oParams = new Nominatim\ParameterParser();
-
-$oGeocode = new Nominatim\Geocode($oDB);
-
-$aLangPrefOrder = $oParams->getPreferredLanguages();
-$oGeocode->setLanguagePreference($aLangPrefOrder);
-
-// Format for output
-$sOutputFormat = $oParams->getSet('format', array('xml', 'json', 'jsonv2', 'geojson', 'geocodejson'), 'jsonv2');
-set_exception_handler_by_format($sOutputFormat);
-
-$oGeocode->loadParamArray($oParams, null);
-
-if (CONST_Search_BatchMode && isset($_GET['batch'])) {
-    $aBatch = json_decode($_GET['batch'], true);
-    $aBatchResults = array();
-    foreach ($aBatch as $aBatchParams) {
-        $oBatchGeocode = clone $oGeocode;
-        $oBatchParams = new Nominatim\ParameterParser($aBatchParams);
-        $oBatchGeocode->loadParamArray($oBatchParams);
-        $oBatchGeocode->setQueryFromParams($oBatchParams);
-        $aSearchResults = $oBatchGeocode->lookup();
-        $aBatchResults[] = $aSearchResults;
-    }
-    include(CONST_LibDir.'/template/search-batch-json.php');
-    exit;
-}
-
-$oGeocode->setQueryFromParams($oParams);
-
-if (!$oGeocode->getQueryString()
-    && isset($_SERVER['PATH_INFO'])
-    && strlen($_SERVER['PATH_INFO']) > 0
-    && $_SERVER['PATH_INFO'][0] == '/'
-) {
-    $sQuery = substr(rawurldecode($_SERVER['PATH_INFO']), 1);
-
-    // reverse order of '/' separated string
-    $aPhrases = explode('/', $sQuery);
-    $aPhrases = array_reverse($aPhrases);
-    $sQuery = join(', ', $aPhrases);
-    $oGeocode->setQuery($sQuery);
-}
-
-$hLog = logStart($oDB, 'search', $oGeocode->getQueryString(), $aLangPrefOrder);
-
-$aSearchResults = $oGeocode->lookup();
-
-logEnd($oDB, $hLog, count($aSearchResults));
-
-$sQuery = $oGeocode->getQueryString();
-
-$aMoreParams = $oGeocode->getMoreUrlParams();
-$aMoreParams['format'] = $sOutputFormat;
-if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
-    $aMoreParams['accept-language'] = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
-}
-
-if (isset($_SERVER['REQUEST_SCHEME'])
-    && isset($_SERVER['HTTP_HOST'])
-    && isset($_SERVER['DOCUMENT_URI'])
-) {
-    $sMoreURL = $_SERVER['REQUEST_SCHEME'].'://'
-                .$_SERVER['HTTP_HOST'].$_SERVER['DOCUMENT_URI'].'/?'
-                .http_build_query($aMoreParams);
-} else {
-    $sMoreURL = '/search.php?'.http_build_query($aMoreParams);
-}
-
-if (CONST_Debug) {
-    exit;
-}
-
-$sOutputTemplate = ($sOutputFormat == 'jsonv2') ? 'json' : $sOutputFormat;
-include(CONST_LibDir.'/template/search-'.$sOutputTemplate.'.php');
diff --git a/lib-php/website/status.php b/lib-php/website/status.php
deleted file mode 100644 (file)
index 2839f72..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-<?php
-/**
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * This file is part of Nominatim. (https://nominatim.org)
- *
- * Copyright (C) 2022 by the Nominatim developer community.
- * For a full list of authors see the git log.
- */
-
-require_once(CONST_LibDir.'/init-website.php');
-require_once(CONST_LibDir.'/ParameterParser.php');
-require_once(CONST_LibDir.'/Status.php');
-
-$oParams = new Nominatim\ParameterParser();
-$sOutputFormat = $oParams->getSet('format', array('text', 'json'), 'text');
-
-$oDB = new Nominatim\DB(CONST_Database_DSN);
-
-if ($sOutputFormat == 'json') {
-    header('content-type: application/json; charset=UTF-8');
-}
-
-
-try {
-    $oStatus = new Nominatim\Status($oDB);
-    $oStatus->status();
-
-    if ($sOutputFormat == 'json') {
-        $epoch = $oStatus->dataDate();
-        $aResponse = array(
-                      'status' => 0,
-                      'message' => 'OK',
-                      'data_updated' => (new DateTime('@'.$epoch))->format(DateTime::RFC3339),
-                      'software_version' => CONST_NominatimVersion
-                     );
-        $sDatabaseVersion = $oStatus->databaseVersion();
-        if ($sDatabaseVersion) {
-            $aResponse['database_version'] = $sDatabaseVersion;
-        }
-        javascript_renderData($aResponse);
-    } else {
-        echo 'OK';
-    }
-} catch (Exception $oErr) {
-    if ($sOutputFormat == 'json') {
-        $aResponse = array(
-                      'status' => $oErr->getCode(),
-                      'message' => $oErr->getMessage()
-                     );
-        javascript_renderData($aResponse);
-    } else {
-        header('HTTP/1.0 500 Internal Server Error');
-        echo 'ERROR: '.$oErr->getMessage();
-    }
-}