+ # Save a way to the database, including all nodes. Any nodes in the previous
+ # version and no longer used are deleted.
+ #
+ # Parameters:
+ # 0. hash of renumbered nodes
+ # 1. current user token (for authentication)
+ # 2. current changeset
+ # 3. new way version
+ # 4. way ID
+ # 5. list of nodes in way
+ # 6. hash of way tags
+ # 7. array of nodes to change (each one is [lon,lat,id,version,tags])
+ #
+ # Returns:
+ # 0. '0' (code for success),
+ # 1. original way id (unchanged),
+ # 2. new way id,
+ # 3. hash of renumbered nodes (old id=>new id),
+ # 4. way version,
+ # 5. hash of node versions (node=>version)
+
+ def putway(renumberednodes, usertoken, changeset, version, originalway, pointlist, attributes, nodes) #:doc:
+
+ # -- Initialise
+
+ user = getuser(usertoken)
+ if !user then return -1,"You are not logged in, so the way could not be saved." end
+ if pointlist.length < 2 then return -2,"Server error - way is only #{points.length} points long." end
+
+ originalway = originalway.to_i
+ 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
+
+ nodeversions = {}
+ nodes.each do |a|
+ lon = a[0].to_f
+ lat = a[1].to_f
+ id = a[2].to_i
+ version = a[3].to_i
+ if id == 0 then return -2,"Server error - node with id 0 found in way #{originalway}." end
+ if lat== 90 then return -2,"Server error - node with latitude -90 found in way #{originalway}." end
+ if renumberednodes[id] then id = renumberednodes[id] end
+
+ node = Node.new
+ node.changeset_id = changeset
+ node.lat = lat
+ node.lon = lon
+ node.tags = a[4]
+ node.tags.delete('created_by')
+ node.version = version
+ if id <= 0
+ # We're creating the node
+ node.create_with_history(user)
+ renumberednodes[id] = node.id
+ nodeversions[id] = node.version
+ else
+ # We're updating an existing node
+ previous=Node.find(id)
+ previous.update_from(node, user)
+ nodeversions[id] = previous.version
+ end
+ end
+
+ # -- Delete any unique nodes no longer used
+
+ uniques=uniques-pointlist
+ uniques.each do |n|
+ node = Node.find(n)
+ new_node = Node.new
+ new_node.changeset_id = changeset
+ new_node.version = version
+ node.delete_with_history!(new_node, user)
+ 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
+ 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}"]
+ 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."]
+ rescue OSM::APIAlreadyDeletedError => ex
+ 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 :-()"]