philomena/lib/philomena_web/controllers/post_controller.ex
2019-11-17 17:51:14 -05:00

105 lines
No EOL
2.7 KiB
Elixir

defmodule PhilomenaWeb.PostController do
use PhilomenaWeb, :controller
alias Philomena.{Forums.Forum, Posts.Post, Textile.Renderer}
alias Philomena.Repo
import Ecto.Query
def index(conn, params) do
user = conn.assigns.current_user
posts =
Post.search_records(
%{
query: %{
bool: %{
must: parse_search(conn, params) ++ [%{term: %{deleted: false}}]
}
},
sort: parse_sort(params)
},
conn.assigns.pagination,
Post |> preload([topic: :forum, user: [awards: :badge]])
)
rendered =
posts.entries
|> Renderer.render_collection()
posts =
%{posts | entries: Enum.zip(posts.entries, rendered)}
forums =
Forum
|> order_by(asc: :name)
|> Repo.all()
|> Enum.filter(&Canada.Can.can?(user, :show, &1))
|> Enum.map(&{&1.name, &1.id})
forums = [{"-", ""} | forums]
render(conn, "index.html", posts: posts, forums: forums, layout_class: "layout--wide")
end
defp parse_search(conn, %{"post" => post_params}) do
parse_author(post_params) ++
parse_subject(post_params) ++
parse_forum_id(conn, post_params) ++
parse_body(post_params)
end
defp parse_search(_conn, _params), do: [%{match_all: %{}}]
defp parse_author(%{"author" => author}) when author not in [nil, ""] do
case String.contains?(author, ["*", "?"]) do
true ->
[
%{wildcard: %{author: String.downcase(author)}},
%{term: %{anonymous: false}}
]
false ->
[
%{term: %{author: String.downcase(author)}},
%{term: %{anonymous: false}}
]
end
end
defp parse_author(_params), do: []
defp parse_subject(%{"subject" => subject}) when subject not in [nil, ""] do
[%{match: %{subject: %{query: subject, operator: "and"}}}]
end
defp parse_subject(_params), do: []
defp parse_forum_id(conn, %{"forum_id" => forum_id}) when forum_id not in [nil, ""] do
with {forum_id, _rest} <- Integer.parse(forum_id),
true <- valid_forum?(conn.assigns.current_user, forum_id)
do
[%{term: %{forum_id: forum_id}}]
else
_error ->
[]
end
end
defp parse_forum_id(_conn, _params), do: []
defp parse_body(%{"body" => body}) when body not in [nil, ""],
do: [%{match: %{body: body}}]
defp parse_body(_params), do: []
defp parse_sort(%{"post" => %{"sf" => sf, "sd" => sd}}) when sf in ["created_at", "_score"] and sd in ["desc", "asc"] do
%{sf => sd}
end
defp parse_sort(_params) do
%{created_at: :desc}
end
defp valid_forum?(user, forum_id) do
forum =
Forum
|> where(id: ^forum_id)
|> Repo.one()
Canada.Can.can?(user, :show, forum)
end
end