Bonfire.Social.FeedLoader (Bonfire v1.0.0-social-rc.3.22)
View SourceDetermines 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 lists of objects
Replaces parameters in the filter value with the actual values from opts.
Functions
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 (seeFeedFiltersfor 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{}} = feed(:explore)
iex> %{edges: _, page_info: %Paginator.PageInfo{}} = feed(%{feed_name: :explore})
> 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,
:quote_tags,
: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()
[:posts_with_thread, :with_post_content, :with_subject]
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: [:tags]}, current_user: %{id: "alice"}, tags: "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()
[:quote_tags, :with_creator, :with_media, :with_object_more, :with_object_peered, :with_replied, :with_reply_to, :with_subject]
iex> filters = %{subjects: ["alice"]}
iex> preloads_from_filters(filters) |> Enum.sort()
[:quote_tags, :with_creator, :with_media, :with_object_more, :with_object_peered, :with_replied, :with_reply_to]
iex> filters = %{feed_name: "unknown"}
iex> preloads_from_filters(filters) |> Enum.sort()
[:quote_tags, :with_creator, :with_media, :with_object_more, :with_object_peered, :with_replied, :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}} = preset_feed_filters(:local, [])
# 1: Retrieve a preset feed without parameters
iex> {:ok, %{feed_name: :local}} =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(:likes, current_user: %{id: "alice"})
# 5: Feed with `current_user_required` should check for current user
iex> {:ok, %{activity_types: [:flag]}} = preset_feed_filters(:my_flags, current_user: %{id: "alice"})
# 6: Feed with `current_user_required` and no current user
iex> preset_feed_filters(:my_flags, [])
{:error, :unauthorized}
# ** (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 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"}
# (Currently disabled:) 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