discourse/app/controllers/directory_items_controller.rb
Vinoth Kannan 1ea19a4d51
FIX: unable to filter user directory when sorted by user field. ()
Since the "users" table is already added in the "includes" method it gives unexpected results while using it again in the "joins" method.
2022-02-16 07:57:35 +05:30

124 lines
4.6 KiB
Ruby

# frozen_string_literal: true
class DirectoryItemsController < ApplicationController
PAGE_SIZE = 50
def index
raise Discourse::InvalidAccess.new(:enable_user_directory) unless SiteSetting.enable_user_directory?
period = params.require(:period)
period_type = DirectoryItem.period_types[period.to_sym]
raise Discourse::InvalidAccess.new(:period_type) unless period_type
result = DirectoryItem.where(period_type: period_type).includes(user: :user_custom_fields)
if params[:group]
group = Group.find_by(name: params[:group])
raise Discourse::InvalidParameters.new(:group) if group.blank?
guardian.ensure_can_see!(group)
guardian.ensure_can_see_group_members!(group)
result = result.includes(user: :groups).where(users: { groups: { id: group.id } })
else
result = result.includes(user: :primary_group)
end
if params[:exclude_usernames]
result = result.references(:user).where.not(users: { username: params[:exclude_usernames].split(",") })
end
order = params[:order] || DirectoryColumn.automatic_column_names.first
dir = params[:asc] ? 'ASC' : 'DESC'
active_directory_column_names = DirectoryColumn.active_column_names
if active_directory_column_names.include?(order.to_sym)
result = result.order("directory_items.#{order} #{dir}, directory_items.id")
elsif params[:order] === 'username'
result = result.order("users.#{order} #{dir}, directory_items.id")
else
# Ordering by user field value
user_field = UserField.find_by(name: params[:order])
if user_field
result = result
.references(:user)
.joins("LEFT OUTER JOIN user_custom_fields ON user_custom_fields.user_id = users.id AND user_custom_fields.name = 'user_field_#{user_field.id}'")
.order("user_custom_fields.name = 'user_field_#{user_field.id}' ASC, user_custom_fields.value #{dir}")
end
end
if period_type == DirectoryItem.period_types[:all]
result = result.includes(:user_stat)
end
page = params[:page].to_i
user_ids = nil
if params[:name].present?
user_ids = UserSearch.new(params[:name], include_staged_users: true).search.pluck(:id)
if user_ids.present?
# Add the current user if we have at least one other match
if current_user && result.dup.where(user_id: user_ids).exists?
user_ids << current_user.id
end
result = result.where(user_id: user_ids)
else
result = result.where('false')
end
end
if params[:username]
user_id = User.where(username_lower: params[:username].to_s.downcase).pluck_first(:id)
if user_id
result = result.where(user_id: user_id)
else
result = result.where('false')
end
end
result_count = result.count
result = result.limit(PAGE_SIZE).offset(PAGE_SIZE * page).to_a
more_params = params.slice(:period, :order, :asc, :group, :user_field_ids).permit!
more_params[:page] = page + 1
load_more_uri = URI.parse(directory_items_path(more_params))
load_more_directory_items_json = "#{load_more_uri.path}.json?#{load_more_uri.query}"
# Put yourself at the top of the first page
if result.present? && current_user.present? && page == 0 && !params[:group].present?
position = result.index { |r| r.user_id == current_user.id }
# Don't show the record unless you're not in the top positions already
if (position || 10) >= 10
your_item = DirectoryItem.where(period_type: period_type, user_id: current_user.id).first
result.insert(0, your_item) if your_item
end
end
last_updated_at = DirectoryItem.last_updated_at(period_type)
serializer_opts = {}
if params[:user_field_ids]
serializer_opts[:user_custom_field_map] = {}
user_field_ids = params[:user_field_ids]&.split("|")&.map(&:to_i)
user_field_ids.each do |user_field_id|
serializer_opts[:user_custom_field_map]["#{User::USER_FIELD_PREFIX}#{user_field_id}"] = user_field_id
end
end
if params[:plugin_column_ids]
serializer_opts[:plugin_column_ids] = params[:plugin_column_ids]&.split("|")&.map(&:to_i)
end
serializer_opts[:attributes] = active_directory_column_names
serialized = serialize_data(result, DirectoryItemSerializer, serializer_opts)
render_json_dump(directory_items: serialized,
meta: {
last_updated_at: last_updated_at,
total_rows_directory_items: result_count,
load_more_directory_items: load_more_directory_items_json
}
)
end
end