diff --git a/lib/philomena/posts/query.ex b/lib/philomena/posts/query.ex index c180263f..3672f213 100644 --- a/lib/philomena/posts/query.ex +++ b/lib/philomena/posts/query.ex @@ -93,6 +93,7 @@ defmodule Philomena.Posts.Query do bool_fields: mod_bool_fields, custom_fields: user_custom, transforms: user_transforms, + aliases: mod_aliases, default_field: default_field ) diff --git a/lib/philomena_web/controllers/activity_controller.ex b/lib/philomena_web/controllers/activity_controller.ex index f2c8897b..3248720b 100644 --- a/lib/philomena_web/controllers/activity_controller.ex +++ b/lib/philomena_web/controllers/activity_controller.ex @@ -1,51 +1,28 @@ defmodule PhilomenaWeb.ActivityController do use PhilomenaWeb, :controller + alias PhilomenaWeb.ImageLoader alias Philomena.{Images.Image, ImageFeatures.ImageFeature, Comments.Comment, Channels.Channel, Topics.Topic, Forums.Forum} alias Philomena.Interactions - alias Philomena.Images alias Philomena.Repo import Ecto.Query def index(conn, _params) do user = conn.assigns.current_user - filter = conn.assigns.compiled_filter - {:ok, image_query} = Images.Query.compile(user, "created_at.lte:3 minutes ago") - images = - Image.search_records( - %{ - query: %{ - bool: %{ - must: image_query, - must_not: [ - filter, - %{term: %{hidden_from_users: true}} - ], - } - }, - sort: %{created_at: :desc} - }, - %{conn.assigns.image_pagination | page_number: 1}, - Image |> preload([:tags]) + {:ok, images} = + ImageLoader.search_string( + conn, + "created_at.lte:3 minutes ago", + pagination: %{conn.assigns.image_pagination | page_number: 1} ) top_scoring = - Image.search_records( - %{ - query: %{ - bool: %{ - must: %{range: %{first_seen_at: %{gt: "now-3d"}}}, - must_not: [ - filter, - %{term: %{hidden_from_users: true}} - ] - } - }, - sort: [%{score: :desc}, %{first_seen_at: :desc}] - }, - %{page_number: :rand.uniform(6), page_size: 4}, - Image |> preload([:tags]) + ImageLoader.query( + conn, + %{range: %{first_seen_at: %{gt: "now-3d"}}}, + sorts: [%{score: :desc}, %{first_seen_at: :desc}], + pagination: %{page_number: :rand.uniform(6), page_size: 4} ) comments = @@ -69,24 +46,14 @@ defmodule PhilomenaWeb.ActivityController do ) watched = if !!user do - {:ok, watched_query} = Images.Query.compile(user, "my:watched") + {:ok, watched_images} = + ImageLoader.search_string( + conn, + "my:watched", + pagination: %{conn.assigns.image_pagination | page_number: 1} + ) - Image.search_records( - %{ - query: %{ - bool: %{ - must: watched_query, - must_not: [ - filter, - %{term: %{hidden_from_users: true}} - ] - } - }, - sort: %{created_at: :desc} - }, - %{conn.assigns.image_pagination | page_number: 1}, - Image |> preload([:tags]) - ) + watched_images end featured_image = diff --git a/lib/philomena_web/controllers/image_controller.ex b/lib/philomena_web/controllers/image_controller.ex index c5668697..60565467 100644 --- a/lib/philomena_web/controllers/image_controller.ex +++ b/lib/philomena_web/controllers/image_controller.ex @@ -1,6 +1,7 @@ defmodule PhilomenaWeb.ImageController do use PhilomenaWeb, :controller + alias PhilomenaWeb.ImageLoader alias Philomena.{Images, Images.Image, Comments.Comment, Textile.Renderer} alias Philomena.Servers.ImageProcessor alias Philomena.Interactions @@ -18,17 +19,7 @@ defmodule PhilomenaWeb.ImageController do plug PhilomenaWeb.AdvertPlug when action in [:show] def index(conn, _params) do - query = conn.assigns.compiled_filter - - images = - Image.search_records( - %{ - query: %{bool: %{must_not: [query, %{term: %{hidden_from_users: true}}]}}, - sort: %{created_at: :desc} - }, - conn.assigns.image_pagination, - Image |> preload([:tags, :user]) - ) + images = ImageLoader.query(conn, %{match_all: %{}}) interactions = Interactions.user_interactions(images, conn.assigns.current_user) diff --git a/lib/philomena_web/controllers/profile_controller.ex b/lib/philomena_web/controllers/profile_controller.ex index 4fb52f0c..03511a98 100644 --- a/lib/philomena_web/controllers/profile_controller.ex +++ b/lib/philomena_web/controllers/profile_controller.ex @@ -1,53 +1,38 @@ defmodule PhilomenaWeb.ProfileController do use PhilomenaWeb, :controller - alias Philomena.{Images, Images.Image, Users.User} - import Ecto.Query + alias PhilomenaWeb.ImageLoader + alias Philomena.Users.User + alias Philomena.Interactions plug :load_and_authorize_resource, model: User, only: :show, id_field: "slug", preload: [awards: :badge, public_links: :tag] def show(conn, _params) do current_user = conn.assigns.current_user - filter = conn.assigns.compiled_filter user = conn.assigns.user - {:ok, upload_query} = Images.Query.compile(current_user, "uploader_id:#{user.id}") - {:ok, fave_query} = Images.Query.compile(current_user, "faved_by_id:#{user.id}") - - recent_uploads = - Image.search_records( - %{ - query: %{ - bool: %{ - must_not: filter, - must: upload_query - } - }, - sort: %{created_at: :desc} - }, - %{page_number: 1, page_size: 6}, - Image |> preload([:tags]) + {:ok, recent_uploads} = + ImageLoader.search_string( + conn, + "uploader_id:#{user.id}", + pagination: %{page_number: 1, page_size: 6} ) - recent_faves = - Image.search_records( - %{ - query: %{ - bool: %{ - must_not: filter, - must: fave_query - } - }, - sort: %{created_at: :desc} - }, - %{page_number: 1, page_size: 6}, - Image |> preload([:tags]) + {:ok, recent_faves} = + ImageLoader.search_string( + conn, + "faved_by_id:#{user.id}", + pagination: %{page_number: 1, page_size: 6} ) + interactions = + Interactions.user_interactions([recent_uploads, recent_faves], current_user) + render( conn, "show.html", user: user, + interactions: interactions, recent_uploads: recent_uploads, recent_faves: recent_faves, layout_class: "layout--wide" diff --git a/lib/philomena_web/controllers/search_controller.ex b/lib/philomena_web/controllers/search_controller.ex index 71c42d4a..c582f2b8 100644 --- a/lib/philomena_web/controllers/search_controller.ex +++ b/lib/philomena_web/controllers/search_controller.ex @@ -1,42 +1,24 @@ defmodule PhilomenaWeb.SearchController do use PhilomenaWeb, :controller - alias Philomena.Images.{Image, Query} + alias PhilomenaWeb.ImageLoader alias Philomena.ImageSorter alias Philomena.Interactions - import Ecto.Query - def index(conn, params) do - filter = conn.assigns.compiled_filter user = conn.assigns.current_user sort = ImageSorter.parse_sort(params) - with {:ok, query} <- Query.compile(user, params["q"]) do - images = - Image.search_records( - %{ - query: %{bool: %{must: [query | sort.queries], must_not: [filter, %{term: %{hidden_from_users: true}}]}}, - sort: sort.sorts - }, - conn.assigns.image_pagination, - Image |> preload(:tags) - ) + case ImageLoader.search_string(conn, params["q"], sorts: sort.sorts, queries: sort.queries) do + {:ok, images} -> + interactions = + Interactions.user_interactions(images, user) - interactions = - Interactions.user_interactions(images, user) - - conn - |> render("index.html", images: images, search_query: params["q"], interactions: interactions, layout_class: "layout--wide") - else - {:error, msg} -> conn - |> render("index.html", - images: [], - error: msg, - search_query: params["q"] - ) + |> render("index.html", images: images, search_query: params["q"], interactions: interactions, layout_class: "layout--wide") + + {:error, msg} -> + render(conn, "index.html", images: [], error: msg, search_query: params["q"]) end end - end diff --git a/lib/philomena_web/controllers/tag_controller.ex b/lib/philomena_web/controllers/tag_controller.ex index 154a0cfd..db5765bb 100644 --- a/lib/philomena_web/controllers/tag_controller.ex +++ b/lib/philomena_web/controllers/tag_controller.ex @@ -1,7 +1,8 @@ defmodule PhilomenaWeb.TagController do use PhilomenaWeb, :controller - alias Philomena.{Images.Image, Tags, Tags.Tag} + alias PhilomenaWeb.ImageLoader + alias Philomena.{Tags, Tags.Tag} alias Philomena.Textile.Renderer alias Philomena.Interactions alias Philomena.Repo @@ -30,29 +31,16 @@ defmodule PhilomenaWeb.TagController do end def show(conn, %{"id" => slug}) do + user = conn.assigns.current_user + tag = Tag |> where(slug: ^slug) |> preload([:aliases, :implied_tags, :implied_by_tags, :dnp_entries, public_links: :user]) |> Repo.one() - query = conn.assigns.compiled_filter - user = conn.assigns.current_user - images = - Image.search_records( - %{ - query: %{ - bool: %{ - must_not: [query, %{term: %{hidden_from_users: true}}], - must: %{term: %{"namespaced_tags.name": tag.name}} - } - }, - sort: %{created_at: :desc} - }, - conn.assigns.image_pagination, - Image |> preload([:tags, :user]) - ) + ImageLoader.query(conn, %{term: %{"namespaced_tags.name" => tag.name}}) interactions = Interactions.user_interactions(images, user) diff --git a/lib/philomena_web/image_loader.ex b/lib/philomena_web/image_loader.ex new file mode 100644 index 00000000..4977bc9c --- /dev/null +++ b/lib/philomena_web/image_loader.ex @@ -0,0 +1,53 @@ +defmodule PhilomenaWeb.ImageLoader do + alias Philomena.Images.{Image, Query} + import Ecto.Query + + def search_string(conn, search_string, options \\ []) do + user = conn.assigns.current_user + + with {:ok, tree} <- Query.compile(user, search_string) do + {:ok, query(conn, tree, options)} + else + error -> + error + end + end + + def query(conn, body, options \\ []) do + sort_queries = Keyword.get(options, :queries, []) + sort_sorts = Keyword.get(options, :sorts, [%{created_at: :desc}]) + pagination = Keyword.get(options, :pagination, conn.assigns.image_pagination) + + user = conn.assigns.current_user + filter = conn.assigns.compiled_filter + filters = create_filters(user, filter) + + Image.search_records( + %{ + query: %{ + bool: %{ + must: List.flatten([body, sort_queries]), + must_not: filters + } + }, + sort: sort_sorts + }, + pagination, + Image |> preload(:tags) + ) + end + + defp create_filters(user, filter) do + [ + filter, + %{term: %{hidden_from_users: true}} + ] + |> maybe_custom_hide(user) + end + + defp maybe_custom_hide(filters, %{id: id}), + do: [%{term: %{hidden_by_user_ids: id}} | filters] + + defp maybe_custom_hide(filters, _user), + do: filters +end \ No newline at end of file