154 lines
5.8 KiB
Ruby
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
|