- # 1. original way id (unchanged),
- # 2. new way id,
- # 3. hash of renumbered nodes (old id=>new id)
-
- def putway(renumberednodes, usertoken, originalway, points, attributes) #:doc:
-
- # -- Initialise and carry out checks
-
- uid = getuserid(usertoken)
- if !uid then return -1,"You are not logged in, so the way could not be saved." end
-
- originalway = originalway.to_i
-
- points.each do |a|
- if a[2] == 0 or a[2].nil? then return -2,"Server error - node with id 0 found in way #{originalway}." end
- if a[1] == 90 then return -2,"Server error - node with lat -90 found in way #{originalway}." end
- end
-
- if points.length < 2 then return -2,"Server error - way is only #{points.length} points long." end
-
- # -- Get unique nodes
-
- if originalway < 0
- way = Way.new
- uniques = []
- else
- way = Way.find(originalway)
- uniques = way.unshared_node_ids
- end
-
- # -- Compare nodes and save changes to any that have changed
-
- nodes = []
-
- points.each do |n|
- lon = n[0].to_f
- lat = n[1].to_f
- id = n[2].to_i
- savenode = false
-
- if renumberednodes[id]
- id = renumberednodes[id]
- elsif id < 0
- # Create new node
- node = Node.new
- savenode = true
- else
- node = Node.find(id)
- nodetags=node.tags_as_hash
- nodetags.delete('created_by')
- if !fpcomp(lat, node.lat) or !fpcomp(lon, node.lon) or
- n[4] != nodetags or !node.visible?
- savenode = true
- end
- end
-
- if savenode
- node.user_id = uid
- node.lat = lat
- node.lon = lon
- node.tags = Tags.join(n[4])
- node.visible = true
- node.save_with_history!
-
- if id != node.id
- renumberednodes[id] = node.id
- id = node.id
- end
- end
-
- uniques = uniques - [id]
- nodes.push(id)
- end
-
- # -- Delete any unique nodes
-
- uniques.each do |n|
- deleteitemrelations(n, 'node')
-
- node = Node.find(n)
- node.user_id = uid
- node.visible = false
- node.save_with_history!
- end
-
- # -- Save revised way
-
- way.tags = attributes
- way.nds = nodes
- way.user_id = uid
- way.visible = true
- way.save_with_history!
-
- [0, originalway, way.id, renumberednodes]
+ # 1. message,
+ # 2. original way id (unchanged),
+ # 3. new way id,
+ # 4. hash of renumbered nodes (old id=>new id),
+ # 5. way version,
+ # 6. hash of changed node versions (node=>version)
+ # 7. hash of deleted node versions (node=>version)
+
+ def putway(renumberednodes, usertoken, changeset_id, wayversion, originalway, pointlist, attributes, nodes, deletednodes)
+ amf_handle_error("'putway' #{originalway}", "way", originalway) do
+ # -- Initialise
+
+ user = getuser(usertoken)
+ return -1, "You are not logged in, so the way could not be saved." unless user
+ return -1, t("application.setup_user_auth.blocked") if user.blocks.active.exists?
+ return -1, "You must accept the contributor terms before you can edit." if REQUIRE_TERMS_AGREED && user.terms_agreed.nil?
+
+ return -2, "Server error - way is only #{pointlist.length} points long." if pointlist.length < 2
+
+ return -1, "One of the tags is invalid. Linux users may need to upgrade to Flash Player 10.1." unless tags_ok(attributes)
+ attributes = strip_non_xml_chars attributes
+
+ originalway = originalway.to_i
+ pointlist.collect!(&:to_i)
+
+ way = nil # this is returned, so scope it outside the transaction
+ nodeversions = {}
+ Way.transaction do
+ # -- Update each changed node
+
+ nodes.each do |a|
+ lon = a[0].to_f
+ lat = a[1].to_f
+ id = a[2].to_i
+ version = a[3].to_i
+
+ return -2, "Server error - node with id 0 found in way #{originalway}." if id.zero?
+ return -2, "Server error - node with latitude -90 found in way #{originalway}." if lat == 90
+
+ id = renumberednodes[id] if renumberednodes[id]
+
+ node = Node.new
+ node.changeset_id = changeset_id
+ node.lat = lat
+ node.lon = lon
+ node.tags = a[4]
+
+ # fixup node tags in a way as well
+ return -1, "One of the tags is invalid. Linux users may need to upgrade to Flash Player 10.1." unless tags_ok(node.tags)
+ node.tags = strip_non_xml_chars node.tags
+
+ 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[node.id] = node.version
+ else
+ # We're updating an existing node
+ previous = Node.find(id)
+ node.id = id
+ previous.update_from(node, user)
+ nodeversions[previous.id] = previous.version
+ end
+ end
+
+ # -- Save revised way
+
+ pointlist.collect! do |a|
+ renumberednodes[a] ? renumberednodes[a] : a
+ end
+ new_way = Way.new
+ new_way.tags = attributes
+ new_way.nds = pointlist
+ new_way.changeset_id = changeset_id
+ 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
+ else
+ way = Way.find(originalway)
+ if way.tags != attributes || way.nds != pointlist || !way.visible?
+ new_way.id = originalway
+ way.update_from(new_way, user)
+ end
+ end
+
+ # -- Delete unwanted nodes
+
+ deletednodes.each do |id, v|
+ node = Node.find(id.to_i)
+ new_node = Node.new
+ new_node.changeset_id = changeset_id
+ new_node.version = v.to_i
+ new_node.id = id.to_i
+ begin
+ node.delete_with_history!(new_node, user)
+ rescue OSM::APIPreconditionFailedError
+ # We don't do anything here as the node is being used elsewhere
+ # and we don't want to delete it
+ end
+ end
+ end
+
+ [0, "", originalway, way.id, renumberednodes, way.version, nodeversions, deletednodes]
+ end