X-Git-Url: https://git.openstreetmap.org/rails.git/blobdiff_plain/392d3d12264c83d7ab03d34471792476fac31cf6..a85f6d6e914d8990c5fd9ae30731ab6bf1c1337b:/app/controllers/geocoder_controller.rb diff --git a/app/controllers/geocoder_controller.rb b/app/controllers/geocoder_controller.rb index 312762216..81c179a67 100644 --- a/app/controllers/geocoder_controller.rb +++ b/app/controllers/geocoder_controller.rb @@ -6,17 +6,22 @@ class GeocoderController < ApplicationController before_action :authorize_web before_action :set_locale before_action :require_oauth, :only => [:search] + authorize_resource :class => false + before_action :normalize_params, :only => [:search] + def search - @params = normalize_params @sources = [] - if @params[:lat] && @params[:lon] - @sources.push(:name => "latlon", :url => root_path) - @sources.push(:name => "osm_nominatim_reverse", :url => nominatim_reverse_url(:format => "html")) - elsif @params[:query] - @sources.push(:name => "osm_nominatim", :url => nominatim_url(:format => "html")) + if params[:lat] && params[:lon] + @sources.push(:name => "latlon", :url => root_path, + :fetch_url => url_for(params.permit(:lat, :lon, :latlon_digits, :zoom).merge(:action => "search_latlon"))) + @sources.push(:name => "osm_nominatim_reverse", :url => nominatim_reverse_url(:format => "html"), + :fetch_url => url_for(params.permit(:lat, :lon, :zoom).merge(:action => "search_osm_nominatim_reverse"))) + elsif params[:query] + @sources.push(:name => "osm_nominatim", :url => nominatim_url(:format => "html"), + :fetch_url => url_for(params.permit(:query, :minlat, :minlon, :maxlat, :maxlon).merge(:action => "search_osm_nominatim"))) end if @sources.empty? @@ -34,13 +39,13 @@ class GeocoderController < ApplicationController # We've got two nondescript numbers for a query, which can mean both "lat, lon" or "lon, lat". @results = [] - if lat >= -90 && lat <= 90 && lon >= -180 && lon <= 180 + if lat.between?(-90, 90) && lon.between?(-180, 180) @results.push(:lat => params[:lat], :lon => params[:lon], :zoom => params[:zoom], :name => "#{params[:lat]}, #{params[:lon]}") end - if lon >= -90 && lon <= 90 && lat >= -180 && lat <= 180 + if lon.between?(-90, 90) && lat.between?(-180, 180) @results.push(:lat => params[:lon], :lon => params[:lat], :zoom => params[:zoom], :name => "#{params[:lon]}, #{params[:lat]}") @@ -54,10 +59,10 @@ class GeocoderController < ApplicationController end else # Coordinates in a query have come with markers for latitude and longitude. - if lat < -90 || lat > 90 + if !lat.between?(-90, 90) @error = "Latitude #{lat} out of range" render :action => "error" - elsif lon < -180 || lon > 180 + elsif !lon.between?(-180, 180) @error = "Longitude #{lon} out of range" render :action => "error" else @@ -101,9 +106,14 @@ class GeocoderController < ApplicationController if klass == "boundary" && type == "administrative" rank = (place.attributes["address_rank"].to_i + 1) / 2 prefix_name = t "geocoder.search_osm_nominatim.admin_levels.level#{rank}", :default => prefix_name + border_type = nil + place_type = nil + place_tags = %w[linked_place place] place.elements["extratags"].elements.each("tag") do |extratag| - prefix_name = t "geocoder.search_osm_nominatim.prefix.place.#{extratag.attributes['value']}", :default => prefix_name if extratag.attributes["key"] == "linked_place" || extratag.attributes["key"] == "place" + border_type = t "geocoder.search_osm_nominatim.border_types.#{extratag.attributes['value']}", :default => border_type if extratag.attributes["key"] == "border_type" + place_type = t "geocoder.search_osm_nominatim.prefix.place.#{extratag.attributes['value']}", :default => place_type if place_tags.include?(extratag.attributes["key"]) end + prefix_name = place_type || border_type || prefix_name end prefix = t ".prefix_format", :name => prefix_name object_type = place.attributes["osm_type"] @@ -206,13 +216,9 @@ class GeocoderController < ApplicationController if query = params[:query] query.strip! - if latlon = query.match(/^(?[NS])\s*(?\d{1,3}(?:\.\d+)?)°?\W*(?[EW])\s*(?\d{1,3}(?:\.\d+)?)°?$/) || # [NSEW] decimal degrees - query.match(/^(?\d{1,3}(?:\.\d+)?)°?\s*(?[NS])\W*(?\d{1,3}(?:\.\d+)?)°?\s*(?[EW])$/) || # decimal degrees [NSEW] - query.match(/^(?[NS])\s*(?\d{1,3})°?(?:\s*(?\d{1,3}(?:\.\d+)?)['′]?)\W*(?[EW])\s*(?\d{1,3})°?(?:\s*(?\d{1,3}(?:\.\d+)?)['′]?)$/) || # [NSEW] degrees, decimal minutes - query.match(/^(?\d{1,3})°?(?:\s*(?\d{1,3}(?:\.\d+)?)['′]?)\s*(?[NS])\W*(?\d{1,3})°?(?:\s*(?\d{1,3}(?:\.\d+)?)['′]?)\s*(?[EW])$/) || # degrees, decimal minutes [NSEW] - query.match(/^(?[NS])\s*(?\d{1,3})°?\s*(?\d{1,2})['′]?(?:\s*(?\d{1,3}(?:\.\d+)?)["″]?)\W*(?[EW])\s*(?\d{1,3})°?\s*(?\d{1,2})['′]?(?:\s*(?\d{1,3}(?:\.\d+)?)["″]?)$/) || # [NSEW] degrees, minutes, decimal seconds - query.match(/^(?\d{1,3})°?\s*(?\d{1,2})['′]?(?:\s*(?\d{1,3}(?:\.\d+)?)["″]?)\s*(?[NS])\W*(?\d{1,3})°?\s*(?\d{1,2})['′]?(?:\s*(?\d{1,3}(?:\.\d+)?)["″]?)\s*(?[EW])$/) # degrees, minutes, decimal seconds [NSEW] - params.merge!(to_decdeg(latlon.named_captures)).delete(:query) + if latlon = query.match(/^(?[NS])\s*#{dms_regexp('ns')}\W*(?[EW])\s*#{dms_regexp('ew')}$/) || + query.match(/^#{dms_regexp('ns')}\s*(?[NS])\W*#{dms_regexp('ew')}\s*(?[EW])$/) + params.merge!(to_decdeg(latlon.named_captures.compact)).delete(:query) elsif latlon = query.match(%r{^(?[+-]?\d+(?:\.\d+)?)(?:\s+|\s*[,/]\s*)(?[+-]?\d+(?:\.\d+)?)$}) params.merge!(:lat => latlon["lat"], :lon => latlon["lon"]).delete(:query) @@ -220,17 +226,23 @@ class GeocoderController < ApplicationController params[:latlon_digits] = true end end + end - params.permit(:query, :lat, :lon, :latlon_digits, :zoom, :minlat, :minlon, :maxlat, :maxlon) + def dms_regexp(name_prefix) + / + (?: (?<#{name_prefix}d>\d{1,3}(?:\.\d+)?)°? ) | + (?: (?<#{name_prefix}d>\d{1,3})°?\s*(?<#{name_prefix}m>\d{1,2}(?:\.\d+)?)['′]? ) | + (?: (?<#{name_prefix}d>\d{1,3})°?\s*(?<#{name_prefix}m>\d{1,2})['′]?\s*(?<#{name_prefix}s>\d{1,2}(?:\.\d+)?)["″]? ) + /x end def to_decdeg(captures) - ns = captures.fetch("ns").casecmp("s").zero? ? -1 : 1 + ns = captures.fetch("ns").casecmp?("s") ? -1 : 1 nsd = BigDecimal(captures.fetch("nsd", "0")) nsm = BigDecimal(captures.fetch("nsm", "0")) nss = BigDecimal(captures.fetch("nss", "0")) - ew = captures.fetch("ew").casecmp("w").zero? ? -1 : 1 + ew = captures.fetch("ew").casecmp?("w") ? -1 : 1 ewd = BigDecimal(captures.fetch("ewd", "0")) ewm = BigDecimal(captures.fetch("ewm", "0")) ews = BigDecimal(captures.fetch("ews", "0"))