Class: DirectoryItemsController

Inherits:
ApplicationController show all
Defined in:
app/controllers/directory_items_controller.rb

Constant Summary collapse

PAGE_SIZE =
50

Constants inherited from ApplicationController

ApplicationController::LEGACY_NO_THEMES, ApplicationController::LEGACY_NO_UNOFFICIAL_PLUGINS, ApplicationController::NO_PLUGINS, ApplicationController::NO_THEMES, ApplicationController::NO_UNOFFICIAL_PLUGINS, ApplicationController::SAFE_MODE

Constants included from CanonicalURL::ControllerExtensions

CanonicalURL::ControllerExtensions::ALLOWED_CANONICAL_PARAMS

Instance Attribute Summary

Attributes inherited from ApplicationController

#theme_id

Instance Method Summary collapse

Methods inherited from ApplicationController

#application_layout, #can_cache_content?, #clear_notifications, #conditionally_allow_site_embedding, #current_homepage, #discourse_expires_in, #dont_cache_page, #ember_cli_required?, #fetch_user_from_params, #guardian, #handle_permalink, #handle_theme, #handle_unverified_request, #has_escaped_fragment?, #immutable_for, #no_cookies, #perform_refresh_session, #post_ids_including_replies, #preload_json, #rate_limit_second_factor!, #redirect_with_client_support, #render_json_dump, #render_serialized, requires_plugin, #rescue_discourse_actions, #resolve_safe_mode, #secure_session, #serialize_data, #set_current_user_for_logs, #set_layout, #set_mobile_view, #set_mp_snapshot_fields, #show_browser_update?, #store_preloaded, #use_crawler_layout?, #with_resolved_locale

Methods included from VaryHeader

#ensure_vary_header

Methods included from ReadOnlyMixin

#add_readonly_header, #allowed_in_staff_writes_only_mode?, #block_if_readonly_mode, #check_readonly_mode, included, #staff_writes_only_mode?

Methods included from Hijack

#hijack

Methods included from GlobalPath

#cdn_path, #cdn_relative_path, #full_cdn_url, #path, #upload_cdn_path

Methods included from JsonError

#create_errors_json

Methods included from CanonicalURL::ControllerExtensions

#canonical_url, #default_canonical, included

Methods included from CurrentUser

#clear_current_user, #current_user, has_auth_cookie?, #is_api?, #is_user_api?, #log_off_user, #log_on_user, lookup_from_env, #refresh_session

Instance Method Details

#indexObject



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'app/controllers/directory_items_controller.rb', line 7

def index
  unless SiteSetting.enable_user_directory?
    raise Discourse::InvalidAccess.new(:enable_user_directory)
  end

  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

  result = apply_exclude_groups_filter(result)

  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

  result = result.includes(:user_stat) if period_type == DirectoryItem.period_types[:all]
  page = fetch_int_from_params(:page, default: 0)

  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
      user_ids << current_user.id if current_user && result.dup.where(user_id: user_ids).exists?
      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).pick(:id)
    if user_id
      result = result.where(user_id: user_id)
    else
      result = result.where("false")
    end
  end

  limit = fetch_limit_from_params(default: PAGE_SIZE, max: PAGE_SIZE)

  result_count = result.count
  result = result.limit(limit).offset(limit * 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
      unless @users_in_exclude_groups&.include?(current_user.id)
        your_item = DirectoryItem.where(period_type: period_type, user_id: current_user.id).first
        result.insert(0, your_item) if your_item
      end
    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