Initial commit
This commit is contained in:
@@ -0,0 +1,270 @@
|
||||
require 'active_record'
|
||||
|
||||
require_relative '../../models/carto/shared_entity'
|
||||
require_dependency 'carto/bounding_box_utils'
|
||||
require_dependency 'carto/uuidhelper'
|
||||
|
||||
# TODO: consider moving some of this to model scopes if convenient
|
||||
class Carto::VisualizationQueryBuilder
|
||||
include Carto::UUIDHelper
|
||||
|
||||
def self.user_public_tables(user)
|
||||
user_public(user).with_type(Carto::Visualization::TYPE_CANONICAL)
|
||||
end
|
||||
|
||||
def self.user_public_visualizations(user)
|
||||
user_public_privacy_visualizations(user).with_published
|
||||
end
|
||||
|
||||
def self.user_public_privacy_visualizations(user)
|
||||
user_public(user).with_type(Carto::Visualization::TYPE_DERIVED)
|
||||
end
|
||||
|
||||
def self.user_link_privacy_visualizations(user)
|
||||
new.with_user_id(user.id)
|
||||
.with_type(Carto::Visualization::TYPE_DERIVED)
|
||||
.with_privacy(Carto::Visualization::PRIVACY_LINK)
|
||||
end
|
||||
|
||||
def self.user_password_privacy_visualizations(user)
|
||||
new.with_user_id(user.id)
|
||||
.with_type(Carto::Visualization::TYPE_DERIVED)
|
||||
.with_privacy(Carto::Visualization::PRIVACY_PROTECTED)
|
||||
end
|
||||
|
||||
def self.user_all_visualizations(user)
|
||||
new.with_user_id(user ? user.id : nil).with_type(Carto::Visualization::TYPE_DERIVED)
|
||||
end
|
||||
|
||||
def self.user_public(user)
|
||||
new.with_user_id(user ? user.id : nil).with_privacy(Carto::Visualization::PRIVACY_PUBLIC)
|
||||
end
|
||||
|
||||
def initialize
|
||||
@include_associations = []
|
||||
@eager_load_associations = []
|
||||
@filtering_params = {}
|
||||
end
|
||||
|
||||
def with_id_or_name(id_or_name)
|
||||
raise 'VisualizationQueryBuilder: id or name supplied is nil' if id_or_name.nil?
|
||||
|
||||
if is_uuid?(id_or_name)
|
||||
with_id(id_or_name)
|
||||
else
|
||||
with_name(id_or_name)
|
||||
end
|
||||
end
|
||||
|
||||
def with_id(id)
|
||||
@filtering_params[:id] = id
|
||||
self
|
||||
end
|
||||
|
||||
def with_excluded_ids(ids)
|
||||
@filtering_params[:excluded_ids] = ids
|
||||
self
|
||||
end
|
||||
|
||||
def without_synced_external_sources
|
||||
@filtering_params[:exclude_synced_external_sources] = true
|
||||
self
|
||||
end
|
||||
|
||||
def without_imported_remote_visualizations
|
||||
@filtering_params[:exclude_imported_remote_visualizations] = true
|
||||
self
|
||||
end
|
||||
|
||||
def without_raster
|
||||
@filtering_params[:excluded_kinds] ||= []
|
||||
@filtering_params[:excluded_kinds] << Carto::Visualization::KIND_RASTER
|
||||
self
|
||||
end
|
||||
|
||||
def with_name(name)
|
||||
@filtering_params[:name] = name
|
||||
self
|
||||
end
|
||||
|
||||
def with_user_id(user_id)
|
||||
@filtering_params[:user_id] = user_id
|
||||
self
|
||||
end
|
||||
|
||||
def with_user_id_not(user_id)
|
||||
@filtering_params[:user_id_not] = user_id
|
||||
self
|
||||
end
|
||||
|
||||
def with_privacy(privacy)
|
||||
@filtering_params[:privacy] = privacy
|
||||
self
|
||||
end
|
||||
|
||||
def with_liked_by_user_id(user_id)
|
||||
@filtering_params[:liked_by_user_id] = user_id
|
||||
self
|
||||
end
|
||||
|
||||
def with_shared_with_user_id(user_id)
|
||||
@filtering_params[:shared_with_user_id] = user_id
|
||||
self
|
||||
end
|
||||
|
||||
def with_owned_by_or_shared_with_user_id(user_id)
|
||||
@filtering_params[:owned_by_or_shared_with_user_id] = user_id
|
||||
self
|
||||
end
|
||||
|
||||
def with_prefetch_user(force_join = false)
|
||||
if force_join
|
||||
with_eager_load_of(:user)
|
||||
else
|
||||
with_include_of(:user)
|
||||
end
|
||||
end
|
||||
|
||||
def with_prefetch_table
|
||||
nested_association = { map: :user_table }
|
||||
with_eager_load_of(nested_association)
|
||||
end
|
||||
|
||||
def with_prefetch_dependent_visualizations
|
||||
inner_visualization = { visualization: { map: { layers: :layers_user_tables }, permission: :owner } }
|
||||
nested_association = { map: { user_table: { layers: { maps: inner_visualization } } } }
|
||||
with_eager_load_of(nested_association)
|
||||
end
|
||||
|
||||
def with_prefetch_permission
|
||||
nested_association = { permission: :owner }
|
||||
with_eager_load_of(nested_association)
|
||||
end
|
||||
|
||||
def with_prefetch_external_source
|
||||
with_eager_load_of(:external_source)
|
||||
end
|
||||
|
||||
def with_prefetch_synchronization
|
||||
with_eager_load_of(:synchronization)
|
||||
self
|
||||
end
|
||||
|
||||
def with_type(type)
|
||||
@filtering_params[:type] = type
|
||||
self
|
||||
end
|
||||
|
||||
alias with_types with_type
|
||||
|
||||
def with_locked(locked)
|
||||
@filtering_params[:locked] = locked
|
||||
self
|
||||
end
|
||||
|
||||
def with_current_user_id(user_id)
|
||||
@current_user_id = user_id
|
||||
end
|
||||
|
||||
def with_order(order, direction = 'asc')
|
||||
@order = order.to_s
|
||||
@direction = direction.to_s
|
||||
self
|
||||
end
|
||||
|
||||
def with_partial_match(tainted_search_pattern)
|
||||
@filtering_params[:tainted_search_pattern] = tainted_search_pattern
|
||||
self
|
||||
end
|
||||
|
||||
def with_tags(tags)
|
||||
@filtering_params[:tags] = tags
|
||||
self
|
||||
end
|
||||
|
||||
def with_bounding_box(bounding_box)
|
||||
@filtering_params[:bounding_box] = bounding_box
|
||||
self
|
||||
end
|
||||
|
||||
def with_display_name
|
||||
@filtering_params[:only_with_display_name] = true
|
||||
self
|
||||
end
|
||||
|
||||
def with_organization_id(organization_id)
|
||||
@filtering_params[:organization_id] = organization_id
|
||||
self
|
||||
end
|
||||
|
||||
# Published: see `Carto::Visualization#published?`
|
||||
def with_published
|
||||
@filtering_params[:only_published] = true
|
||||
self
|
||||
end
|
||||
|
||||
def with_version(version)
|
||||
@filtering_params[:version] = version
|
||||
self
|
||||
end
|
||||
|
||||
def build
|
||||
query = Carto::Visualization.all
|
||||
query = Carto::VisualizationQueryFilterer.new(query).filter(@filtering_params)
|
||||
query = with_associations(query)
|
||||
order_query(query)
|
||||
end
|
||||
|
||||
def build_paged(page = 1, per_page = 20)
|
||||
build.offset((page.to_i - 1) * per_page.to_i).limit(per_page.to_i)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def order_query(query)
|
||||
# Search has its own ordering criteria
|
||||
return query if @tainted_search_pattern
|
||||
|
||||
orderer = Carto::VisualizationQueryOrderer.new(query)
|
||||
orderer.order(@order, @direction)
|
||||
end
|
||||
|
||||
def with_include_of(association)
|
||||
@include_associations << association
|
||||
self
|
||||
end
|
||||
|
||||
def with_eager_load_of(association)
|
||||
@eager_load_associations << association
|
||||
self
|
||||
end
|
||||
|
||||
def with_associations(query)
|
||||
query = query.includes(@include_associations) unless @include_associations.empty?
|
||||
query = query.eager_load(@eager_load_associations) unless @eager_load_associations.empty?
|
||||
# We have to include favorites if we're not filtering by them
|
||||
# Why? Both of them include a join with the likes table: favorited uses
|
||||
# a left-join one and the filter will use an inner-join.
|
||||
# So what is the problem? It'll fail because is not possible to include two
|
||||
# joins for the same table
|
||||
# And what is the difference?
|
||||
# - Filtering leaves only the favorited/liked visualizations by the user
|
||||
# - With favorited we add the like/favorite data to the visualization information
|
||||
query = with_favorited(query) unless @filtering_params[:liked_by_user_id]
|
||||
with_dependent_visualization_count(query)
|
||||
end
|
||||
|
||||
def with_favorited(query)
|
||||
return query unless @order && @order.include?("favorited")
|
||||
raise 'Cannot order by favorited if no user is provided' unless @current_user_id
|
||||
|
||||
Carto::VisualizationQueryIncluder.new(query).include_favorited(@current_user_id)
|
||||
end
|
||||
|
||||
def with_dependent_visualization_count(query)
|
||||
return query unless @order && @order.include?("dependent_visualizations")
|
||||
|
||||
Carto::VisualizationQueryIncluder.new(query).include_dependent_visualization_count(@filtering_params)
|
||||
end
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user