]> git.openstreetmap.org Git - nominatim.git/blobdiff - lib/lib.php
fix syntax errors and update tests
[nominatim.git] / lib / lib.php
index 1b499005d7d73ffa40f9b37a70a569859049d928..ec5b9b1f4330f3a68cce22ef2959767045ddeaaa 100644 (file)
@@ -1,45 +1,5 @@
 <?php
 
-       function failInternalError($sError, $sSQL = false, $vDumpVar = false)
-       {
-               header('HTTP/1.0 500 Internal Server Error');
-               header('Content-type: text/html; charset=utf-8');
-               echo "<html><body><h1>Internal Server Error</h1>";
-               echo '<p>Nominatim has encountered an internal error while processing your request. This is most likely because of a bug in the software.</p>';
-               echo "<p><b>Details:</b> ".$sError,"</p>";
-               echo '<p>Feel free to report the bug in the <a href="http://trac.openstreetmap.org">OSM bug database</a>. Please include the error message above and the URL you used.</p>';
-               if (CONST_Debug)
-               {
-                       echo "<hr><h2>Debugging Information</h2><br>";
-                       if ($sSQL)
-                       {
-                               echo "<h3>SQL query</h3><code>".$sSQL."</code>";
-                       }
-                       if ($vDumpVar)
-                       {
-                               echo "<h3>Result</h3> <code>";
-                               var_dump($vDumpVar);
-                               echo "</code>";
-                       }
-               }
-               echo "\n</body></html>\n";
-               exit;
-       }
-
-
-       function userError($sError)
-       {
-               header('HTTP/1.0 400 Bad Request');
-               header('Content-type: text/html; charset=utf-8');
-               echo "<html><body><h1>Bad Request</h1>";
-               echo '<p>Nominatim has encountered an error with your request.</p>';
-               echo "<p><b>Details:</b> ".$sError,"</p>";
-               echo '<p>If you feel this error is incorrect feel free to report the bug in the <a href="http://trac.openstreetmap.org">OSM bug database</a>. Please include the error message above and the URL you used.</p>';
-               echo "\n</body></html>\n";
-               exit;
-       }
-
-
        function fail($sError, $sUserError = false)
        {
                if (!$sUserError) $sUserError = $sError;
@@ -49,17 +9,6 @@
        }
 
 
-       function getBlockingProcesses()
-       {
-               $sStats = file_get_contents('/proc/stat');
-               if (preg_match('/procs_blocked ([0-9]+)/i', $sStats, $aMatches))
-               {
-                       return (int)$aMatches[1];
-               }
-               return 0;
-       }
-
-
        function getLoadAverage()
        {
                $sLoadAverage = file_get_contents('/proc/loadavg');
@@ -71,7 +20,7 @@
        function getProcessorCount()
        {
                $sCPU = file_get_contents('/proc/cpuinfo');
-               preg_match_all('#processor      : [0-9]+#', $sCPU, $aMatches);
+               preg_match_all('#processor\s+: [0-9]+#', $sCPU, $aMatches);
                return sizeof($aMatches[0]);
        }
 
@@ -95,7 +44,7 @@
        function bySearchRank($a, $b)
        {
                if ($a['iSearchRank'] == $b['iSearchRank'])
-            return strlen($a['sOperator']) + strlen($a['sHouseNumber']) - strlen($b['sOperator']) - strlen($b['sHouseNumber']);
+                       return strlen($a['sOperator']) + strlen($a['sHouseNumber']) - strlen($b['sOperator']) - strlen($b['sHouseNumber']);
                return ($a['iSearchRank'] < $b['iSearchRank']?-1:1);
        }
 
        {
                if ($a['importance'] != $b['importance'])
                        return ($a['importance'] > $b['importance']?-1:1);
-               /*
-                  if ($a['aPointPolygon']['numfeatures'] != $b['aPointPolygon']['numfeatures'])
-                  return ($a['aPointPolygon']['numfeatures'] > $b['aPointPolygon']['numfeatures']?-1:1);
-                  if ($a['aPointPolygon']['area'] != $b['aPointPolygon']['area'])
-                  return ($a['aPointPolygon']['area'] > $b['aPointPolygon']['area']?-1:1);
-               //              if ($a['levenshtein'] != $b['levenshtein'])
-               //                      return ($a['levenshtein'] < $b['levenshtein']?-1:1);
-               if ($a['rank_search'] != $b['rank_search'])
-               return ($a['rank_search'] < $b['rank_search']?-1:1);
-                */
+
                return ($a['foundorder'] < $b['foundorder']?-1:1);
        }
 
                return $aResult;
        }
 
+       function getInverseWordSets($aWords, $iDepth)
+       {
+               $aResult = array(array(join(' ',$aWords)));
+               $sFirstToken = '';
+               if ($iDepth < 8)
+               {
+                       while(sizeof($aWords) > 1)
+                       {
+                               $sWord = array_pop($aWords);
+                               $sFirstToken = $sWord.($sFirstToken?' ':'').$sFirstToken;
+                               $aRest = getInverseWordSets($aWords, $iDepth+1);
+                               foreach($aRest as $aSet)
+                               {
+                                       $aResult[] = array_merge(array($sFirstToken),$aSet);
+                               }
+                       }
+               }
+               return $aResult;
+       }
+
 
        function getTokensFromSets($aSets)
        {
                        {
                                $aTokens[' '.$sWord] = ' '.$sWord;
                                $aTokens[$sWord] = $sWord;
-                               //if (!strpos($sWord,' ')) $aTokens[$sWord] = $sWord;
                        }
                }
                return $aTokens;
           GB Postcode functions
         */
 
-       function gbPostcodeAlphaDifference($s1, $s2)
-       {
-               $aValues = array(
-                               'A'=>0,
-                               'B'=>1,
-                               'D'=>2,
-                               'E'=>3,
-                               'F'=>4,
-                               'G'=>5,
-                               'H'=>6,
-                               'J'=>7,
-                               'L'=>8,
-                               'N'=>9,
-                               'O'=>10,
-                               'P'=>11,
-                               'Q'=>12,
-                               'R'=>13,
-                               'S'=>14,
-                               'T'=>15,
-                               'U'=>16,
-                               'W'=>17,
-                               'X'=>18,
-                               'Y'=>19,
-                               'Z'=>20);
-               return abs(($aValues[$s1[0]]*21+$aValues[$s1[1]]) - ($aValues[$s2[0]]*21+$aValues[$s2[1]]));
-       }
-
-
        function gbPostcodeCalculate($sPostcode, $sPostcodeSector, $sPostcodeEnd, &$oDB)
        {
                // Try an exact match on the gb_postcode table
                $sSQL = 'select \'AA\', ST_X(ST_Centroid(geometry)) as lon,ST_Y(ST_Centroid(geometry)) as lat from gb_postcode where postcode = \''.$sPostcode.'\'';
-               $aNearPostcodes = $oDB->getAll($sSQL);
-               if (PEAR::IsError($aNearPostcodes))
-               {
-                       var_dump($sSQL, $aNearPostcodes);
-                       exit;
-               }
+               $aNearPostcodes = chksql($oDB->getAll($sSQL));
 
                if (sizeof($aNearPostcodes))
                {
        }
 
 
-       function usPostcodeCalculate($sPostcode, &$oDB)
-       {
-               $iZipcode = (int)$sPostcode;
-
-               // Try an exact match on the us_zippostcode table
-               $sSQL = 'select zipcode, ST_X(ST_Centroid(geometry)) as lon,ST_Y(ST_Centroid(geometry)) as lat from us_zipcode where zipcode = '.$iZipcode;
-               $aNearPostcodes = $oDB->getAll($sSQL);
-               if (PEAR::IsError($aNearPostcodes))
-               {
-                       var_dump($sSQL, $aNearPostcodes);
-                       exit;
-               }
-
-               if (!sizeof($aNearPostcodes))
-               {
-                       $sSQL = 'select zipcode,ST_X(ST_Centroid(geometry)) as lon,ST_Y(ST_Centroid(geometry)) as lat from us_zipcode where zipcode between '.($iZipcode-100).' and '.($iZipcode+100).' order by abs(zipcode - '.$iZipcode.') asc limit 5';
-                       $aNearPostcodes = $oDB->getAll($sSQL);
-                       if (PEAR::IsError($aNearPostcodes))
-                       {
-                               var_dump($sSQL, $aNearPostcodes);
-                               exit;
-                       }
-               }
-
-               if (!sizeof($aNearPostcodes))
-               {
-                       return false;
-               }
-
-               $fTotalLat = 0;
-               $fTotalLon = 0;
-               $fTotalFac = 0;
-               foreach($aNearPostcodes as $aPostcode)
-               {
-                       $iDiff = abs($aPostcode['zipcode'] - $iZipcode) + 1;
-                       if ($iDiff == 0)
-                               $fFac = 1;
-                       else
-                               $fFac = 1/($iDiff*$iDiff);
-
-                       $fTotalFac += $fFac;
-                       $fTotalLat += $aPostcode['lat'] * $fFac;
-                       $fTotalLon += $aPostcode['lon'] * $fFac;
-               }
-               if ($fTotalFac)
-               {
-                       $fLat = $fTotalLat / $fTotalFac;
-                       $fLon = $fTotalLon / $fTotalFac;
-                       return array(array('lat' => $fLat, 'lon' => $fLon, 'radius' => 0.2));
-               }
-               return false;
-
-               /*
-                  $fTotalFac is a surprisingly good indicator of accuracy
-                  $iZoom = 18 + round(log($fTotalFac,32));
-                  $iZoom = max(13,min(18,$iZoom));
-                */
-       }
-
-
        function getClassTypes()
        {
                return array(
  'landuse:farm' => array('label'=>'Farm','frequency'=>1201,'icon'=>'', 'defdiameter' => 0.02,),
  'place:farm' => array('label'=>'Farm','frequency'=>1162,'icon'=>'', 'defdiameter' => 0.02,),
 
- 'highway:motorway_junction' => array('label'=>'Motorway Junction','frequency'=>1126,'icon'=>'','simplelabel'=>'Road',),
+ 'highway:motorway_junction' => array('label'=>'Motorway Junction','frequency'=>1126,'icon'=>'','simplelabel'=>'Junction',),
  'highway:motorway' => array('label'=>'Motorway','frequency'=>4627,'icon'=>'','simplelabel'=>'Road',),
  'highway:trunk' => array('label'=>'Trunk','frequency'=>23084,'icon'=>'','simplelabel'=>'Road',),
  'highway:primary' => array('label'=>'Primary','frequency'=>32138,'icon'=>'','simplelabel'=>'Road',),
  'tourism:hotel' => array('label'=>'Hotel','frequency'=>2150,'icon'=>'accommodation_hotel2',),
  'tourism:motel' => array('label'=>'Motel','frequency'=>43,'icon'=>'',),
  'amenity:cinema' => array('label'=>'Cinema','frequency'=>277,'icon'=>'tourist_cinema',),
- 'tourism:information' => array('label'=>'Information','frequency'=>224,'icon'=>'amenity_information',),
  'tourism:artwork' => array('label'=>'Artwork','frequency'=>171,'icon'=>'tourist_art_gallery2',),
  'historic:archaeological_site' => array('label'=>'Archaeological Site','frequency'=>407,'icon'=>'tourist_archaeological2',),
  'amenity:doctors' => array('label'=>'Doctors','frequency'=>581,'icon'=>'health_doctors',),
  'shop:electronics' => array('label'=>'Electronics','frequency'=>96,'icon'=>'',),
  'shop:department_store' => array('label'=>'Department Store','frequency'=>86,'icon'=>'',),
  'shop:books' => array('label'=>'Books','frequency'=>85,'icon'=>'',),
- 'shop:yes' => array('label'=>'Yes','frequency'=>68,'icon'=>'',),
+ 'shop:yes' => array('label'=>'Shop','frequency'=>68,'icon'=>'',),
  'shop:outdoor' => array('label'=>'Outdoor','frequency'=>67,'icon'=>'',),
  'shop:mall' => array('label'=>'Mall','frequency'=>63,'icon'=>'',),
  'shop:florist' => array('label'=>'Florist','frequency'=>61,'icon'=>'',),
  'shop:travel_agency' => array('label'=>'Travel Agency','frequency'=>21,'icon'=>'',),
  'shop:hifi' => array('label'=>'Hifi','frequency'=>21,'icon'=>'',),
  'amenity:shop' => array('label'=>'Shop','frequency'=>61,'icon'=>'',),
+ 'tourism:information' => array('label'=>'Information','frequency'=>224,'icon'=>'amenity_information',),
 
  'place:house' => array('label'=>'House','frequency'=>2086,'icon'=>'','defzoom'=>18,),
  'place:house_name' => array('label'=>'House','frequency'=>2086,'icon'=>'','defzoom'=>18,),
  'historic:roman_road' => array('label'=>'Roman Road','frequency'=>27,'icon'=>'',),
  'historic:fort' => array('label'=>'Fort','frequency'=>26,'icon'=>'',),
  'railway:subway_entrance' => array('label'=>'Subway Entrance','frequency'=>26,'icon'=>'',),
- 'historic:yes' => array('label'=>'Yes','frequency'=>25,'icon'=>'',),
+ 'historic:yes' => array('label'=>'Historic','frequency'=>25,'icon'=>'',),
  'highway:gate' => array('label'=>'Gate','frequency'=>25,'icon'=>'',),
  'leisure:fishing' => array('label'=>'Fishing','frequency'=>24,'icon'=>'',),
  'historic:museum' => array('label'=>'Museum','frequency'=>24,'icon'=>'',),
 
  'place:houses' => array('label'=>'Houses','frequency'=>85,'icon'=>'',),
  'railway:preserved' => array('label'=>'Preserved','frequency'=>227,'icon'=>'',),
- 'waterway:derelict canal' => array('label'=>'Derelict Canal','frequency'=>21,'icon'=>'',),
+ 'waterway:derelict_canal' => array('label'=>'Derelict Canal','frequency'=>21,'icon'=>'',),
  'amenity:dead_pub' => array('label'=>'Dead Pub','frequency'=>20,'icon'=>'',),
  'railway:disused_station' => array('label'=>'Disused Station','frequency'=>114,'icon'=>'',),
  'railway:abandoned' => array('label'=>'Abandoned','frequency'=>641,'icon'=>'',),
                return $aOrders;
        }
 
+       function getResultDiameter($aResult)
+       {
+               $aClassType = getClassTypes();
+
+               $fDiameter = 0.0001;
+
+               if (isset($aResult['class'])
+                         && isset($aResult['type'])
+                         && isset($aResult['admin_level'])
+                         && isset($aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter'])
+                               && $aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter'])
+               {
+                       $fDiameter = $aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter'];
+               }
+               elseif (isset($aResult['class'])
+                         && isset($aResult['type'])
+                         && isset($aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter'])
+                               && $aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter'])
+               {
+                       $fDiameter = $aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter'];
+               }
+
+               return $fDiameter;
+       }
+
 
-       function javascript_renderData($xVal)
+       function javascript_renderData($xVal, $iOptions = 0)
        {
-               header("Access-Control-Allow-Origin: *");
-               $jsonout = json_encode($xVal);
+               if (defined('PHP_VERSION_ID') && PHP_VERSION_ID > 50400)
+                       $iOptions |= JSON_UNESCAPED_UNICODE;
+               $jsonout = json_encode($xVal, $iOptions);
 
                if( ! isset($_GET['json_callback']))
                {
        }
 
 
-       function getAddressDetails(&$oDB, $sLanguagePrefArraySQL, $iPlaceID, $sCountryCode = false, $bRaw = false)
+       function getAddressDetails(&$oDB, $sLanguagePrefArraySQL, $iPlaceID, $sCountryCode = false, $housenumber = -1, $bRaw = false)
        {
-               $sSQL = "select *,get_name_by_language(name,$sLanguagePrefArraySQL) as localname from get_addressdata($iPlaceID)";
+               $sSQL = "select *,get_name_by_language(name,$sLanguagePrefArraySQL) as localname from get_addressdata($iPlaceID, $housenumber)";
                if (!$bRaw) $sSQL .= " WHERE isaddress OR type = 'country_code'";
                $sSQL .= " order by rank_address desc,isaddress desc";
 
-               $aAddressLines = $oDB->getAll($sSQL);
-               if (PEAR::IsError($aAddressLines))
-               {
-                       var_dump($aAddressLines);
-                       exit;
-               }
+               $aAddressLines = chksql($oDB->getAll($sSQL));
                if ($bRaw) return $aAddressLines;
                //echo "<pre>";
                //var_dump($aAddressLines);
                        $sSQL .= ' OR ST_DWithin('.$sPointSQL.', ST_Centroid(geometry), '.$fSearchDiam.'))';
                        $sSQL .= ' ORDER BY ST_distance('.$sPointSQL.', geometry) ASC limit 1';
                        //var_dump($sSQL);
-                       $aPlace = $oDB->getRow($sSQL);
-                       if (PEAR::IsError($aPlace))
-                       {
-                               var_Dump($sSQL, $aPlace);
-                               exit;
-                       }
+                       $aPlace = chksql($oDB->getRow($sSQL));
                        $iPlaceID = $aPlace['place_id'];
                }
 
                if ($iPlaceID)
                {
                        $sSQL = "select address_place_id from place_addressline where cached_rank_address <= $iMaxRank and place_id = $iPlaceID order by cached_rank_address desc,isaddress desc,distance desc limit 1";
-                       $iPlaceID = $oDB->getOne($sSQL);
-                       if (PEAR::IsError($iPlaceID))
-                       {
-                               var_Dump($sSQL, $iPlaceID);
-                               exit;
-                       }
+                       $iPlaceID = chksql($oDB->getOne($sSQL));
 
                        if ($iPlaceID && $aPlace['place_id'] && $iMaxRank < 28)
                        {
                                $sSQL = "select address_place_id from place_addressline where cached_rank_address <= $iMaxRank and place_id = ".$aPlace['place_id']." order by cached_rank_address desc,isaddress desc,distance desc";
-                               $iPlaceID = $oDB->getOne($sSQL);
-                               if (PEAR::IsError($iPlaceID))
-                               {
-                                       var_Dump($sSQL, $iPlaceID);
-                                       exit;
-                               }
+                               $iPlaceID = chksql($oDB->getOne($sSQL));
                        }
                        if (!$iPlaceID)
                        {
                }
                // degrees decimal seconds
                // N 40 26 46 W 79 58 56
-               // N 40° 26′ 46″ W, 79° 58′ 56″
+               // N 40° 26′ 46″, W 79° 58′ 56″
                //                      1        2            3            4                5        6            7            8
                elseif (preg_match('/\\b([NS])[ ]([0-9]+)[° ]+([0-9]+)[′\' ]+([0-9]+)[″"]*[, ]+([EW])[ ]([0-9]+)[° ]+([0-9]+)[′\' ]+([0-9]+)[″"]*\\b/', $sQuery, $aData))
                {
 
                return array('lat' => $fQueryLat, 'lon' => $fQueryLon, 'query' => $sQuery);
        }
+
+
+       function geometryText2Points($geometry_as_text, $fRadius)
+       {
+               $aPolyPoints = NULL;
+               if (preg_match('#POLYGON\\(\\(([- 0-9.,]+)#', $geometry_as_text, $aMatch))
+               {
+                       preg_match_all('/(-?[0-9.]+) (-?[0-9.]+)/', $aMatch[1], $aPolyPoints, PREG_SET_ORDER);
+               }
+               elseif (preg_match('#LINESTRING\\(([- 0-9.,]+)#', $geometry_as_text, $aMatch))
+               {
+                       preg_match_all('/(-?[0-9.]+) (-?[0-9.]+)/', $aMatch[1], $aPolyPoints, PREG_SET_ORDER);
+               }
+               elseif (preg_match('#MULTIPOLYGON\\(\\(\\(([- 0-9.,]+)#', $geometry_as_text, $aMatch))
+               {
+                       preg_match_all('/(-?[0-9.]+) (-?[0-9.]+)/', $aMatch[1], $aPolyPoints, PREG_SET_ORDER);
+               }
+               elseif (preg_match('#POINT\\((-?[0-9.]+) (-?[0-9.]+)\\)#', $geometry_as_text, $aMatch))
+               {
+                       $aPolyPoints = createPointsAroundCenter($aMatch[1], $aMatch[2], $fRadius);
+               }
+
+               if (isset($aPolyPoints))
+               {
+                       $aResultPoints = array();
+                       foreach($aPolyPoints as $aPoint)
+                       {
+                               $aResultPoints[] = array($aPoint[1], $aPoint[2]);
+                       }
+                       return $aResultPoints;
+               }
+
+               return;
+       }
+
+       function createPointsAroundCenter($fLon, $fLat, $fRadius)
+       {
+                       $iSteps = max(8, min(100, ($fRadius * 40000)^2));
+                       $fStepSize = (2*pi())/$iSteps;
+                       $aPolyPoints = array();
+                       for($f = 0; $f < 2*pi(); $f += $fStepSize)
+                       {
+                               $aPolyPoints[] = array('', $fLon+($fRadius*sin($f)), $fLat+($fRadius*cos($f)) );
+                       }
+                       return $aPolyPoints;
+       }