287 lines
5.9 KiB
Elixir
287 lines
5.9 KiB
Elixir
![]() |
defmodule Content.Posts do
|
||
|
@page_size 3
|
||
|
|
||
|
@moduledoc """
|
||
|
The Content context.
|
||
|
"""
|
||
|
|
||
|
import Ecto.Query, warn: false
|
||
|
alias Content.Repo
|
||
|
|
||
|
alias Content.Option
|
||
|
alias Content.Post
|
||
|
alias Ecto.Changeset
|
||
|
|
||
|
@preloads [:metas, :author, :categories, :tags, :comments, :post_format]
|
||
|
|
||
|
@doc """
|
||
|
Returns the lisdpt of posts for admin interface.
|
||
|
|
||
|
## Examples
|
||
|
|
||
|
iex> list_admin_posts()
|
||
|
[%Post{}, ...]
|
||
|
|
||
|
"""
|
||
|
def list_admin_posts(page, post_type \\ "post") do
|
||
|
post_type = post_type || "post"
|
||
|
Repo.all(
|
||
|
from p in Post,
|
||
|
where: p.post_type == ^post_type,
|
||
|
where: p.post_status in ["publish", "future", "draft", "pending", "private", "inherit"],
|
||
|
preload: ^@preloads,
|
||
|
order_by: [desc: p.post_date],
|
||
|
limit: @page_size,
|
||
|
offset: ^(@page_size * (String.to_integer(page) - 1))
|
||
|
)
|
||
|
end
|
||
|
|
||
|
@doc """
|
||
|
Returns the list of posts.
|
||
|
|
||
|
## Examples
|
||
|
|
||
|
iex> list_posts()
|
||
|
[%Post{}, ...]
|
||
|
|
||
|
"""
|
||
|
def list_posts(params \\ %{}) do
|
||
|
page = params |> Map.get("page", "1")
|
||
|
|
||
|
normal_posts =
|
||
|
params
|
||
|
|> post_scope_for_params()
|
||
|
|> limit(@page_size)
|
||
|
|> offset(^(@page_size * (String.to_integer(page) - 1)))
|
||
|
|> Repo.all()
|
||
|
|
||
|
sticky_posts_for_page(params) ++ normal_posts
|
||
|
end
|
||
|
|
||
|
def post_scope_for_params(params) do
|
||
|
post_type = params |> Map.get("post_type", "post")
|
||
|
category = params |> Map.get("category")
|
||
|
|
||
|
query =
|
||
|
post_scope()
|
||
|
|> where([p], p.post_type == ^post_type)
|
||
|
|
||
|
if category do
|
||
|
query |> join(:inner, [p], term in assoc(p, :categories), on: term.slug == ^category)
|
||
|
else
|
||
|
query
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def post_scope do
|
||
|
from p in Post,
|
||
|
where: p.post_status == "publish",
|
||
|
preload: ^@preloads,
|
||
|
order_by: [desc: p.post_date]
|
||
|
end
|
||
|
|
||
|
def post_scope_with_drafts do
|
||
|
from p in Post,
|
||
|
preload: ^@preloads,
|
||
|
order_by: [desc: p.post_date]
|
||
|
end
|
||
|
|
||
|
def sticky_posts_for_page(%{"page" => "1"} = params) do
|
||
|
sticky_posts =
|
||
|
params
|
||
|
|> post_scope_for_params()
|
||
|
|> where([p], p.'ID' in ^sticky_ids())
|
||
|
|> Repo.all()
|
||
|
|
||
|
sticky_posts
|
||
|
|> Enum.map(fn post ->
|
||
|
post
|
||
|
|> Changeset.change(%{sticky: true})
|
||
|
|> Changeset.apply_changes()
|
||
|
end)
|
||
|
end
|
||
|
def sticky_posts_for_page(_), do: []
|
||
|
|
||
|
defp sticky_ids do
|
||
|
case Repo.one(from opt in Option, where: opt.option_name == "sticky_posts") do
|
||
|
nil ->
|
||
|
[]
|
||
|
option ->
|
||
|
option
|
||
|
|> Option.parse_option_value
|
||
|
|> Enum.map(&(elem(&1, 1)))
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def last_page(params \\ %{}) do
|
||
|
post_count =
|
||
|
params
|
||
|
|> post_scope_for_params()
|
||
|
|> Repo.aggregate(:count, :ID)
|
||
|
|
||
|
post_count
|
||
|
|> (&(&1 / @page_size)).()
|
||
|
|> Float.ceil
|
||
|
|> trunc
|
||
|
end
|
||
|
|
||
|
def thumbs_for_posts(posts) do
|
||
|
post_to_thumbnail_id =
|
||
|
posts
|
||
|
|> Enum.map(fn post -> {post.'ID', (post |> Post.metas_map)["_thumbnail_id"]} end)
|
||
|
|> Enum.reject(&(elem(&1, 1) == nil))
|
||
|
|
||
|
thumbs =
|
||
|
Post
|
||
|
|> preload(:metas)
|
||
|
|> where([thumb], thumb.'ID' in ^Enum.map(post_to_thumbnail_id, &(elem(&1, 1))))
|
||
|
|> Repo.all()
|
||
|
|> Enum.map(fn thumb -> {thumb.'ID', thumb} end)
|
||
|
|> Map.new
|
||
|
|
||
|
post_to_thumbnail_id
|
||
|
|> Enum.map(fn {key, value} -> {key, thumbs[String.to_integer(value)]} end)
|
||
|
|> Map.new
|
||
|
end
|
||
|
|
||
|
@doc """
|
||
|
Gets a single posts.
|
||
|
|
||
|
Raises `Ecto.NoResultsError` if the Wp posts does not exist.
|
||
|
|
||
|
## Examples
|
||
|
|
||
|
iex> get_posts!(123)
|
||
|
%Post{}
|
||
|
|
||
|
iex> get_posts!(456)
|
||
|
** (Ecto.NoResultsError)
|
||
|
|
||
|
"""
|
||
|
def get_posts!(slug) do
|
||
|
id_filter = fn scope, id ->
|
||
|
|
||
|
case Integer.parse(id, 10) do
|
||
|
:error ->
|
||
|
scope |> where([p], p.post_name == ^id)
|
||
|
{int_id, _} ->
|
||
|
scope |> where([p], p.'ID' == ^int_id)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
post_scope()
|
||
|
|> where([p], p.post_type != "nav_menu_item")
|
||
|
|> id_filter.(slug)
|
||
|
|> Repo.one!()
|
||
|
end
|
||
|
|
||
|
@doc """
|
||
|
Gets a single post that may or may not be in draft status.
|
||
|
|
||
|
Raises `Ecto.NoResultsError` if the Wp posts does not exist.
|
||
|
|
||
|
## Examples
|
||
|
|
||
|
iex> get_post_with_drafts!(123)
|
||
|
%Post{}
|
||
|
|
||
|
iex> get_post_with_drafts!(456)
|
||
|
** (Ecto.NoResultsError)
|
||
|
|
||
|
"""
|
||
|
def get_post_with_drafts!(slug) do
|
||
|
id_filter = fn scope, id ->
|
||
|
|
||
|
case Integer.parse(id, 10) do
|
||
|
:error ->
|
||
|
scope |> where([p], p.post_name == ^id)
|
||
|
{int_id, ""} ->
|
||
|
scope |> where([p], p.'ID' == ^int_id)
|
||
|
{_int_id, _} ->
|
||
|
scope |> where([p], p.post_name == ^id)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
post_scope_with_drafts()
|
||
|
|> where([p], p.post_type != "nav_menu_item")
|
||
|
|> id_filter.(slug)
|
||
|
|> Repo.one!()
|
||
|
end
|
||
|
|
||
|
@doc """
|
||
|
Creates a posts.
|
||
|
|
||
|
## Examples
|
||
|
|
||
|
iex> create_posts(%{field: value})
|
||
|
{:ok, %Post{}}
|
||
|
|
||
|
iex> create_posts(%{field: bad_value})
|
||
|
{:error, %Ecto.Changeset{}}
|
||
|
|
||
|
"""
|
||
|
def create_posts(attrs \\ %{}) do
|
||
|
%Post{}
|
||
|
|> Post.changeset(attrs)
|
||
|
|> Repo.insert()
|
||
|
end
|
||
|
|
||
|
@doc """
|
||
|
Builds a post for preview, but does not save it.
|
||
|
"""
|
||
|
def preview_post(attrs \\ %{}) do
|
||
|
%Post{}
|
||
|
|> Repo.preload(@preloads)
|
||
|
|> Post.changeset(attrs)
|
||
|
|> Changeset.put_change(:post_name, "preview")
|
||
|
|> Changeset.apply_changes()
|
||
|
end
|
||
|
|
||
|
@doc """
|
||
|
Updates a posts.
|
||
|
|
||
|
## Examples
|
||
|
|
||
|
iex> update_posts(posts, %{field: new_value})
|
||
|
{:ok, %Post{}}
|
||
|
|
||
|
iex> update_posts(posts, %{field: bad_value})
|
||
|
{:error, %Ecto.Changeset{}}
|
||
|
|
||
|
"""
|
||
|
def update_posts(%Post{} = posts, attrs) do
|
||
|
posts
|
||
|
|> Post.changeset(attrs)
|
||
|
|> Repo.update()
|
||
|
end
|
||
|
|
||
|
@doc """
|
||
|
Deletes a Post.
|
||
|
|
||
|
## Examples
|
||
|
|
||
|
iex> delete_posts(posts)
|
||
|
{:ok, %Post{}}
|
||
|
|
||
|
iex> delete_posts(posts)
|
||
|
{:error, %Ecto.Changeset{}}
|
||
|
|
||
|
"""
|
||
|
def delete_posts(%Post{} = posts) do
|
||
|
Repo.delete(posts)
|
||
|
end
|
||
|
|
||
|
@doc """
|
||
|
Returns an `%Ecto.Changeset{}` for tracking posts changes.
|
||
|
|
||
|
## Examples
|
||
|
|
||
|
iex> change_posts(posts)
|
||
|
%Ecto.Changeset{source: %Post{}}
|
||
|
|
||
|
"""
|
||
|
def change_posts(%Post{} = posts) do
|
||
|
Post.changeset(posts, %{})
|
||
|
end
|
||
|
end
|