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
##
# 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
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.friends.identifiable)
+ 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
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
#------------------------------------------------------------
#------------------------------------------------------------
##
- # 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