View Source Bonfire.Social.FeedLoader (Bonfire v0.9.11-social-beta.6)
Determines the appropriate filters, joins, and/or preloads for feed queries based.
Entrypoint for Bonfire.Social.Feeds
and Bonfire.Social.FeedActivities
, and Bonfire.Social.Activities
.
Summary
Functions
Returns the count of items in a feed based on given filters and options.
Returns the count of distinct subjects in a feed based on given filters and options.
Gets a feed based on filters and options.
Gets feed ids and options for the given feed or list of feeds.
Returns paginated results for the given query.
Returns a page of feed activities (reverse chronological) + pagination metadata
Maps high-level preload keys to their corresponding detailed preload lists.
Match feed filters against rule criteria.
Gets a user's home feed, a combination of all feeds the user is subscribed to.
Parameterizes the filters by replacing parameterized values with values from opts
.
Computes the list of preloads to apply based on the provided filters. Returns a list of preload atoms.
Converts socket, assigns, or options to feed options.
Gets an aliased feed's filters by name, with optional parameters.
Return a boundarised query for a feed
add assocs needed in timelines/feeds
add assocs needed in lists of objects
Replaces parameters in the filter value with the actual values from opts
.
Functions
contextual_preloads_from_filters(feed_filters, context, context_rules \\ preloads_by_context_rules())
Returns the count of items in a feed based on given filters and options.
Examples
> count(filters, current_user: me)
10
Returns the count of distinct subjects in a feed based on given filters and options.
Examples
> count_subjects(filters, opts)
3
Gets a feed based on filters and options.
Parameters
name_or_filters
- A map of filter parameters (seeFeedFilters
for the list of supported filters) or a feed name atom/string if no other filters are neededopts
- Options that aren't filter-related
Examples
iex> %{edges: _, page_info: %Paginator.PageInfo{}} = Bonfire.Social.FeedActivities.feed(:explore)
iex> %{edges: _, page_info: %Paginator.PageInfo{}} = Bonfire.Social.FeedActivities.feed(%{feed_name: :explore})
> Bonfire.Social.FeedActivities.feed("feed123", [])
%{edges: [%{activity: %{}}], page_info: %Paginator.PageInfo{}}
Gets feed ids and options for the given feed or list of feeds.
TODO: this should be replaced by feed presets
Examples
> feed_ids_and_opts(feed_name, opts)
{feed_ids, opts}
> feed_ids_and_opts({feed_name, feed_id}, opts)
> feed_ids_and_opts(:my, [current_user: me])
{["feed_id1", "feed_id2"], [exclude_activity_types: [:flag, :boost, :follow]]}
> feed_ids_and_opts({:notifications, "feed_id3"}, [current_user: me])
{"feed_id3", [include_flags: true, exclude_activity_types: false, show_objects_only_once: false, preload: [:notifications]]}
Returns paginated results for the given query.
Examples
> feed_many_paginated(query, opts)
%{edges: edges, page_info: page_info}
Returns a page of feed activities (reverse chronological) + pagination metadata
TODO: consolidate with feed/2
?
Examples
iex> %{edges: _, page_info: %{}} = feed_paginated([], [])
iex> query = Ecto.Query.from(f in Bonfire.Data.Social.FeedPublish)
iex> %{edges: _, page_info: %{}} = feed_paginated([], base_query: query)
Maps high-level preload keys to their corresponding detailed preload lists.
Examples
# Single preload key
iex> map_activity_preloads([:feed]) |> Enum.sort()
[
:with_creator,
:with_media,
:with_object_more,
:with_replied,
:with_subject
]
# Multiple preload keys
iex> map_activity_preloads([:feed, :notifications]) |> Enum.sort()
[:notifications, :with_creator, :with_media, :with_object_more, :with_replied, :with_subject]
# With :all key it includes all defined preloads
iex> map_activity_preloads([:all]) |> Enum.sort()
[
:maybe_with_labelled,
:tags,
:with_creator,
:with_media,
:with_object_more,
:with_parent,
:with_post_content,
:with_replied,
:with_reply_to,
:with_seen,
:with_subject,
:with_thread_name,
:with_verb
]
# With unknown key
iex> map_activity_preloads([:unknown_key])
[:unknown_key]
# Empty list returns empty list
iex> map_activity_preloads([])
[]
# Removes duplicates when preload lists overlap
iex> map_activity_preloads([:posts, :posts_with_thread]) |> Enum.sort()
[
:with_post_content,
:with_replied,
:with_subject,
:with_thread_name
]
Match feed filters against rule criteria.
Examples
iex> matches_filter?(%{types: "*"}, %{types: "post"})
true
iex> matches_filter?(%{types: ["post", "comment"]}, %{types: ["comment", "reaction"]})
true
iex> matches_filter?(%{types: "post"}, %{types: ["comment", "post"]})
true
iex> matches_filter?(%{types: :post}, %{types: ["comment", "post"]})
true
iex> matches_filter?(%{types: "post"}, %{types: [:comment, :post]})
true
iex> matches_filter?(%{types: ["post"]}, %{types: "post"})
true
iex> matches_filter?(%{types: "post"}, %{types: "comment"})
false
iex> matches_filter?(%{types: :post}, %{types: "post"})
true
Gets a user's home feed, a combination of all feeds the user is subscribed to.
TODO: should just be an alias to feed(:my, opts)
Examples
> Bonfire.Social.FeedActivities.my_feed([current_user: %{id: "user123"}])
%{edges: [%{activity: %{}}], page_info: %{}}
> Bonfire.Social.FeedActivities.my_feed([current_user: %{id: "user123"}], ["feed_id1", "feed_id2"])
%{edges: [%{activity: %{}}], page_info: %{}}
Parameterizes the filters by replacing parameterized values with values from opts
.
Examples
# 1: Parameterizing a simple filter
iex> parameterize_filters(%{}, %{subjects: [:me]}, current_user: %{id: "alice"})
%{subjects: [%{id: "alice"}]}
# 2: Parameterizing multiple filters
iex> parameterize_filters(%{}, %{subjects: [:me], tags: [:hashtag]}, current_user: %{id: "alice"}, hashtag: "elixir")
%{subjects: [%{id: "alice"}], tags: ["elixir"]}
# 3: Parameterizing with undefined options
iex> parameterize_filters(%{}, %{subjects: :me}, current_user: nil)
%{subjects: nil}
# 4: Handling filters that don't require parameterization
iex> parameterize_filters(%{activity_types: ["like"]}, %{}, current_user: "bob")
%{activity_types: ["like"]}
Computes the list of preloads to apply based on the provided filters. Returns a list of preload atoms.
Uses rules defined in configuration rather than code.
Multiple rules can match and their preloads will be merged, with exclusions applied last.
Examples
iex> filters = %{feed_name: "remote"}
iex> preloads_from_filters(filters) |> Enum.sort()
[:with_creator, :with_media, :with_object_more, :with_peered, :with_reply_to, :with_subject]
iex> filters = %{feed_name: :remote}
iex> preloads_from_filters(filters) |> Enum.sort()
[:with_creator, :with_media, :with_object_more, :with_peered, :with_reply_to, :with_subject]
iex> filters = %{feed_name: ["remote"]}
iex> preloads_from_filters(filters) |> Enum.sort()
[:with_creator, :with_media, :with_object_more, :with_peered, :with_reply_to, :with_subject]
iex> filters = %{feed_name: [:remote]}
iex> preloads_from_filters(filters) |> Enum.sort()
[:with_creator, :with_media, :with_object_more, :with_peered, :with_reply_to, :with_subject]
iex> filters = %{subjects: ["alice"]}
iex> preloads_from_filters(filters) |> Enum.sort()
[:with_creator, :with_media, :with_object_more, :with_reply_to]
iex> filters = %{feed_name: "unknown"}
iex> preloads_from_filters(filters) |> Enum.sort()
[
:with_creator,
:with_media,
:with_object_more,
:with_peered,
:with_reply_to,
:with_subject
]
Converts socket, assigns, or options to feed options.
Examples
> assigns = %{exclude_activity_types: [:flag, :boost]}
> to_feed_options(filters, assigns)
[exclude_activity_types: [:flag, :boost, :follow]]
Gets an aliased feed's filters by name, with optional parameters.
Examples
# 1: Retrieve a preset feed without parameters
iex> {:ok, %{feed_name: :local, exclude_activity_types: [:like]}} = preset_feed_filters(:local, [])
# 1: Retrieve a preset feed without parameters
iex> {:ok, %{feed_name: :local, exclude_activity_types: [:like]}} =preset_feed_filters(:local, [])
# 2: Retrieve a preset feed with parameters
iex> {:ok, %{subjects: "alice"}} = preset_feed_filters(:user_activities, [by: "alice"])
# 3: Feed not found (error case)
iex> preset_feed_filters("unknown_feed", [])
{:error, :not_found}
# 4: Preset feed with parameterized filters
iex> {:ok, %{activity_types: :like, subjects: %{id: "alice"}}} = preset_feed_filters(:liked_by_me, current_user: %{id: "alice"})
# 5: Feed with `current_user_required` should check for current user
iex> {:ok, %{feed_name: :messages}} = preset_feed_filters(:messages, current_user: %{id: "alice"})
# 6: Feed with `current_user_required` and no current user
iex> preset_feed_filters(:messages, [])
** (Bonfire.Fail.Auth) You need to log in first.
# 7: Custom feed with additional parameters
iex> {:ok, %{activity_types: :follow, objects: "alice"}} = preset_feed_filters(:user_followers, [by: "alice"])
Return a boundarised query for a feed
add assocs needed in timelines/feeds
add assocs needed in lists of objects
Replaces parameters in the filter value with the actual values from opts
.
Examples
# Replacing a `me` parameter with the current user
iex> replace_parameters(:me, %{}, current_user: %{id: "alice"})
%{id: "alice"}
# Replacing a `:current_user` parameter with the current user only if available
iex> replace_parameters(:current_user, %{}, current_user: nil)
nil
# Replacing a `by` parameter with the a value from the filters
iex> replace_parameters(:by, %{by: %{id: "alice"}}, [])
%{id: "alice"}
# Replacing a `by` parameter with the a value from the opts
iex> replace_parameters(:by, %{}, by: %{id: "alice"})
%{id: "alice"}
# Replacing a `:by` parameter with the current user as a fallback
iex> replace_parameters(:by, %{}, current_user: %{id: "alice"})
%{id: "alice"}
# Failing with `:current_user_required` parameter if we have no current user
iex> replace_parameters(:current_user_required, %{}, current_user: nil)
** (Bonfire.Fail.Auth) You need to log in first.
# Handling a parameter that is in the opts
iex> replace_parameters(:type, %{}, type: "post")
"post"
# Handling a parameter that is in the filters
iex> replace_parameters(:type, %{type: "post"}, [])
"post"
# Handling a parameter that is in the filters with string key
iex> replace_parameters(:type, %{"type"=> "post"}, [])
"post"
# # Handling a string key parameter that is in the filters
# iex> replace_parameters("type", %{type: "post"}, [])
# "post"
# # Handling a string key parameter that is in the opts - FIXME
# iex> replace_parameters("type", %{}, type: "post")
# "post"
# Handling a parameter that is not in the opts
iex> replace_parameters(:unknown, %{}, current_user: "bob")
:unknown