X-Git-Url: https://git.openstreetmap.org./rails.git/blobdiff_plain/4370fe45add697f481ab88764aba8379eb3316c2..437eb1fa8a518e760d76e51a1ab6ddd20c39ffc9:/app/controllers/changesets_controller.rb diff --git a/app/controllers/changesets_controller.rb b/app/controllers/changesets_controller.rb index aa9d81343..07e7a365f 100644 --- a/app/controllers/changesets_controller.rb +++ b/app/controllers/changesets_controller.rb @@ -2,14 +2,14 @@ class ChangesetsController < ApplicationController include UserMethods + include PaginationMethods layout "site" before_action :authorize_web before_action :set_locale - before_action -> { check_database_readable(:need_api => true) }, :only => [:index, :feed, :show] + before_action -> { check_database_readable(:need_api => true) } before_action :require_oauth, :only => :show - before_action :check_database_writable, :only => [:subscribe, :unsubscribe] authorize_resource @@ -18,12 +18,13 @@ class ChangesetsController < ApplicationController ## # list non-empty changesets in reverse chronological order def index - param! :max_id, Integer, :min => 1 + param! :before, Integer, :min => 1 + param! :after, Integer, :min => 1 - @params = params.permit(:display_name, :bbox, :friends, :nearby, :max_id, :list) + @params = params.permit(:display_name, :bbox, :friends, :nearby, :before, :after, :list) - if request.format == :atom && @params[:max_id] - redirect_to url_for(@params.merge(:max_id => nil)), :status => :moved_permanently + if request.format == :atom && (@params[:before] || @params[:after]) + redirect_to url_for(@params.merge(:before => nil, :after => nil)), :status => :moved_permanently return end @@ -53,16 +54,17 @@ class ChangesetsController < ApplicationController changesets.where("false") end elsif @params[:bbox] - changesets = conditions_bbox(changesets, BoundingBox.from_bbox_params(params)) + bbox_array = @params[:bbox].split(",").map(&:to_f) + raise OSM::APIBadUserInput, "The parameter bbox must be of the form min_lon,min_lat,max_lon,max_lat" unless bbox_array.count == 4 + + changesets = conditions_bbox(changesets, *bbox_array) elsif @params[:friends] && current_user changesets = changesets.where(:user => current_user.followings.identifiable) elsif @params[:nearby] && current_user changesets = changesets.where(:user => current_user.nearby) end - changesets = changesets.where(:changesets => { :id => ..@params[:max_id] }) if @params[:max_id] - - @changesets = changesets.order("changesets.id DESC").limit(20).preload(:user, :changeset_tags, :comments) + @changesets, @newer_changesets_id, @older_changesets_id = get_page_items(changesets, :includes => [:user, :changeset_tags, :comments]) render :action => :index, :layout => false end @@ -107,34 +109,6 @@ class ChangesetsController < ApplicationController render :template => "browse/not_found", :status => :not_found, :layout => map_layout end - ## - # subscribe to a changeset - def subscribe - @changeset = Changeset.find(params[:id]) - - if request.post? - @changeset.subscribe(current_user) unless @changeset.subscribed?(current_user) - - redirect_to changeset_path(@changeset) - end - rescue ActiveRecord::RecordNotFound - render :action => "no_such_entry", :status => :not_found - end - - ## - # unsubscribe from a changeset - def unsubscribe - @changeset = Changeset.find(params[:id]) - - if request.post? - @changeset.unsubscribe(current_user) - - redirect_to changeset_path(@changeset) - end - rescue ActiveRecord::RecordNotFound - render :action => "no_such_entry", :status => :not_found - end - private #------------------------------------------------------------ @@ -142,21 +116,37 @@ class ChangesetsController < ApplicationController #------------------------------------------------------------ ## - # if a bounding box was specified do some sanity checks. # restrict changesets to those enclosed by a bounding box - def conditions_bbox(changesets, bbox) - if bbox - bbox.check_boundaries - bbox = bbox.to_scaled - - changesets.where("min_lon < ? and max_lon > ? and min_lat < ? and max_lat > ?", - bbox.max_lon.to_i, bbox.min_lon.to_i, - bbox.max_lat.to_i, bbox.min_lat.to_i) - else + def conditions_bbox(changesets, min_lon, min_lat, max_lon, max_lat) + db_min_lat = (min_lat * GeoRecord::SCALE).to_i + db_max_lat = (max_lat * GeoRecord::SCALE).to_i + db_min_lon = (wrap_lon(min_lon) * GeoRecord::SCALE).to_i + db_max_lon = (wrap_lon(max_lon) * GeoRecord::SCALE).to_i + + changesets = changesets.where("min_lat < ? and max_lat > ?", db_max_lat, db_min_lat) + + if max_lon - min_lon >= 360 + # the query bbox spans the entire world, therefore no lon checks are necessary changesets + elsif db_min_lon <= db_max_lon + # the normal case when the query bbox doesn't include the antimeridian + changesets.where("min_lon < ? and max_lon > ?", db_max_lon, db_min_lon) + else + # the query bbox includes the antimeridian + # this case works as if there are two query bboxes: + # [-180*SCALE .. db_max_lon], [db_min_lon .. 180*SCALE] + # it would be necessary to check if changeset bboxes intersect with either of the query bboxes: + # (changesets.min_lon < db_max_lon and changesets.max_lon > -180*SCALE) or (changesets.min_lon < 180*SCALE and changesets.max_lon > db_min_lon) + # but the comparisons with -180*SCALE and 180*SCALE are unnecessary: + # (changesets.min_lon < db_max_lon) or (changesets.max_lon > db_min_lon) + changesets.where("min_lon < ? or max_lon > ?", db_max_lon, db_min_lon) end end + def wrap_lon(lon) + ((lon + 180) % 360) - 180 + end + ## # eliminate empty changesets (where the bbox has not been set) # this should be applied to all changeset list displays