From: Sarah Hoffmann Date: Mon, 26 Mar 2018 18:57:29 +0000 (+0200) Subject: Merge remote-tracking branch 'upstream/master' X-Git-Tag: deploy~340 X-Git-Url: https://git.openstreetmap.org/nominatim.git/commitdiff_plain/9b76a8ffb4c4cd13628d85c00cf286382970b149?hp=ab54a4b8d7ba75f7a1ecd18de34bbce5af291b5b Merge remote-tracking branch 'upstream/master' --- diff --git a/VAGRANT.md b/VAGRANT.md index 2aafb7de..d4e88304 100644 --- a/VAGRANT.md +++ b/VAGRANT.md @@ -91,7 +91,7 @@ statements. ## Running functional tests -Tests in `/features/db` and `/features/osm2pgsql` have to pass 100%. Other +Tests in `test/bdd/db` and `test/bdd/osm2pgsql` have to pass 100%. Other tests might require full planet-wide data. Sadly even if you have your own planet-wide data there will be enough differences to the openstreetmap.org installation to cause false positives in the other tests (see FAQ). @@ -103,11 +103,11 @@ To run the full test suite To run a single file - behave -DBUILDDIR=/home/vagrant/build/ features/api/reverse.feature + behave -DBUILDDIR=/home/vagrant/build/ api/lookup/simple.feature Or a single test by line number - behave -DBUILDDIR=/home/vagrant/build/ features/api/reverse.feature:34 + behave -DBUILDDIR=/home/vagrant/build/ api/lookup/simple.feature:34 To run specific groups of tests you can add tags just before the `Scenario line`, e.g. diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index d2fe03d0..f335060f 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -9,6 +9,7 @@ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/appendix) ADD_CUSTOM_TARGET(doc COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_CURRENT_SOURCE_DIR}/admin ${CMAKE_CURRENT_BINARY_DIR}/admin COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_CURRENT_SOURCE_DIR}/develop ${CMAKE_CURRENT_BINARY_DIR}/develop + COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_CURRENT_SOURCE_DIR}/api ${CMAKE_CURRENT_BINARY_DIR}/api COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_CURRENT_SOURCE_DIR}/index.md ${CMAKE_CURRENT_BINARY_DIR}/index.md COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/bash2md.sh ${PROJECT_SOURCE_DIR}/vagrant/Install-on-Centos-7.sh ${CMAKE_CURRENT_BINARY_DIR}/appendix/Install-on-Centos-7.md COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/bash2md.sh ${PROJECT_SOURCE_DIR}/vagrant/Install-on-Ubuntu-16.sh ${CMAKE_CURRENT_BINARY_DIR}/appendix/Install-on-Ubuntu-16.md diff --git a/docs/api/Lookup.md b/docs/api/Lookup.md new file mode 100644 index 00000000..3b6472ad --- /dev/null +++ b/docs/api/Lookup.md @@ -0,0 +1,75 @@ +## Address lookup + +Lookup the address of one or multiple OSM objects like node, way or relation. + +### Parameters +``` + https://nominatim.openstreetmap.org/lookup? +``` + +* `format=[xml|json]` + + * Output format + +* `json_callback=` + + * Wrap json output in a callback function (JSONP) i.e. `()` + +* `accept-language=` + + * Preferred language order for showing search results, overrides the value specified in the "Accept-Language" HTTP header. + * Either uses standard rfc2616 accept-language string or a simple comma separated list of language codes. + +* `osm_ids=[N|W|R],…,[N|W|R]` + + * If you are making large numbers of request please include a valid email address or alternatively include your email address as part of the User-Agent string. + * This information will be kept confidential and only used to contact you in the event of a problem, see [Usage Policy](https://operations.osmfoundation.org/policies/nominatim/) for more details. + +* `extratags=1` + * Include additional information in the result if available, e.g. wikipedia link, opening hours. + +* `namedetails=1` + * Include a list of alternative names in the results. + * These may include language variants, references, operator and brand. + +### Example + +* [https://nominatim.openstreetmap.org/lookup?osm_ids=R146656,W104393803,N240109189](https://nominatim.openstreetmap.org/lookup?osm_ids=R146656,W104393803,N240109189) + +```xml + + + Manchester + Greater Manchester + North West England + England + United Kingdom + gb + + + Brandenburg Gate + 1 + Pariser Platz + Mitte + Mitte + Berlin + Berlin + 10117 + Germany + de + + + Berlin + Berlin + Germany + de + + +``` diff --git a/docs/api/Reverse.md b/docs/api/Reverse.md new file mode 100644 index 00000000..999827a1 --- /dev/null +++ b/docs/api/Reverse.md @@ -0,0 +1,132 @@ +## Reverse Geocoding + +Reverse geocoding generates an address from a latitude and longitude. The optional `zoom` parameter specifies the level of detail required in terms of something suitable for a Leaflet.js/OpenLayers/etc. zoom level. + +### Parameters +``` +https://nominatim.openstreetmap.org/reverse? +``` + +* `format=[xml|json|jsonv2]` + + * Output format. + * `jsonv2` adds the next fields to response: + * `place_rank` + * `category` + * `type` + * `importance` + * `addresstype` + +* `json_callback=` + + * Wrap json output in a callback function (JSONP) i.e. `()` + +* `accept-language=` + + * Preferred language order for showing search results, overrides the value specified in the "Accept-Language" HTTP header. + * Either uses standard rfc2616 accept-language string or a simple comma separated list of language codes. + +* `osm_type=[N|W|R]` `osm_id=` + * A specific osm node / way / relation to return an address for + * **Please use this in preference to lat/lon where possible** + +* `lat=` `lon=` + * The location to generate an address for + +* `zoom=[0-18]` + * Level of detail required where `0` is country and `18` is house/building + +* `addressdetails=[0|1]` + * defaults to 0 + * Include a breakdown of the address into elements + +* `email=` + + * If you are making large numbers of request please include a valid email address or alternatively include your email address as part of the User-Agent string. + * This information will be kept confidential and only used to contact you in the event of a problem, see [Usage Policy](https://operations.osmfoundation.org/policies/nominatim/) for more details. + +* `polygon_geojson=1` + * Output geometry of results in geojson format. + +* `polygon_kml=1` + * Output geometry of results in kml format. + +* `polygon_svg=1` + * Output geometry of results in svg format. + +* `polygon_text=1` + * Output geometry of results as a WKT. + +* `extratags=1` + * Include additional information in the result if available, e.g. wikipedia link, opening hours. + +* `namedetails=1` + * Include a list of alternative names in the results. + * These may include language variants, references, operator and brand. + +### Example + +* [https://nominatim.openstreetmap.org/reverse?format=xml&lat=52.5487429714954&lon=-1.81602098644987&zoom=18&addressdetails=1](https://nominatim.openstreetmap.org/reverse?format=xml&lat=52.5487429714954&lon=-1.81602098644987&zoom=18&addressdetails=1) + +```xml + + + 135, Pilkington Avenue, Wylde Green, City of Birmingham, West Midlands (county), B72, United Kingdom + + + 135 + Pilkington Avenue + Wylde Green + Sutton Coldfield + City of Birmingham + West Midlands (county) + B72 + United Kingdom + gb + + +``` + +##### Example with `format=jsonv2` + +* [https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=-34.44076&lon=-58.70521](https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=-34.44076&lon=-58.70521) + +```json +{ + "place_id":"134140761", + "licence":"Data © OpenStreetMap contributors, ODbL 1.0. http:\/\/www.openstreetmap.org\/copyright", + "osm_type":"way", + "osm_id":"280940520", +"lat":"-34.4391708", + "lon":"-58.7064573", + "place_rank":"26", + "category":"highway", + "type":"motorway", + "importance":"0.1", + "addresstype":"road", + "display_name":"Autopista Pedro Eugenio Aramburu, El Triángulo, Partido de Malvinas Argentinas, Buenos Aires, 1.619, Argentina", + "name":"Autopista Pedro Eugenio Aramburu", + "address":{ + "road":"Autopista Pedro Eugenio Aramburu", + "village":"El Triángulo", + "state_district":"Partido de Malvinas Argentinas", + "state":"Buenos Aires", + "postcode":"1.619", + "country":"Argentina", + "country_code":"ar" + }, + "boundingbox":["-34.44159","-34.4370994","-58.7086067","-58.7044712"] +} +``` + +### Hierarchy + +* Admin level => XML entity + * 2 => `` + * 4 => `` + * 5 => `` + * 6 + * 7 => `` + * 8 => `` + * 9 => `` + * 10 => `` diff --git a/docs/api/Search.md b/docs/api/Search.md new file mode 100644 index 00000000..e166abaf --- /dev/null +++ b/docs/api/Search.md @@ -0,0 +1,216 @@ + +## Search +Nominatim indexes named (or numbered) features with the OSM data set and a subset of other unnamed features (pubs, hotels, churches, etc) + +Search terms are processed first left to right and then right to left if that fails. + +Both searches will work: [pilkington avenue, birmingham](//nominatim.openstreetmap.org/search?q=pilkington+avenue,birmingham), [birmingham, pilkington avenue](//nominatim.openstreetmap.org/search?q=birmingham,+pilkington+avenue) + +(Commas are optional, but improve performance by reducing the complexity of the search.) + +Where house numbers have been defined for an area they should be used: [135 pilkington avenue, birmingham](//nominatim.openstreetmap.org/search?q=135+pilkington+avenue,+birmingham) + +### Special Keywords +Various keywords are translated into searches for specific osm tags (e.g. Pub => amenity=pub). A current list of [special phrases](https://wiki.openstreetmap.org/wiki/Nominatim/Special_Phrases) processed is available. + +### Parameters + +``` + https://nominatim.openstreetmap.org/search? + https://nominatim.openstreetmap.org/search/? +``` + +* `format=[html|xml|json|jsonv2]` + + * Output format + * defaults to `html` + + +* `json_callback=` + + * Wrap json output in a callback function (JSONP) i.e. `()` + +* `accept-language=` + + * Preferred language order for showing search results, overrides the value specified in the "Accept-Language" HTTP header. + * Either uses standard rfc2616 accept-language string or a simple comma separated list of language codes. + +* `q=` + + * Query string to search for. + * Alternatively can be entered as: + + * `street= ` + * `city=` + * `county=` + * `state=` + * `country=` + * `postalcode=` + + **(experimental)** Alternative query string format for structured requests. +Structured requests are faster and require fewer server resources. **Do not combine with `q=` parameter**. + +* `countrycodes=[,][,]...` + + * Limit search results to a specific country (or a list of countries). + * `` should be the ISO 3166-1alpha2 code, e.g. `gb` for the United Kingdom, `de` for Germany, etc. + +* `viewbox=,,,` + * The preferred area to find search results. Any two corner points of the box are accepted in any order as long as they span a real box. + +* `bounded=[0|1]` + * defaults to 0 + * Restrict the results to only items contained with the viewbox (see above). + * Restricting the results to the bounding box also enables searching by amenity only. + * For example a search query of just `"[pub]"` would normally be rejected but with `bounded=1` will result in a list of items matching within the bounding box. + +* `polygon=[0|1]` + * defaults to 0 + * Output polygon outlines for items found **(deprecated, use one of the polygon_* parameters instead)** + +* `addressdetails=[0|1]` + * defaults to 0 + * Include a breakdown of the address into elements + +* `email=` + + * If you are making large numbers of request please include a valid email address or alternatively include your email address as part of the User-Agent string. + * This information will be kept confidential and only used to contact you in the event of a problem, see [Usage Policy](https://operations.osmfoundation.org/policies/nominatim/) for more details. + +* `exclude_place_ids=` + * defaults to 10 + * Limit the number of returned results. + +* `dedupe=[0|1]` + * defaults to 1 + * Sometimes you have several objects in OSM identifying the same place or object in reality. The simplest case is a street being split in many different OSM ways due to different characteristics. + * Nominatim will attempt to detect such duplicates and only return one match; this is controlled by the dedupe parameter which defaults to 1. Since the limit is, for reasons of efficiency, enforced before and not after de-duplicating, it is possible that de-duplicating leaves you with less results than requested. + +* `debug=[0|1]` + * defaults to 0 + * Output assorted developer debug information. Data on internals of nominatim "Search Loop" logic, and SQL queries. The output is (rough) HTML format. This overrides the specified machine readable format. + +* `polygon_geojson=1` + * Output geometry of results in geojson format. + +* `polygon_kml=1` + * Output geometry of results in kml format. + +* `polygon_svg=1` + * Output geometry of results in svg format. + +* `polygon_text=1` + * Output geometry of results as a WKT. + +* `extratags=1` + * Include additional information in the result if available, e.g. wikipedia link, opening hours. + +* `namedetails=1` + * Include a list of alternative names in the results. + * These may include language variants, references, operator and brand. + +### Examples + +* [https://nominatim.openstreetmap.org/search?q=135+pilkington+avenue,+birmingham&format=xml&polygon=1&addressdetails=1](https://nominatim.openstreetmap.org/search?q=135+pilkington+avenue,+birmingham&format=xml&polygon=1&addressdetails=1) +* [https://nominatim.openstreetmap.org/search/135%20pilkington%20avenue,%20birmingham?format=xml&polygon=1&addressdetails=1](https://nominatim.openstreetmap.org/search/135%20pilkington%20avenue,%20birmingham?format=xml&polygon=1&addressdetails=1) +* [https://nominatim.openstreetmap.org/search/gb/birmingham/pilkington%20avenue/135?format=xml&polygon=1&addressdetails=1](https://nominatim.openstreetmap.org/search/gb/birmingham/pilkington%20avenue/135?format=xml&polygon=1&addressdetails=1) + +```xml + + + 135 + Pilkington Avenue + Wylde Green + Sutton Coldfield + City of Birmingham + West Midlands (county) + B72 + United Kingdom + gb + + +``` + +* [https://nominatim.openstreetmap.org/search/Unter%20den%20Linden%201%20Berlin?format=json&addressdetails=1&limit=1&polygon_svg=1](https://nominatim.openstreetmap.org/search/Unter%20den%20Linden%201%20Berlin?format=json&addressdetails=1&limit=1&polygon_svg=1) + +```json + { + "address": { + "city": "Berlin", + "city_district": "Mitte", + "construction": "Unter den Linden", + "continent": "European Union", + "country": "Deutschland", + "country_code": "de", + "house_number": "1", + "neighbourhood": "Scheunenviertel", + "postcode": "10117", + "public_building": "Kommandantenhaus", + "state": "Berlin", + "suburb": "Mitte" + }, + "boundingbox": [ + "52.5170783996582", + "52.5173187255859", + "13.3975105285645", + "13.3981599807739" + ], + "class": "amenity", + "display_name": "Kommandantenhaus, 1, Unter den Linden, Scheunenviertel, Mitte, Berlin, 10117, Deutschland, European Union", + "importance": 0.73606775332943, + "lat": "52.51719785", + "licence": "Data \u00a9 OpenStreetMap contributors, ODbL 1.0. https://www.openstreetmap.org/copyright", + "lon": "13.3978352028938", + "osm_id": "15976890", + "osm_type": "way", + "place_id": "30848715", + "svg": "M 13.397511 -52.517283599999999 L 13.397829400000001 -52.517299800000004 13.398131599999999 -52.517315099999998 13.398159400000001 -52.517112099999999 13.3975388 -52.517080700000001 Z", + "type": "public_building" + } +``` + +* [https://nominatim.openstreetmap.org/?format=json&addressdetails=1&q=bakery+in+berlin+wedding&format=json&limit=1](https://nominatim.openstreetmap.org/?format=json&addressdetails=1&q=bakery+in+berlin+wedding&format=json&limit=1) + +```json + { + "address": { + "bakery": "B\u00e4cker Kamps", + "city_district": "Mitte", + "continent": "European Union", + "country": "Deutschland", + "country_code": "de", + "footway": "Bahnsteig U6", + "neighbourhood": "Sprengelkiez", + "postcode": "13353", + "state": "Berlin", + "suburb": "Wedding" + }, + "boundingbox": [ + "52.5460929870605", + "52.5460968017578", + "13.3591794967651", + "13.3591804504395" + ], + "class": "shop", + "display_name": "B\u00e4cker Kamps, Bahnsteig U6, Sprengelkiez, Wedding, Mitte, Berlin, 13353, Deutschland, European Union", + "icon": "https://nominatim.openstreetmap.org/images/mapicons/shopping_bakery.p.20.png", + "importance": 0.201, + "lat": "52.5460941", + "licence": "Data \u00a9 OpenStreetMap contributors, ODbL 1.0. https://www.openstreetmap.org/copyright", + "lon": "13.35918", + "osm_id": "317179427", + "osm_type": "node", + "place_id": "1453068", + "type": "bakery" + } +``` \ No newline at end of file diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index b0aee5d0..b2ff881c 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -5,6 +5,10 @@ site_url: http://nominatim.org repo_url: https://github.com/openstreetmap/Nominatim pages: - 'Introduction' : 'index.md' + - 'API Reference': + - 'Search': 'api/Search.md' + - 'Reverse': 'api/Reverse.md' + - 'Address Lookup': 'api/Lookup.md' - 'Administration Guide': - 'Basic Installation': 'admin/Installation.md' - 'Importing and Updating' : 'admin/Import-and-Update.md' diff --git a/lib/DebugHtml.php b/lib/DebugHtml.php new file mode 100644 index 00000000..ce2b8361 --- /dev/null +++ b/lib/DebugHtml.php @@ -0,0 +1,159 @@ +

Debug output for $sHeading

\n"; + } + + public static function newSection($sHeading) + { + echo "

$sHeading

\n"; + } + + public static function printVar($sHeading, $mVar) + { + echo '
'.$sHeading. ':  ';
+        Debug::outputVar($mVar, str_repeat(' ', strlen($sHeading) + 3));
+        echo "
\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 ''.$sHeading.":\n"; + echo ''; + if (!empty($aVar)) { + echo ''; + $aKeys = array(); + $aInfo = reset($aVar); + if (!is_array($aInfo)) { + $aInfo = $aInfo->debugInfo(); + } + foreach ($aInfo as $sKey => $mVal) { + echo ''; + $aKeys[] = $sKey; + } + echo ''; + foreach ($aVar as $oRow) { + $aInfo = $oRow; + if (!is_array($oRow)) { + $aInfo = $oRow->debugInfo(); + } + echo ''; + foreach ($aKeys as $sKey) { + echo ''; + } + echo ''; + } + } + echo '
'.$sKey.'
';
+                    if (isset($aInfo[$sKey])) {
+                        Debug::outputVar($aInfo[$sKey], '');
+                    }
+                    echo '
'; + } + + public static function printGroupTable($sHeading, $aVar) + { + echo ''.$sHeading.":\n"; + echo ''; + if (!empty($aVar)) { + echo ''; + $aKeys = array(); + $aInfo = reset(reset($aVar)); + if (!is_array($aInfo)) { + $aInfo = $aInfo->debugInfo(); + } + foreach ($aInfo as $sKey => $mVal) { + echo ''; + $aKeys[] = $sKey; + } + echo ''; + foreach ($aVar as $sGrpKey => $aGroup) { + foreach ($aGroup as $oRow) { + $aInfo = $oRow; + if (!is_array($oRow)) { + $aInfo = $oRow->debugInfo(); + } + echo ''; + foreach ($aKeys as $sKey) { + echo ''; + } + echo ''; + } + } + } + echo '
Group'.$sKey.'
'.$sGrpKey.'
';
+                        if (!empty($aInfo[$sKey])) {
+                            Debug::outputVar($aInfo[$sKey], '');
+                        }
+                        echo '
'; + } + + public static function printSQL($sSQL) + { + echo '

'.$sSQL.'

'."\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 = ', '; + } + } + } else { + Debug::outputSimpleVar($mVar); + } + } + + private static function outputSimpleVar($mVar) + { + if (is_bool($mVar)) { + echo ''.($mVar ? 'True' : 'False').''; + return $mVar ? 4 : 5; + } + + if (is_string($mVar)) { + echo "'$mVar'"; + return strlen($mVar) + 2; + } + + echo (string)$mVar; + return strlen((string)$mVar); + } +} diff --git a/lib/DebugNone.php b/lib/DebugNone.php new file mode 100644 index 00000000..e2d18b2d --- /dev/null +++ b/lib/DebugNone.php @@ -0,0 +1,11 @@ +loadStructuredAddressElement($sPostalCode, 'postalcode', 5, 11, array(5, 11)); $this->loadStructuredAddressElement($sCountry, 'country', 4, 4, false); - if (sizeof($this->aStructuredQuery) > 0) { + if (!empty($this->aStructuredQuery)) { $this->sQuery = join(', ', $this->aStructuredQuery); if ($this->iMaxAddressRank < 30) { $this->sAllowedTypesSQLList = '(\'place\',\'boundary\')'; @@ -317,7 +317,7 @@ class Geocode $aParams = $this->aStructuredQuery; - if (sizeof($aParams) == 1) return false; + if (count($aParams) == 1) return false; $aOrderToFallback = array('postalcode', 'street', 'city', 'county', 'state'); @@ -375,8 +375,8 @@ class Geocode $sPhraseType, $iToken == 0 && $iPhrase == 0, $iPhrase == 0, - $iToken + 1 == sizeof($aWordset) - && $iPhrase + 1 == sizeof($aPhrases) + $iToken + 1 == count($aWordset) + && $iPhrase + 1 == count($aPhrases) ); foreach ($aNewSearches as $oSearch) { @@ -411,7 +411,7 @@ class Geocode usort($aNewWordsetSearches, array('Nominatim\SearchDescription', 'bySearchRank')); $aWordsetSearches = array_slice($aNewWordsetSearches, 0, 50); } - //var_Dump('
',sizeof($aWordsetSearches)); exit; + //var_Dump('
',count($aWordsetSearches)); exit; $aNewPhraseSearches = array_merge($aNewPhraseSearches, $aNewWordsetSearches); usort($aNewPhraseSearches, array('Nominatim\SearchDescription', 'bySearchRank')); @@ -442,12 +442,10 @@ class Geocode $iSearchCount = 0; $aSearches = array(); foreach ($aGroupedSearches as $iScore => $aNewSearches) { - $iSearchCount += sizeof($aNewSearches); + $iSearchCount += count($aNewSearches); $aSearches = array_merge($aSearches, $aNewSearches); if ($iSearchCount > 50) break; } - - //if (CONST_Debug) _debugDumpGroupedSearches($aGroupedSearches, $aValidTokens); } // Revisit searches, drop bad searches and give penalty to unlikely combinations. @@ -502,8 +500,11 @@ class Geocode public function lookup() { + Debug::newFunction('Geocode::lookup'); if (!$this->sQuery && !$this->aStructuredQuery) return array(); + Debug::printDebugArray('Geocode', $this); + $oCtx = new SearchContext(); if ($this->aRoutePoints) { @@ -523,7 +524,11 @@ class Geocode $oCtx->setCountryList($this->aCountryCodes); } + Debug::newSection('Query Preprocessing'); + $sNormQuery = $this->normTerm($this->sQuery); + Debug::printVar('Normalized query', $sNormQuery); + $sLanguagePrefArraySQL = getArraySQL( array_map('getDBQuoted', $this->aLangPrefOrder) ); @@ -560,6 +565,10 @@ class Geocode $aSpecialTermsRaw, PREG_SET_ORDER ); + if (!empty($aSpecialTermsRaw)) { + Debug::printVar('Special terms', $aSpecialTermsRaw); + } + foreach ($aSpecialTermsRaw as $aSpecialTerm) { $sQuery = str_replace($aSpecialTerm[0], ' ', $sQuery); if (!$sSpecialTerm) { @@ -582,7 +591,8 @@ class Geocode $sSQL = 'SELECT class, type FROM word '; $sSQL .= ' WHERE word_token in (\' '.$sToken.'\')'; $sSQL .= ' AND class is not null AND class not in (\'place\')'; - if (CONST_Debug) var_Dump($sSQL); + + Debug::printSQL($sSQL); $aSearchWords = chksql($this->oDB->getAll($sSQL)); $aNewSearches = array(); foreach ($aSearches as $oSearch) { @@ -609,10 +619,15 @@ class Geocode $bStructuredPhrases = false; } + Debug::printDebugArray('Search context', $oCtx); + Debug::printDebugArray('Base search', $aSearches[0]); + Debug::printVar('Final query phrases', $aInPhrases); + // Convert each phrase to standard form // Create a list of standard words // Get all 'sets' of words // Generate a complete list of all + Debug::newSection('Tokenization'); $aTokens = array(); $aPhrases = array(); foreach ($aInPhrases as $iPhrase => $sPhrase) { @@ -627,13 +642,16 @@ class Geocode } } - if (sizeof($aTokens)) { + Debug::printDebugTable('Phrases', $aPhrases); + Debug::printVar('Tokens', $aTokens); + + if (!empty($aTokens)) { // Check which tokens we have, get the ID numbers $sSQL = 'SELECT word_id, word_token, word, class, type, country_code, operator, search_name_count'; $sSQL .= ' FROM word '; $sSQL .= ' WHERE word_token in ('.join(',', array_map('getDBQuoted', $aTokens)).')'; - if (CONST_Debug) var_Dump($sSQL); + Debug::printSQL($sSQL); $aValidTokens = array(); $aDatabaseWords = chksql( @@ -665,7 +683,6 @@ class Geocode } $aWordFrequencyScores[$aToken['word_id']] = $aToken['search_name_count'] + 1; } - if (CONST_Debug) var_Dump($aPhrases, $aValidTokens); // US ZIP+4 codes - if there is no token, merge in the 5-digit ZIP code foreach ($aTokens as $sToken) { @@ -690,9 +707,11 @@ class Geocode $aValidTokens[' '.$sToken] = array(array('class' => 'place', 'type' => 'house', 'word_token' => ' '.$sToken)); } } + Debug::printGroupTable('Valid Tokens', $aValidTokens); // Any words that have failed completely? // TODO: suggestions + Debug::newSection('Search candidates'); $aGroupedSearches = $this->getGroupedSearches($aSearches, $aPhrases, $aValidTokens, $bStructuredPhrases); @@ -702,8 +721,8 @@ class Geocode // because order in the address doesn't matter. $aPhrases = array_reverse($aPhrases); $aPhrases[0]->invertWordSets(); - if (sizeof($aPhrases) > 1) { - $aPhrases[sizeof($aPhrases)-1]->invertWordSets(); + if (count($aPhrases) > 1) { + $aPhrases[count($aPhrases)-1]->invertWordSets(); } $aReverseGroupedSearches = $this->getGroupedSearches($aSearches, $aPhrases, $aValidTokens, false); @@ -738,7 +757,7 @@ class Geocode $sHash = serialize($aSearch); if (isset($aSearchHash[$sHash])) { unset($aGroupedSearches[$iGroup][$iSearch]); - if (sizeof($aGroupedSearches[$iGroup]) == 0) unset($aGroupedSearches[$iGroup]); + if (empty($aGroupedSearches[$iGroup])) unset($aGroupedSearches[$iGroup]); } else { $aSearchHash[$sHash] = 1; } @@ -771,7 +790,7 @@ class Geocode if ($iQueryLoop > 20) break; } - if (sizeof($aResults) && ($this->iMinAddressRank != 0 || $this->iMaxAddressRank != 30)) { + 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 @@ -806,7 +825,7 @@ class Geocode $aFilteredIDs = array(); if ($aFilterSql) { $sSQL = join(' UNION ', $aFilterSql); - if (CONST_Debug) var_dump($sSQL); + Debug::printSQL($sSQL); $aFilteredIDs = chksql($this->oDB->getCol($sSQL)); } @@ -824,7 +843,7 @@ class Geocode $aResults = $tempIDs; } - if (sizeof($aResults)) break; + if (!empty($aResults)) break; if ($iGroupLoop > 4) break; if ($iQueryLoop > 30) break; } @@ -835,7 +854,7 @@ class Geocode $oLookup = $oReverse->lookupPoint($oCtx->sqlNear, false); - if (CONST_Debug) var_dump('Reverse search', $aLookup); + Debug::printVar('Reverse search', $oLookup); if ($oLookup) { $aResults = array($oLookup->iId => $oLookup); @@ -843,7 +862,7 @@ class Geocode } // No results? Done - if (!sizeof($aResults)) { + if (empty($aResults)) { if ($this->bFallback) { if ($this->fallbackStructuredQuery()) { return $this->lookup(); @@ -870,10 +889,7 @@ class Geocode if (!preg_match('/[\pL\pN]/', $sWord)) unset($aRecheckWords[$i]); } - if (CONST_Debug) { - echo 'Recheck words:<\i>'; - var_dump($aRecheckWords); - } + Debug::printVar('Recheck words', $aRecheckWords); foreach ($aSearchResults as $iIdx => $aResult) { // Default @@ -952,18 +968,16 @@ class Geocode $aResult['foundorder'] += 0.01; } } - if (CONST_Debug) var_dump($aResult); $aSearchResults[$iIdx] = $aResult; } uasort($aSearchResults, 'byImportance'); + Debug::printVar('Pre-filter results', $aSearchResults); $aOSMIDDone = array(); $aClassTypeNameDone = array(); $aToFilter = $aSearchResults; $aSearchResults = array(); - if (CONST_Debug) var_dump($aToFilter); - $bFirst = true; foreach ($aToFilter as $aResult) { $this->aExcludePlaceIDs[$aResult['place_id']] = $aResult['place_id']; @@ -982,10 +996,33 @@ class Geocode } // Absolute limit on number of results - if (sizeof($aSearchResults) >= $this->iFinalLimit) break; + if (count($aSearchResults) >= $this->iFinalLimit) break; } - if (CONST_Debug) var_dump($aSearchResults); + 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), + 'Include address' => $this->bIncludeAddressDetails, + 'Excluded place IDs' => Debug::fmtArrayVals($this->aExcludePlaceIDs), + 'Try reversed query'=> $this->bReverseInPlan, + '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/ParameterParser.php b/lib/ParameterParser.php index c9a97c25..26b648bb 100644 --- a/lib/ParameterParser.php +++ b/lib/ParameterParser.php @@ -99,7 +99,7 @@ class ParameterParser arsort($aLanguages); } } - if (!sizeof($aLanguages) && CONST_Default_Language) { + if (empty($aLanguages) && CONST_Default_Language) { $aLanguages[CONST_Default_Language] = 1; } diff --git a/lib/Phrase.php b/lib/Phrase.php index b39079d9..7cf3f297 100644 --- a/lib/Phrase.php +++ b/lib/Phrase.php @@ -83,7 +83,7 @@ class Phrase $aResult = array(array(join(' ', $aWords))); $sFirstToken = ''; if ($iDepth < Phrase::MAX_DEPTH) { - while (sizeof($aWords) > 1) { + while (count($aWords) > 1) { $sWord = array_shift($aWords); $sFirstToken .= ($sFirstToken?' ':'').$sWord; $aRest = $this->createWordSets($aWords, $iDepth + 1); @@ -101,7 +101,7 @@ class Phrase $aResult = array(array(join(' ', $aWords))); $sFirstToken = ''; if ($iDepth < Phrase::MAX_DEPTH) { - while (sizeof($aWords) > 1) { + while (count($aWords) > 1) { $sWord = array_pop($aWords); $sFirstToken = $sWord.($sFirstToken?' ':'').$sFirstToken; $aRest = $this->createInverseWordSets($aWords, $iDepth + 1); @@ -113,4 +113,14 @@ class Phrase return $aResult; } + + public function debugInfo() + { + return array( + 'Type' => $this->sPhraseType, + 'Phrase' => $this->sPhrase, + 'Words' => $this->aWords, + 'WordSets' => $this->aWordSets + ); + } } diff --git a/lib/PlaceLookup.php b/lib/PlaceLookup.php index 41fdea89..98af69f2 100644 --- a/lib/PlaceLookup.php +++ b/lib/PlaceLookup.php @@ -164,19 +164,21 @@ class PlaceLookup $aResults = $this->lookup(array($iPlaceID => new Result($iPlaceID))); - return sizeof($aResults) ? reset($aResults) : null; + return empty($aResults) ? null : reset($aResults); } public function lookup($aResults, $iMinRank = 0, $iMaxRank = 30) { - if (!sizeof($aResults)) { + Debug::newFunction('Place lookup'); + + if (empty($aResults)) { return array(); } $aSubSelects = array(); $sPlaceIDs = Result::joinIdsByTable($aResults, Result::TABLE_PLACEX); - if (CONST_Debug) var_dump('PLACEX', $sPlaceIDs); if ($sPlaceIDs) { + Debug::printVar('Ids from placex', $sPlaceIDs); $sSQL = 'SELECT '; $sSQL .= ' osm_type,'; $sSQL .= ' osm_id,'; @@ -246,6 +248,7 @@ class PlaceLookup // 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,'; @@ -276,6 +279,7 @@ class PlaceLookup 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) @@ -321,6 +325,7 @@ class PlaceLookup // 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) @@ -406,16 +411,13 @@ class PlaceLookup } } - if (CONST_Debug) var_dump($aSubSelects); - - if (!sizeof($aSubSelects)) { + if (empty($aSubSelects)) { return array(); } - $aPlaces = chksql( - $this->oDB->getAll(join(' UNION ', $aSubSelects)), - 'Could not lookup place' - ); + $sSQL = join(' UNION ', $aSubSelects); + Debug::printSQL($sSQL); + $aPlaces = chksql($this->oDB->getAll($sSQL), 'Could not lookup place'); $aClassType = getClassTypes(); foreach ($aPlaces as &$aPlace) { @@ -457,7 +459,7 @@ class PlaceLookup $aPlace['addresstype'] = $sAddressType; } - if (CONST_Debug) var_dump($aPlaces); + Debug::printVar('Places', $aPlaces); return $aPlaces; } diff --git a/lib/Result.php b/lib/Result.php index 30c59854..d69ac62f 100644 --- a/lib/Result.php +++ b/lib/Result.php @@ -27,6 +27,17 @@ class Result /// Subranking within the results (the higher the worse). public $iResultRank = 0; + 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) { diff --git a/lib/SearchContext.php b/lib/SearchContext.php index b0ff38d8..c0ae9032 100644 --- a/lib/SearchContext.php +++ b/lib/SearchContext.php @@ -267,4 +267,18 @@ class SearchContext return ''; } + + 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/SearchDescription.php b/lib/SearchDescription.php index 2e72decc..276f4c98 100644 --- a/lib/SearchDescription.php +++ b/lib/SearchDescription.php @@ -43,7 +43,6 @@ class SearchDescription /// Index of phrase currently processed. private $iNamePhrase = -1; - /** * Create an empty search description. * @@ -94,8 +93,8 @@ class SearchDescription */ public function looksLikeFullAddress() { - return sizeof($this->aName) - && (sizeof($this->aAddress || $this->sCountryCode)) + return (!empty($this->aName)) + && (!empty($this->aAddress) || $this->sCountryCode) && preg_match('/[0-9]+/', $this->sHouseNumber); } @@ -147,7 +146,7 @@ class SearchDescription */ public function isValidSearch() { - if (!sizeof($this->aName)) { + if (empty($this->aName)) { if ($this->sHouseNumber) { return false; } @@ -223,7 +222,7 @@ class SearchDescription // If we have a structured search or this is not the first term, // add the postcode as an addendum. if ($this->iOperator != Operator::POSTCODE - && ($sPhraseType == 'postalcode' || sizeof($this->aName)) + && ($sPhraseType == 'postalcode' || !empty($this->aName)) ) { $oSearch = clone $this; $oSearch->iSearchRank++; @@ -247,8 +246,8 @@ class SearchDescription $oSearch->iSearchRank++; } // also must not appear in the middle of the address - if (sizeof($this->aAddress) - || sizeof($this->aAddressNonSearch) + if (!empty($this->aAddress) + || (!empty($this->aAddressNonSearch)) || $this->sPostcode ) { $oSearch->iSearchRank++; @@ -262,7 +261,7 @@ class SearchDescription $iOp = Operator::NEAR; // near == in for the moment if ($aSearchTerm['operator'] == '') { - if (sizeof($this->aName) || $this->oContext->isBoundedSearch()) { + if (!empty($this->aName) || $this->oContext->isBoundedSearch()) { $iOp = Operator::NAME; } $oSearch->iSearchRank += 2; @@ -280,7 +279,7 @@ class SearchDescription // of the phrase. In structured search the name must forcably in // the first phrase. In unstructured search it may be in a later // phrase when the first phrase is a house number. - if (sizeof($this->aName) || !($bFirstPhrase || $sPhraseType == '')) { + if (!empty($this->aName) || !($bFirstPhrase || $sPhraseType == '')) { if (($sPhraseType == '' || !$bFirstPhrase) && !$bHasPartial) { $oSearch = clone $this; $oSearch->iSearchRank++; @@ -322,7 +321,7 @@ class SearchDescription $iWordID = $aSearchTerm['word_id']; if ((!$bStructuredPhrases || $iPhrase > 0) - && sizeof($this->aName) + && (!empty($this->aName)) && strpos($aSearchTerm['word_token'], ' ') === false ) { if ($aSearchTerm['search_name_count'] + 1 < CONST_Max_Word_Frequency) { @@ -337,7 +336,7 @@ class SearchDescription if (preg_match('#^[0-9]+$#', $aSearchTerm['word_token'])) { $oSearch->iSearchRank += 2; } - if (sizeof($aFullTokens)) { + if (!empty($aFullTokens)) { $oSearch->iSearchRank++; } $aNewSearches[] = $oSearch; @@ -358,11 +357,11 @@ class SearchDescription } if ((!$this->sPostcode && !$this->aAddress && !$this->aAddressNonSearch) - && (!sizeof($this->aName) || $this->iNamePhrase == $iPhrase) + && (empty($this->aName) || $this->iNamePhrase == $iPhrase) ) { $oSearch = clone $this; $oSearch->iSearchRank += 2; - if (!sizeof($this->aName)) { + if (empty($this->aName)) { $oSearch->iSearchRank += 1; } if (preg_match('#^[0-9]+$#', $aSearchTerm['word_token'])) { @@ -405,7 +404,7 @@ class SearchDescription $iHousenumber = -1; if ($this->sCountryCode - && !sizeof($this->aName) + && empty($this->aName) && !$this->iOperator && !$this->sClass && !$this->oContext->hasNearPoint() @@ -414,7 +413,7 @@ class SearchDescription if (4 >= $iMinRank && 4 <= $iMaxRank) { $aResults = $this->queryCountry($oDB); } - } elseif (!sizeof($this->aName) && !sizeof($this->aAddress)) { + } 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()) { @@ -435,33 +434,30 @@ class SearchDescription ); //now search for housenumber, if housenumber provided - if ($this->sHouseNumber && sizeof($aResults)) { + if ($this->sHouseNumber && !empty($aResults)) { $aNamedPlaceIDs = $aResults; $aResults = $this->queryHouseNumber($oDB, $aNamedPlaceIDs, $iLimit); - if (!sizeof($aResults) && $this->looksLikeFullAddress()) { + if (empty($aResults) && $this->looksLikeFullAddress()) { $aResults = $aNamedPlaceIDs; } } // finally get POIs if requested - if ($this->sClass && sizeof($aResults)) { + if ($this->sClass && !empty($aResults)) { $aResults = $this->queryPoiByOperator($oDB, $aResults, $iLimit); } } - if (CONST_Debug) { - echo '
Place IDs: '; - var_dump(array_keys($aResults)); - } + Debug::printDebugTable('Place IDs', $aResults); - if (sizeof($aResults) && $this->sPostcode) { + 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."'"; - if (CONST_Debug) var_dump($sSQL); + Debug::printSQL($sSQL); $aFilteredPlaceIDs = chksql($oDB->getCol($sSQL)); if ($aFilteredPlaceIDs) { $aNewResults = array(); @@ -469,10 +465,7 @@ class SearchDescription $aNewResults[$iPlaceId] = $aResults[$iPlaceId]; } $aResults = $aNewResults; - if (CONST_Debug) { - echo '
Place IDs after postcode filtering: '; - var_dump(array_keys($aResults)); - } + Debug::printVar('Place IDs after postcode filtering', $aResults); } } } @@ -491,7 +484,7 @@ class SearchDescription } $sSQL .= ' ORDER BY st_area(geometry) DESC LIMIT 1'; - if (CONST_Debug) var_dump($sSQL); + Debug::printSQL($sSQL); $aResults = array(); foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) { @@ -532,7 +525,7 @@ class SearchDescription $sSQL .= ' ORDER BY '.$this->oContext->distanceSQL('ct.centroid').' ASC'; } $sSQL .= " limit $iLimit"; - if (CONST_Debug) var_dump($sSQL); + Debug::printSQL($sSQL); $aDBResults = chksql($oDB->getCol($sSQL)); } @@ -546,7 +539,7 @@ class SearchDescription } $sSQL .= ' ORDER BY '.$this->oContext->distanceSQL('centroid').' ASC'; $sSQL .= " LIMIT $iLimit"; - if (CONST_Debug) var_dump($sSQL); + Debug::printSQL($sSQL); $aDBResults = chksql($oDB->getCol($sSQL)); } @@ -562,7 +555,7 @@ class SearchDescription { $sSQL = 'SELECT p.place_id FROM location_postcode p '; - if (sizeof($this->aAddress)) { + 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)'; @@ -576,7 +569,7 @@ class SearchDescription $sSQL .= $this->oContext->excludeSQL(' AND p.place_id'); $sSQL .= " LIMIT $iLimit"; - if (CONST_Debug) var_dump($sSQL); + Debug::printSQL($sSQL); $aResults = array(); foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) { @@ -591,7 +584,7 @@ class SearchDescription $aTerms = array(); $aOrder = array(); - if ($this->sHouseNumber && sizeof($this->aAddress)) { + if ($this->sHouseNumber && !empty($this->aAddress)) { $sHouseNumberRegex = '\\\\m'.$this->sHouseNumber.'\\\\M'; $aOrder[] = ' ('; $aOrder[0] .= 'EXISTS('; @@ -617,13 +610,13 @@ class SearchDescription $aOrder[0] .= ') DESC'; } - if (sizeof($this->aName)) { + if (!empty($this->aName)) { $aTerms[] = 'name_vector @> '.getArraySQL($this->aName); } - if (sizeof($this->aAddress)) { + if (!empty($this->aAddress)) { // For infrequent name terms disable index usage for address if (CONST_Search_NameOnlySearchFrequencyThreshold - && sizeof($this->aName) == 1 + && count($this->aName) == 1 && $aWordFrequencyScores[$this->aName[reset($this->aName)]] < CONST_Search_NameOnlySearchFrequencyThreshold ) { @@ -653,7 +646,7 @@ class SearchDescription $aTerms[] = $this->oContext->withinSQL('centroid'); $aOrder[] = $this->oContext->distanceSQL('centroid'); } elseif ($this->sPostcode) { - if (!sizeof($this->aAddress)) { + 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.1))"; } else { $aOrder[] = "(SELECT min(ST_Distance(search_name.centroid, p.geometry)) FROM location_postcode p WHERE p.postcode = '".$this->sPostcode."')"; @@ -681,7 +674,7 @@ class SearchDescription $sImportanceSQL .= $this->oContext->viewboxImportanceSQL('centroid'); $aOrder[] = "$sImportanceSQL DESC"; - if (sizeof($this->aFullNameAddress)) { + if (!empty($this->aFullNameAddress)) { $sExactMatchSQL = ' ( '; $sExactMatchSQL .= ' SELECT count(*) FROM ( '; $sExactMatchSQL .= ' SELECT unnest('.getArraySQL($this->aFullNameAddress).')'; @@ -700,14 +693,14 @@ class SearchDescription $aResults = array(); - if (sizeof($aTerms)) { + if (!empty($aTerms)) { $sSQL = 'SELECT place_id,'.$sExactMatchSQL; $sSQL .= ' FROM search_name'; $sSQL .= ' WHERE '.join(' and ', $aTerms); $sSQL .= ' ORDER BY '.join(', ', $aOrder); $sSQL .= ' LIMIT '.$iLimit; - if (CONST_Debug) var_dump($sSQL); + Debug::printSQL($sSQL); $aDBResults = chksql( $oDB->getAll($sSQL), @@ -740,7 +733,7 @@ class SearchDescription $sSQL .= $this->oContext->excludeSQL(' AND place_id'); $sSQL .= " LIMIT $iLimit"; - if (CONST_Debug) var_dump($sSQL); + Debug::printSQL($sSQL); // XXX should inherit the exactMatches from its parent foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) { @@ -749,7 +742,7 @@ class SearchDescription $bIsIntHouseNumber= (bool) preg_match('/[0-9]+/', $this->sHouseNumber); $iHousenumber = intval($this->sHouseNumber); - if ($bIsIntHouseNumber && !sizeof($aResults)) { + if ($bIsIntHouseNumber && empty($aResults)) { // if nothing found, search in the interpolation line table $sSQL = 'SELECT distinct place_id FROM location_property_osmline'; $sSQL .= ' WHERE startnumber is not NULL'; @@ -768,7 +761,7 @@ class SearchDescription $sSQL .= $this->oContext->excludeSQL(' AND place_id'); $sSQL .= " limit $iLimit"; - if (CONST_Debug) var_dump($sSQL); + Debug::printSQL($sSQL); foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) { $oResult = new Result($iPlaceId, Result::TABLE_OSMLINE); @@ -778,14 +771,14 @@ class SearchDescription } // If nothing found try the aux fallback table - if (CONST_Use_Aux_Location_data && !sizeof($aResults)) { + if (CONST_Use_Aux_Location_data && empty($aResults)) { $sSQL = 'SELECT place_id FROM location_property_aux'; $sSQL .= ' WHERE parent_place_id in ('.$sPlaceIDs.')'; $sSQL .= " AND housenumber = '".$this->sHouseNumber."'"; $sSQL .= $this->oContext->excludeSQL(' AND place_id'); $sSQL .= " limit $iLimit"; - if (CONST_Debug) var_dump($sSQL); + Debug::printSQL($sSQL); foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) { $aResults[$iPlaceId] = new Result($iPlaceId, Result::TABLE_AUX); @@ -793,7 +786,7 @@ class SearchDescription } // If nothing found then search in Tiger data (location_property_tiger) - if (CONST_Use_US_Tiger_Data && $bIsIntHouseNumber && !sizeof($aResults)) { + if (CONST_Use_US_Tiger_Data && $bIsIntHouseNumber && empty($aResults)) { $sSQL = 'SELECT place_id FROM location_property_tiger'; $sSQL .= ' WHERE parent_place_id in ('.$sPlaceIDs.') and ('; if ($iHousenumber % 2 == 0) { @@ -807,7 +800,7 @@ class SearchDescription $sSQL .= $this->oContext->excludeSQL(' AND place_id'); $sSQL .= " limit $iLimit"; - if (CONST_Debug) var_dump($sSQL); + Debug::printSQL($sSQL); foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) { $oResult = new Result($iPlaceId, Result::TABLE_TIGER); @@ -841,7 +834,7 @@ class SearchDescription $sSQL .= ' ORDER BY rank_search ASC '; $sSQL .= " LIMIT $iLimit"; - if (CONST_Debug) var_dump($sSQL); + Debug::printSQL($sSQL); foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) { $aResults[$iPlaceId] = new Result($iPlaceId); @@ -855,7 +848,7 @@ class SearchDescription $bCacheTable = (bool) chksql($oDB->getOne($sSQL)); $sSQL = "SELECT min(rank_search) FROM placex WHERE place_id in ($sPlaceIDs)"; - if (CONST_Debug) var_dump($sSQL); + Debug::printSQL($sSQL); $iMaxRank = (int)chksql($oDB->getOne($sSQL)); // For state / country level searches the normal radius search doesn't work very well @@ -868,7 +861,7 @@ class SearchDescription $sSQL .= " AND ST_GeometryType(geometry) in ('ST_Polygon','ST_MultiPolygon')"; $sSQL .= ' ORDER BY rank_search ASC '; $sSQL .= ' LIMIT 1'; - if (CONST_Debug) var_dump($sSQL); + Debug::printSQL($sSQL); $sPlaceGeom = chksql($oDB->getOne($sSQL)); } @@ -878,7 +871,7 @@ class SearchDescription $iMaxRank += 5; $sSQL = 'SELECT place_id FROM placex'; $sSQL .= " WHERE place_id in ($sPlaceIDs) and rank_search < $iMaxRank"; - if (CONST_Debug) var_dump($sSQL); + Debug::printSQL($sSQL); $aPlaceIDs = chksql($oDB->getCol($sSQL)); $sPlaceIDs = join(',', $aPlaceIDs); } @@ -923,7 +916,7 @@ class SearchDescription } $sSQL .= " limit $iLimit"; - if (CONST_Debug) var_dump($sSQL); + Debug::printSQL($sSQL); foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) { $aResults[$iPlaceId] = new Result($iPlaceId); @@ -955,7 +948,7 @@ class SearchDescription } $sSQL .= " limit $iLimit"; - if (CONST_Debug) var_dump($sSQL); + Debug::printSQL($sSQL); foreach (chksql($oDB->getCol($sSQL)) as $iPlaceId) { $aResults[$iPlaceId] = new Result($iPlaceId); @@ -1000,6 +993,24 @@ class SearchDescription //////////// 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) { diff --git a/lib/cmd.php b/lib/cmd.php index a1084938..1edf5dfd 100644 --- a/lib/cmd.php +++ b/lib/cmd.php @@ -16,7 +16,7 @@ function getCmdOpt($aArg, $aSpec, &$aResult, $bExitOnError = false, $bExitOnUnkn $aResult = array(); $bUnknown = false; - $iSize = sizeof($aArg); + $iSize = count($aArg); for ($i = 1; $i < $iSize; $i++) { if (isset($aQuick[$aArg[$i]])) { $aLine = $aQuick[$aArg[$i]]; diff --git a/lib/init-cmd.php b/lib/init-cmd.php index 860ef215..50c709c9 100644 --- a/lib/init-cmd.php +++ b/lib/init-cmd.php @@ -2,6 +2,7 @@ require_once('init.php'); require_once('cmd.php'); +require_once('DebugNone.php'); // handle http proxy when using file_get_contents if (CONST_HTTP_Proxy) { diff --git a/lib/init-website.php b/lib/init-website.php index d8c012a4..ca5214da 100644 --- a/lib/init-website.php +++ b/lib/init-website.php @@ -2,6 +2,7 @@ require_once('init.php'); require_once('ParameterParser.php'); +require_once(CONST_Debug ? 'DebugHtml.php' : 'DebugNone.php'); /*************************************************************************** * diff --git a/lib/lib.php b/lib/lib.php index d7ccf2d2..fa71d296 100644 --- a/lib/lib.php +++ b/lib/lib.php @@ -14,7 +14,7 @@ function getProcessorCount() { $sCPU = file_get_contents('/proc/cpuinfo'); preg_match_all('#processor\s+: [0-9]+#', $sCPU, $aMatches); - return sizeof($aMatches[0]); + return count($aMatches[0]); } diff --git a/lib/template/address-json.php b/lib/template/address-json.php index 85f6fe8e..4f0d024f 100644 --- a/lib/template/address-json.php +++ b/lib/template/address-json.php @@ -2,7 +2,7 @@ $aFilteredPlaces = array(); -if (!sizeof($aPlace)) { +if (empty($aPlace)) { if (isset($sError)) $aFilteredPlaces['error'] = $sError; else $aFilteredPlaces['error'] = 'Unable to geocode'; diff --git a/lib/template/address-xml.php b/lib/template/address-xml.php index 6183b284..5eddfa3e 100644 --- a/lib/template/address-xml.php +++ b/lib/template/address-xml.php @@ -11,7 +11,7 @@ echo " attribution='Data © OpenStreetMap contributors, ODbL 1.0. http://www.ope echo " querystring='".htmlspecialchars($_SERVER['QUERY_STRING'], ENT_QUOTES)."'"; echo ">\n"; -if (!sizeof($aPlace)) { +if (empty($aPlace)) { if (isset($sError)) echo "$sError"; else echo 'Unable to geocode'; diff --git a/lib/template/details-html.php b/lib/template/details-html.php index dedf52f3..ef7d9248 100644 --- a/lib/template/details-html.php +++ b/lib/template/details-html.php @@ -199,7 +199,7 @@ } } - if (sizeof($aParentOfLines)) + if (!empty($aParentOfLines)) { headline('Parent Of'); @@ -223,7 +223,7 @@ _one_row($aAddressLine); } } - if (sizeof($aParentOfLines) >= 500) { + if (count($aParentOfLines) >= 500) { echo '

There are more child objects which are not shown.

'; } } diff --git a/lib/template/search-batch-json.php b/lib/template/search-batch-json.php index 09ea48b6..513f3c2b 100644 --- a/lib/template/search-batch-json.php +++ b/lib/template/search-batch-json.php @@ -49,7 +49,7 @@ foreach ($aBatchResults as $aSearchResults) { $aPlace['icon'] = $aPointDetails['icon']; } - if (isset($aPointDetails['address']) && sizeof($aPointDetails['address'])>0) { + if (isset($aPointDetails['address']) && !empty($aPointDetails['address'])) { $aPlace['address'] = $aPointDetails['address']; } diff --git a/lib/template/search-html.php b/lib/template/search-html.php index 37a6ce4a..53c6c88c 100644 --- a/lib/template/search-html.php +++ b/lib/template/search-html.php @@ -57,7 +57,7 @@ echo ''; $i = $i+1; } - if (sizeof($aSearchResults) && $sMoreURL) + if (!empty($aSearchResults) && $sMoreURL) { echo ''; } diff --git a/lib/template/search-json.php b/lib/template/search-json.php index 774b5be0..7c87f636 100644 --- a/lib/template/search-json.php +++ b/lib/template/search-json.php @@ -43,7 +43,7 @@ foreach ($aSearchResults as $iResNum => $aPointDetails) { $aPlace['icon'] = $aPointDetails['icon']; } - if (isset($aPointDetails['address']) && sizeof($aPointDetails['address'])) { + if (isset($aPointDetails['address']) && !empty($aPointDetails['address'])) { $aPlace['address'] = $aPointDetails['address']; } diff --git a/phpcs.xml b/phpcs.xml index a48b5c3e..6b4abc39 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -32,6 +32,13 @@ + + + + + + + diff --git a/utils/importWikipedia.php b/utils/importWikipedia.php index 5a6e6e04..90477b81 100755 --- a/utils/importWikipedia.php +++ b/utils/importWikipedia.php @@ -241,7 +241,7 @@ function _templatesToProperties($aTemplates) } // Assume the first template with lots of params is the type (fallback for infobox) - if (!isset($aPageProperties['sPossibleInfoboxType']) && sizeof($aParams) > 10) { + if (!isset($aPageProperties['sPossibleInfoboxType']) && count($aParams) > 10) { $aPageProperties['sPossibleInfoboxType'] = trim($aTemplate[0]); // $aPageProperties['aInfoboxParams'] = $aParams; } @@ -495,7 +495,7 @@ if (isset($aCMDResult['link'])) { if (!isset($aNominatRecords[0])) { $aNameParts = preg_split('#[(,]#', $aRecord['name']); - if (sizeof($aNameParts) > 1) { + if (count($aNameParts) > 1) { $sNameURL = $sURL.'&q='.urlencode(trim($aNameParts[0])); var_Dump($sNameURL); $sXML = file_get_contents($sNameURL); @@ -509,7 +509,7 @@ if (isset($aCMDResult['link'])) { } // assume first is best/right - for ($i = 0; $i < sizeof($aNominatRecords); $i++) { + for ($i = 0; $i < count($aNominatRecords); $i++) { $fDiff = ($aRecord['lat']-$aNominatRecords[$i]['LAT']) * ($aRecord['lat']-$aNominatRecords[$i]['LAT']); $fDiff += ($aRecord['lon']-$aNominatRecords[$i]['LON']) * ($aRecord['lon']-$aNominatRecords[$i]['LON']); $fDiff = sqrt($fDiff); diff --git a/website/hierarchy.php b/website/hierarchy.php index 8f2f5237..9b488f83 100755 --- a/website/hierarchy.php +++ b/website/hierarchy.php @@ -62,7 +62,7 @@ $oPlaceLookup->setIncludeAddressDetails(true); $aPlaceAddress = array_reverse($oPlaceLookup->getAddressDetails($iPlaceID)); -if (!sizeof($aPlaceAddress)) userError('Unknown place id.'); +if (empty($aPlaceAddress)) userError('Unknown place id.'); $aBreadcrums = array(); foreach ($aPlaceAddress as $i => $aPlace) { @@ -100,7 +100,7 @@ $sSQL .= ' where parent_place_id in ('.join(',', $aRelatedPlaceIDs).') and name $sSQL .= ' order by rank_address asc,rank_search asc,localname,class, type,housenumber'; $aParentOfLines = chksql($oDB->getAll($sSQL)); -if (sizeof($aParentOfLines)) { +if (!empty($aParentOfLines)) { echo '

Parent Of:

'; $aClassType = getClassTypesWithImportance(); $aGroupedAddressLines = array(); @@ -136,7 +136,7 @@ if (sizeof($aParentOfLines)) { echo ''; } } - if (sizeof($aParentOfLines) >= 500) { + if (count($aParentOfLines) >= 500) { echo '

There are more child objects which are not shown.

'; } echo ''; diff --git a/website/polygons.php b/website/polygons.php index 4c1401ef..0f49183f 100755 --- a/website/polygons.php +++ b/website/polygons.php @@ -18,7 +18,7 @@ $oDB =& getDB(); $iTotalBroken = (int) chksql($oDB->getOne('select count(*) from import_polygon_error')); $aPolygons = array(); -while ($iTotalBroken && !sizeof($aPolygons)) { +while ($iTotalBroken && empty($aPolygons)) { $sSQL = 'select osm_type as "type",osm_id as "id",class as "key",type as "value",name->\'name\' as "name",'; $sSQL .= 'country_code as "country",errormessage as "error message",updated'; $sSQL .= ' from import_polygon_error'; @@ -32,7 +32,7 @@ while ($iTotalBroken && !sizeof($aPolygons)) { if ($bReduced) $aWhere[] = "errormessage like 'Area reduced%'"; if ($sClass) $sWhere[] = "class = '".pg_escape_string($sClass)."'"; - if (sizeof($aWhere)) { + if (!empty($aWhere)) { $sSQL .= ' where '.join(' and ', $aWhere); } diff --git a/website/reverse.php b/website/reverse.php index 9660f36d..822081ef 100755 --- a/website/reverse.php +++ b/website/reverse.php @@ -41,7 +41,7 @@ if ($sOsmType && $iOsmId > 0) { if ($oLookup) { $aPlaces = $oPlaceLookup->lookup(array($oLookup->iId => $oLookup)); - if (sizeof($aPlaces)) { + if (!empty($aPlaces)) { $aPlace = reset($aPlaces); } } diff --git a/website/search.php b/website/search.php index 0dddacce..6dc44335 100755 --- a/website/search.php +++ b/website/search.php @@ -68,7 +68,7 @@ $aSearchResults = $oGeocode->lookup(); if ($sOutputFormat=='html') { $sDataDate = chksql($oDB->getOne("select TO_CHAR(lastimportdate,'YYYY/MM/DD HH24:MI')||' GMT' from import_status limit 1")); } -logEnd($oDB, $hLog, sizeof($aSearchResults)); +logEnd($oDB, $hLog, count($aSearchResults)); $sQuery = $oGeocode->getQueryString();