117 lines
3.3 KiB
Ruby
117 lines
3.3 KiB
Ruby
|
module CartoDB
|
||
|
module Map
|
||
|
class Copier
|
||
|
def copy(map, layers=true)
|
||
|
new_map = new_map_from(map).save
|
||
|
if layers
|
||
|
copy_layers(map, new_map)
|
||
|
end
|
||
|
|
||
|
new_map
|
||
|
end
|
||
|
|
||
|
def new_map_from(map)
|
||
|
@new_map ||= map.dup
|
||
|
# Explicit association assignment to make user itself available, beyond its id, for validations
|
||
|
if map.user
|
||
|
@new_map.user ||= map.user
|
||
|
end
|
||
|
|
||
|
# Default is to copy all attributes from the canonical map. This overrides it
|
||
|
@new_map.scrollwheel = true
|
||
|
@new_map.options[:scrollwheel] = true if @new_map.options
|
||
|
|
||
|
@new_map
|
||
|
end
|
||
|
|
||
|
def copy_layers(origin_map, destination_map)
|
||
|
layer_copies_from(origin_map).map do |layer|
|
||
|
link(destination_map, layer)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def copy_base_layer(origin_map, destination_map)
|
||
|
origin_map.user_layers.map do |layer|
|
||
|
link(destination_map, layer.dup)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# TL;DR: adds data layers between existing base layers.
|
||
|
#
|
||
|
# Stacks data layer on top of the last data layer and/or
|
||
|
# the first base layer found, and keeps any existing "top"
|
||
|
# base layers on top.
|
||
|
def copy_data_layers(origin_map, destination_map, user)
|
||
|
last_data = destination_map.layers.reverse.find(&:data_layer?)
|
||
|
order = if last_data
|
||
|
last_data.order + 1
|
||
|
else
|
||
|
first_base = destination_map.layers.find(&:base_layer?)
|
||
|
first_base ? (first_base.order + 1) : 0
|
||
|
end
|
||
|
|
||
|
modified_layers = []
|
||
|
|
||
|
data_layer_copies_from(origin_map, user).map do |layer|
|
||
|
# Push layers on top if needed
|
||
|
if(destination_map.layers.map(&:order).include?(order))
|
||
|
destination_map.layers.select { |l| l.order >= order }.each do |layer|
|
||
|
layer.order += 1
|
||
|
# layer must be saved later
|
||
|
modified_layers << layer
|
||
|
end
|
||
|
end
|
||
|
|
||
|
layer.order = order
|
||
|
link(destination_map, layer)
|
||
|
# link saves
|
||
|
modified_layers -= [layer]
|
||
|
order += 1
|
||
|
end
|
||
|
|
||
|
# this avoid extra saving (including validation) overhead
|
||
|
modified_layers.uniq.map(&:save)
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
attr_reader :map
|
||
|
|
||
|
def data_layer_copies_from(map, user)
|
||
|
map.data_layers.map do |layer|
|
||
|
new_layer = layer.dup
|
||
|
new_layer.qualify_for_organization(map.user.username) if user.id != map.user.id
|
||
|
|
||
|
user.builder_enabled? ? reset_layer_styles(layer, new_layer) : new_layer
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def layer_copies_from(map)
|
||
|
map.layers.map(&:dup)
|
||
|
end
|
||
|
|
||
|
def link(map, layer)
|
||
|
layer.save
|
||
|
layer.add_map(map)
|
||
|
layer.save
|
||
|
end
|
||
|
|
||
|
def reset_layer_styles(old_layer, new_layer)
|
||
|
user_table = old_layer.user_tables.first
|
||
|
return new_layer unless user_table
|
||
|
|
||
|
geometry_type = user_table.service.geometry_types.first
|
||
|
return new_layer unless geometry_type
|
||
|
|
||
|
tile_style = ModelFactories::LayerFactory.builder_tile_style(geometry_type)
|
||
|
new_layer.options['tile_style'] = tile_style
|
||
|
|
||
|
style_properties = ModelFactories::LayerFactory.style_properties(geometry_type)
|
||
|
new_layer.options['style_properties'] = style_properties
|
||
|
|
||
|
new_layer
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|