# Start new changeset
def startchangeset(usertoken, cstags, closeid, closecomment)
- user = getuserid(usertoken)
+ user = getuser(usertoken)
if !user then return -1,"You are not logged in, so Potlatch can't write any changes to the database." end
# close previous changeset and add comment
cs.user_id = user.id
# smsm1 doesn't like the next two lines and thinks they need to be abstracted to the model more/better
cs.created_at = Time.now
- cs.closed_at = Time.new + Changeset::IDLE_TIMEOUT
+ cs.closed_at = cs.created_at + Changeset::IDLE_TIMEOUT
cs.save_with_tags!
return [0,cs.id]
end
# 3. hash of tags,
# 4. version,
# 5. is this the current, visible version? (boolean)
-
+ #
+ # *** FIXME:
+ # Should work by timestamp, not version (so that we can recover versions when
+ # a node has been changed, but not the enclosing way)
+ # Use strptime (http://www.ruby-doc.org/core/classes/DateTime.html) to
+ # to turn string back into timestamp.
+
def getway_old(id, version) #:doc:
if version < 0
old_way = OldWay.find(:first, :conditions => ['visible = ? AND id = ?', true, id], :order => 'version DESC')
# Find history of a way. Returns 'way', id, and
# an array of previous versions.
+ #
+ # *** FIXME:
+ # Should look for changes in constituent nodes as well,
+ # and return timestamps.
+ # Heuristic: Find all nodes that have ever been part of the way;
+ # get a list of their revision dates; add revision dates of the way;
+ # sort and collapse list (to within 2 seconds); trim all dates before the
+ # start dateÊof the way.
def getway_history(wayid) #:doc:
- begin
- history = Way.find(wayid).old_ways.reverse.collect do |old_way|
- user_object = old_way.changeset.user
- user = user_object.data_public? ? user_object.display_name : 'anonymous'
- uid = user_object.data_public? ? user_object.id : 0
- [old_way.version, old_way.timestamp.strftime("%d %b %Y, %H:%M"), old_way.visible ? 1 : 0, user, uid]
+
+ # Find list of revision dates for way and all constituent nodes
+ revdates=[]
+ Way.find(wayid).old_ways.collect do |a|
+ revdates.push(a.timestamp)
+ a.nds.each do |n|
+ Node.find(n).old_nodes.collect do |o|
+ revdates.push(o.timestamp)
+ end
end
+ end
+ waycreated=revdates[0]
+ revdates.uniq!
+ revdates.sort!
- return ['way',wayid,history]
- rescue ActiveRecord::RecordNotFound
- return ['way', wayid, []]
+ # Remove any dates (from nodes) before first revision date of way
+ revdates.delete_if { |d| d<waycreated }
+ # Remove any elements where 2 seconds doesn't elapse before next one
+ revdates.delete_if { |d| revdates.include?(d+1) or revdates.include?(d+2) }
+
+RAILS_DEFAULT_LOGGER.info("** revision dates: #{revdates.inspect}")
+RAILS_DEFAULT_LOGGER.info("** range: #{revdates[-1]-revdates[0]}")
+
+ history = Way.find(wayid).old_ways.reverse.collect do |old_way|
+ user_object = old_way.changeset.user
+ user = user_object.data_public? ? user_object.display_name : 'anonymous'
+ uid = user_object.data_public? ? user_object.id : 0
+ [old_way.version, old_way.timestamp.strftime("%d %b %Y, %H:%M"), old_way.visible ? 1 : 0, user, uid]
end
+
+ return ['way',wayid,history]
+ rescue ActiveRecord::RecordNotFound
+ return ['way', wayid, []]
end
# Find history of a node. Returns 'node', id, and
# Returns array listing GPXs, each one comprising id, name and description.
def findgpx(searchterm, usertoken)
- uid = getuserid(usertoken)
+ user = getuser(usertoken)
if !uid then return -1,"You must be logged in to search for GPX traces." end
gpxs = []
if searchterm.to_i>0 then
- gpx = Trace.find(searchterm.to_i, :conditions => ["visible=? AND (public=? OR user_id=?)",true,true,uid] )
+ gpx = Trace.find(searchterm.to_i, :conditions => ["visible=? AND (public=? OR user_id=?)",true,true,user.id] )
if gpx then
gpxs.push([gpx.id, gpx.name, gpx.description])
end
else
- Trace.find(:all, :limit => 21, :conditions => ["visible=? AND (public=? OR user_id=?) AND MATCH(name) AGAINST (?)",true,true,uid,searchterm] ).each do |gpx|
+ Trace.find(:all, :limit => 21, :conditions => ["visible=? AND (public=? OR user_id=?) AND MATCH(name) AGAINST (?)",true,true,user.id,searchterm] ).each do |gpx|
gpxs.push([gpx.id, gpx.name, gpx.description])
end
end
# 2. new relation id.
def putrelation(renumberednodes, renumberedways, usertoken, changeset, version, relid, tags, members, visible) #:doc:
- user = getuserid(usertoken)
+ user = getuser(usertoken)
if !user then return -1,"You are not logged in, so the relation could not be saved." end
relid = relid.to_i
return [0, relid, relation.id, relation.version]
end
rescue OSM::APIChangesetAlreadyClosedError => ex
- return [-1, "The changeset #{ex.changeset.id} was closed at #{ex.changeset.closed_at}"]
+ return [-1, "The changeset #{ex.changeset.id} was closed at #{ex.changeset.closed_at}."]
rescue OSM::APIVersionMismatchError => ex
# Really need to check to see whether this is a server load issue, and the
# last version was in the same changeset, or belongs to the same user, then
# we can return something different
- return [-3, "You have taken too long to edit, please reload the area"]
+ return [-3, "You have taken too long to edit, please reload the area."]
rescue OSM::APIAlreadyDeletedError => ex
return [-1, "The object has already been deleted"]
rescue OSM::APIError => ex
# version and no longer used are deleted.
#
# Parameters:
- # 0. hash of renumbered nodes
+ # 0. hash of renumbered nodes (added by amf_controller)
# 1. current user token (for authentication)
# 2. current changeset
# 3. new way version
# 4. way version,
# 5. hash of node versions (node=>version)
- def putway(renumberednodes, usertoken, changeset, version, originalway, pointlist, attributes, nodes) #:doc:
+ def putway(renumberednodes, usertoken, changeset, wayversion, originalway, pointlist, attributes, nodes) #:doc:
# -- Initialise
if pointlist.length < 2 then return -2,"Server error - way is only #{points.length} points long." end
originalway = originalway.to_i
+ pointlist.collect! {|a| a.to_i }
+
+ way=nil # this is returned, so scope it outside the transaction
+ nodeversions = {}
Way.transaction do
# -- Get unique nodes
if originalway <= 0
- way = nil
uniques = []
else
way = Way.find(originalway)
uniques = way.unshared_node_ids
end
- new_way = Way.new
- #Ê-- Update each changed node
+ #-- Update each changed node
- nodeversions = {}
nodes.each do |a|
lon = a[0].to_f
lat = a[1].to_f
# We're creating the node
node.create_with_history(user)
renumberednodes[id] = node.id
- nodeversions[id] = node.version
+ nodeversions[node.id] = node.version
else
# We're updating an existing node
previous=Node.find(id)
previous.update_from(node, user)
- nodeversions[id] = previous.version
+ nodeversions[previous.id] = previous.version
end
end
# -- Save revised way
- if way.tags!=attributes or way.nds!=nodes or !way.visible?
- new_way = Way.new
- new_way.tags = attributes
- new_way.nds = pointlist
- new_way.changeset_id = changeset
- new_way.version = version
+ pointlist.collect! {|a|
+ renumberednodes[a] ? renumberednodes[a]:a
+ } # renumber nodes
+ new_way = Way.new
+ new_way.tags = attributes
+ new_way.nds = pointlist
+ new_way.changeset_id = changeset
+ new_way.version = wayversion
+ if originalway <= 0
+ new_way.create_with_history(user)
+ way=new_way # so we can get way.id and way.version
+ elsif way.tags!=attributes or way.nds!=pointlist or !way.visible?
way.update_from(new_way, user)
end
end # transaction
[0, originalway, way.id, renumberednodes, way.version, nodeversions]
rescue OSM::APIChangesetAlreadyClosedError => ex
- return [-1, "The changeset #{ex.changeset.id} was closed at #{ex.changeset.closed_at}"]
+ return [-2, "Sorry, your changeset #{ex.changeset.id} has been closed (at #{ex.changeset.closed_at})."]
rescue OSM::APIVersionMismatchError => ex
# Really need to check to see whether this is a server load issue, and the
# last version was in the same changeset, or belongs to the same user, then
# we can return something different
return [-3, "Sorry, someone else has changed this way since you started editing - please reload the area"]
rescue OSM::APITooManyWayNodesError => ex
- return [-1, "You have tried to upload a way with #{ex.provided}, however only #{ex.max} are allowed."]
+ return [-1, "You have tried to upload a really long way with #{ex.provided} points: only #{ex.max} are allowed."]
rescue OSM::APIAlreadyDeletedError => ex
- return [-1, "The object has already been deleted"]
+ return [-1, "The object has already been deleted."]
rescue OSM::APIError => ex
# Some error that we don't specifically catch
- return [-2, "Something really bad happened :-()"]
+ return [-2, "Something really bad happened :-(."]
end
# Save POI to the database.
end
return user
end
-
- def getuserid(token)
- user = getuser(token)
- return user ? user.id : nil;
- end
-
- # Compare two floating-point numbers to within 0.0000001
-
- def fpcomp(a,b) #:doc:
- return ((a/0.0000001).round==(b/0.0000001).round)
- end
# Send AMF response