- # 2. new node id.
-
- def putpoi(usertoken, id, lon, lat, tags, visible) #:doc:
- uid = getuserid(usertoken)
- if !uid then return -1,"You are not logged in, so the point could not be saved." end
-
- id = id.to_i
- visible = (visible.to_i == 1)
-
- if id > 0 then
- node = Node.find(id)
-
- if !visible then
- unless node.ways.empty? then return -1,"The point has since become part of a way, so you cannot save it as a POI." end
- deleteitemrelations(id, 'node')
- end
- else
- node = Node.new
- end
-
- node.user_id = uid
- node.lat = lat
- node.lon = lon
- node.tags = Tags.join(tags)
- node.visible = visible
- node.save_with_history!
-
- [0, id, node.id]
+ # 2. new node id,
+ # 3. version.
+
+ def putpoi(usertoken, changeset_id, version, id, lon, lat, tags, visible) #:doc:
+ user = getuser(usertoken)
+ if !user then return -1,"You are not logged in, so the point could not be saved." end
+
+ id = id.to_i
+ visible = (visible.to_i == 1)
+ node = nil
+ new_node = nil
+ Node.transaction do
+ if id > 0 then
+ node = Node.find(id)
+
+ if !visible then
+ unless node.ways.empty? then return -1,"The point has since become part of a way, so you cannot save it as a POI." end
+ end
+ end
+ # We always need a new node, based on the data that has been sent to us
+ new_node = Node.new
+
+ new_node.changeset_id = changeset_id
+ new_node.version = version
+ new_node.lat = lat
+ new_node.lon = lon
+ new_node.tags = tags
+ if id <= 0
+ # We're creating the node
+ new_node.create_with_history(user)
+ elsif visible
+ # We're updating the node
+ node.update_from(new_node, user)
+ else
+ # We're deleting the node
+ node.delete_with_history!(new_node, user)
+ end
+ end # transaction
+
+ if id <= 0
+ return [0, id, new_node.id, new_node.version]
+ else
+ return [0, id, node.id, node.version]
+ end
+ rescue OSM::APIChangesetAlreadyClosedError => ex
+ 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, "Sorry, someone else has changed this point since you started editing. Please click the 'Edit' tab to reload the area."]
+ rescue OSM::APIAlreadyDeletedError => ex
+ return [-1, "The point has already been deleted"]
+ rescue OSM::APIError => ex
+ # Some error that we don't specifically catch
+ return [-2, "Something really bad happened :-()"]