cartodb/app/controllers/carto/api/visualization_searcher.rb
2020-06-15 10:58:47 +08:00

154 lines
5.8 KiB
Ruby

require_dependency 'carto/bounding_box_utils'
module Carto
module Api
module VisualizationSearcher
FILTER_SHARED_YES = 'yes'
FILTER_SHARED_NO = 'no'
FILTER_SHARED_ONLY = 'only'
# Creates a visualization query builder ready
# to search based on params hash (can be request params).
# It doesn't apply ordering or paging, just filtering.
def query_builder_with_filter_from_hash(params)
types, total_types = get_types_parameters
validate_parameters(types, params)
pattern = params[:q]
only_liked = params[:only_liked] == 'true'
only_shared = params[:only_shared] == 'true'
exclude_shared = params[:exclude_shared] == 'true'
exclude_raster = params[:exclude_raster] == 'true'
locked = params[:locked]
shared = compose_shared(params[:shared], only_shared, exclude_shared)
tags = params.fetch(:tags, '').split(',')
tags = nil if tags.empty?
bbox_parameter = params.fetch(:bbox,nil)
privacy = params.fetch(:privacy,nil)
only_with_display_name = params[:only_with_display_name] == 'true'
with_dependent_visualizations = params[:with_dependent_visualizations].to_i
only_published = params[:only_published] == 'true'
vqb = VisualizationQueryBuilder.new
.with_prefetch_user
.with_prefetch_table
.with_prefetch_permission
.with_prefetch_synchronization
.with_prefetch_external_source
.with_types(types)
.with_tags(tags)
if !bbox_parameter.blank?
vqb.with_bounding_box(Carto::BoundingBoxUtils.parse_bbox_parameters(bbox_parameter))
end
# FIXME Patch to exclude legacy visualization from data-library #5097
if only_with_display_name
vqb.with_display_name
end
vqb.with_published if only_published
if current_user
vqb.with_current_user_id(current_user.id)
vqb.with_liked_by_user_id(current_user.id) if only_liked
case shared
when FILTER_SHARED_YES
vqb.with_owned_by_or_shared_with_user_id(current_user.id)
when FILTER_SHARED_NO
vqb.with_user_id(current_user.id) if !only_liked
when FILTER_SHARED_ONLY
vqb.with_shared_with_user_id(current_user.id)
.with_user_id_not(current_user.id)
end
vqb.without_raster if exclude_raster
if locked == 'true'
vqb.with_locked(true)
elsif locked == 'false'
vqb.with_locked(false)
end
if types.include? Carto::Visualization::TYPE_REMOTE
vqb.without_synced_external_sources
vqb.without_imported_remote_visualizations
end
vqb.with_privacy(privacy) unless privacy.nil?
vqb.with_prefetch_dependent_visualizations if with_dependent_visualizations > 0
else
# TODO: ok, this looks like business logic, refactor
subdomain = CartoDB.extract_subdomain(request)
vqb.with_user_id(Carto::User.where(username: subdomain).first.id)
.with_privacy(Carto::Visualization::PRIVACY_PUBLIC)
end
if pattern.present?
vqb.with_partial_match(pattern)
end
vqb
end
def presenter_options_from_hash(params)
options = {}
options[:show_stats] = false if params[:show_stats].to_s == 'false'
options[:show_table] = false if params[:show_table].to_s == 'false'
options[:show_permission] = false if params[:show_permission].to_s == 'false'
options[:show_uses_builder_features] = false if params[:show_uses_builder_features].to_s == 'false'
options[:show_synchronization] = false if params[:show_synchronization].to_s == 'false'
options[:show_table_size_and_row_count] = false if params[:show_table_size_and_row_count].to_s == 'false'
options[:with_dependent_visualizations] = params[:with_dependent_visualizations].to_i
options
end
private
def get_types_parameters
# INFO: this fits types and type into types, so only types is used for search.
# types defaults to type if empty.
# types defaults to derived if type is also empty.
# total_types are the types used for total counts.
types = params.fetch(:types, "").split(',')
type = params[:type].present? ? params[:type] : (types.empty? ? nil : types[0])
# TODO: add this assumption to a test or remove it (this is coupled to the UI)
total_types = [(type == Carto::Visualization::TYPE_REMOTE ? Carto::Visualization::TYPE_CANONICAL : type)].compact
types = [type].compact if types.empty?
types = [Carto::Visualization::TYPE_DERIVED] if types.empty?
return types, total_types
end
def compose_shared(shared, only_shared, exclude_shared)
valid_shared = shared if [FILTER_SHARED_ONLY, FILTER_SHARED_NO, FILTER_SHARED_YES].include?(shared)
return valid_shared if valid_shared
if only_shared
FILTER_SHARED_ONLY
elsif exclude_shared
FILTER_SHARED_NO
elsif exclude_shared == false
FILTER_SHARED_YES
else
# INFO: exclude_shared == nil && !only_shared
nil
end
end
def validate_parameters(types, parameters)
if (!params.fetch(:bbox, nil).nil? && (types.length > 1 || !types.include?(Carto::Visualization::TYPE_CANONICAL)))
raise CartoDB::BoundingBoxError.new('Filter by bbox is only supported for type table')
end
end
end
end
end