Current section
Files
Jump to
Current section
Files
lib/imagine/cms_pages.ex
defmodule Imagine.CmsPages do
@moduledoc """
The CmsPages context.
"""
import Ecto.Query, warn: false
alias Imagine.Repo
alias Imagine.CmsPages.{CmsPage, CmsPageObject, CmsPageTag, CmsPageVersion}
# alias Imagine.Accounts.User
@doc """
Returns the list of cms_pages.
## Examples
iex> list_cms_pages()
[%CmsPage{}, ...]
"""
def list_cms_pages(order_by \\ [asc: :path], limit \\ 1000) do
Repo.all(from p in active_pages_query(), order_by: ^order_by, limit: ^limit)
end
def list_recent_cms_pages(limit \\ 10) do
Repo.all(from p in active_pages_query(), order_by: [desc: :updated_on], limit: ^limit)
end
def active_pages_query do
from(p in CmsPage, where: is_nil(p.discarded_at), preload: [:sub_pages])
end
def active_versions_query do
from(v in CmsPageVersion, where: is_nil(v.discarded_at))
end
def discarded_pages_query do
from(p in CmsPage, where: not is_nil(p.discarded_at))
end
def list_discarded_cms_pages do
Repo.all(from p in discarded_pages_query(), order_by: [desc: :discarded_at])
end
def get_home_page! do
Repo.get_by(active_pages_query(), path: "") || Repo.get!(Page, id: 1)
end
def get_trash_page do
%CmsPage{
id: "_trash",
name: "_trash",
path: "_trash",
discarded_at: NaiveDateTime.utc_now(),
sub_pages:
list_discarded_cms_pages()
|> Enum.map(fn p -> %{p | path: "_trash/#{p.name}", sub_pages: []} end)
}
end
@doc """
Gets a single cms_page.
Raises `Ecto.NoResultsError` if the Cms page does not exist.
## Examples
iex> get_cms_page!(123)
%CmsPage{}
iex> get_cms_page!(456)
** (Ecto.NoResultsError)
"""
def get_cms_page!(id),
do: Repo.get!(active_pages_query(), id)
def get_cms_page!(id, opts) do
queryable =
case opts[:include_deleted] do
true -> CmsPage
_ -> active_pages_query()
end
ret = Repo.get!(queryable, id)
ret =
case opts[:preload_versions] do
true ->
ret
|> Repo.preload(
versions:
from(v in CmsPageVersion,
where: is_nil(v.discarded_at),
order_by: [desc: v.version],
select: [:id, :version, :updated_by, :updated_by_username]
)
)
_ ->
ret
end
ret
end
def get_cms_page(id),
do: Repo.get(active_pages_query(), id)
def get_cms_page(id, include_deleted: true),
do: Repo.get(CmsPage, id)
def get_cms_page_with_objects!(id, version \\ nil)
def get_cms_page_with_objects!(id, ""), do: get_cms_page_with_objects!(id, nil)
def get_cms_page_with_objects!(id, nil) do
id
|> get_cms_page!
|> get_published_version
|> preload_objects_and_versions()
end
def get_cms_page_with_objects!(id, version) do
get_cms_page_version_by(cms_page_id: id, version: version)
|> preload_objects_and_versions()
end
def get_cms_page_by_path(path) do
Repo.get_by(active_pages_query(), path: to_string(path))
end
def get_cms_page_by_path_for_nav(path) do
Repo.get_by(active_pages_query(), path: to_string(path))
|> Repo.preload(sub_pages: [:sub_pages])
end
def get_cms_page_version_by(params) do
Repo.get_by(active_versions_query(), params)
end
def get_cms_page_by_path_with_objects(path, version \\ nil)
def get_cms_page_by_path_with_objects(path, nil) do
path
|> get_cms_page_by_path
|> get_published_version
|> preload_objects_and_versions()
end
def get_cms_page_by_path_with_objects(path, version) do
get_cms_page_version_by(path: to_string(path), version: version)
|> preload_objects_and_versions()
end
defp get_published_version(%CmsPage{published_version: v} = page),
do: get_published_version(page, v)
defp get_published_version(_, nil), do: nil
defp get_published_version(_, -1), do: nil
defp get_published_version(page, 0), do: page
defp get_published_version(page, version) do
get_cms_page_version_by(path: page.path, version: version)
end
def preload_objects_and_versions(nil), do: nil
def preload_objects_and_versions(%{version: version} = page_or_version) do
page_or_version
|> Repo.preload([:sub_pages])
|> Repo.preload(
objects: from(o in CmsPageObject, where: o.cms_page_version == ^version),
versions:
from(v in CmsPageVersion,
where: is_nil(v.discarded_at),
order_by: [desc: v.version],
select: [:id, :version, :updated_by, :updated_by_username, :created_on]
)
)
end
@doc """
Creates a cms_page.
## Examples
iex> create_cms_page(%{field: value})
{:ok, %CmsPage{}}
iex> create_cms_page(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_cms_page(attrs, current_user, iteration \\ 0) do
# if this isn't the first time, there was a naming conflict, try again
new_attrs =
case iteration do
0 -> attrs
i -> Map.put(attrs, :name, "#{attrs[:name]}-#{i}")
end
# changeset calculates path, we can use that to check for duplicates
changeset =
%CmsPage{}
|> CmsPage.changeset(new_attrs, true, current_user)
if iteration < 100 && get_cms_page_by_path(changeset.changes.path) do
create_cms_page(attrs, current_user, iteration + 1)
else
result = Repo.insert(changeset)
case result do
{:ok, new_cms_page} ->
{:ok, _version} = create_cms_page_version(new_cms_page)
result
_ ->
result
end
end
end
@doc """
Updates a cms_page, optionally creating a new version (third argument). When creating a new version,
the fourth argument should be the Imagine.Accounts.User who made the change.
## Examples
iex> update_cms_page(cms_page, %{field: new_value})
{:ok, %CmsPage{}}
iex> update_cms_page(cms_page, %{field: bad_value}, true, current_user)
{:error, %Ecto.Changeset{}}
"""
def update_cms_page(
%CmsPage{} = cms_page,
attrs,
save_new_version \\ false,
current_user \\ nil
) do
changeset = CmsPage.changeset(cms_page, attrs, save_new_version, current_user)
result = Repo.update(changeset)
case result do
{:ok, new_cms_page} ->
# do not combine the case statements; both could be true
case changeset do
%{changes: %{parent_id: _new_parent_id}} ->
CmsPage.update_descendant_paths(new_cms_page)
%{changes: %{path: _new_path}} ->
from(v in CmsPageVersion, where: v.cms_page_id == ^new_cms_page.id)
|> Repo.update_all(set: [path: new_cms_page.path])
CmsPage.update_descendant_paths(new_cms_page)
_ ->
nil
end
case changeset do
%{changes: %{version: _new_version}} ->
{:ok, _version} = create_cms_page_version(new_cms_page)
_ ->
nil
end
_ ->
nil
end
Imagine.Cache.flush()
result
end
@doc """
Deletes a CmsPage.
## Examples
iex> delete_cms_page(cms_page)
{:ok, %CmsPage{}}
iex> delete_cms_page(cms_page)
{:error, %Ecto.Changeset{}}
"""
def delete_cms_page(%CmsPage{} = cms_page) do
now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
result =
cms_page
|> Ecto.Changeset.change(%{discarded_at: now})
|> Repo.update()
from(v in CmsPageVersion, where: v.cms_page_id == ^cms_page.id)
|> Repo.update_all(set: [discarded_at: now])
Imagine.Cache.flush()
result
end
def undelete_cms_page(%CmsPage{} = cms_page) do
result =
cms_page
|> Ecto.Changeset.change(%{discarded_at: nil})
|> Repo.update()
from(v in CmsPageVersion, where: v.cms_page_id == ^cms_page.id)
|> Repo.update_all(set: [discarded_at: nil])
Imagine.Cache.flush()
result
end
def destroy_cms_page(%CmsPage{} = cms_page) do
result = Repo.delete(cms_page)
Imagine.Cache.flush()
result
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking cms_page changes.
## Examples
iex> change_cms_page(cms_page)
%Ecto.Changeset{source: %CmsPage{}}
"""
def change_cms_page(%CmsPage{} = cms_page) do
Ecto.Changeset.change(cms_page)
end
@doc """
Returns the list of cms_page_versions.
## Examples
iex> list_cms_page_versions()
[%CmsPageVersion{}, ...]
"""
def list_cms_page_versions do
Repo.all(active_versions_query())
end
@doc """
Gets a single cms_page_version.
Raises `Ecto.NoResultsError` if the Cms page version does not exist.
## Examples
iex> get_cms_page_version!(123)
%CmsPageVersion{}
iex> get_cms_page_version!(456)
** (Ecto.NoResultsError)
"""
def get_cms_page_version!(id),
do: Repo.get!(active_versions_query(), id)
@doc """
Creates a cms_page_version.
## Examples
iex> create_cms_page_version(%{field: value})
{:ok, %CmsPageVersion{}}
iex> create_cms_page_version(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_cms_page_version(cms_page) do
%CmsPageVersion{}
|> CmsPageVersion.changeset(cms_page)
|> Repo.insert()
end
@doc """
Returns the list of cms_page_objects.
## Examples
iex> list_cms_page_objects()
[%CmsPageObject{}, ...]
"""
def list_cms_page_objects do
Repo.all(CmsPageObject)
end
@doc """
Gets a single cms_page_object.
Raises `Ecto.NoResultsError` if the Cms page object does not exist.
## Examples
iex> get_cms_page_object!(123)
%CmsPageObject{}
iex> get_cms_page_object!(456)
** (Ecto.NoResultsError)
"""
def get_cms_page_object!(id),
do: Repo.get!(CmsPageObject, id)
def build_cms_page_object(
%CmsPage{id: cms_page_id, version: cms_page_version},
obj_name,
obj_type
) do
build_cms_page_object(cms_page_id, cms_page_version, obj_name, obj_type)
end
def build_cms_page_object(
%CmsPageVersion{cms_page_id: cms_page_id, version: cms_page_version},
obj_name,
obj_type
) do
build_cms_page_object(cms_page_id, cms_page_version, obj_name, obj_type)
end
def build_cms_page_object(cms_page_id, cms_page_version, obj_name, obj_type) do
%CmsPageObject{cms_page_id: cms_page_id}
|> Ecto.Changeset.change(
name: obj_name,
obj_type: obj_type,
cms_page_version: cms_page_version
)
end
@doc """
Creates a cms_page_object.
## Examples
iex> create_cms_page_object(%{field: value})
{:ok, %CmsPageObject{}}
iex> create_cms_page_object(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_cms_page_object(cms_page, attrs \\ %{}) do
cms_page
|> Ecto.build_assoc(:objects)
|> CmsPageObject.changeset(attrs)
|> Repo.insert()
end
@doc """
Updates a cms_page_object.
## Examples
iex> update_cms_page_object(cms_page_object, %{field: new_value})
{:ok, %CmsPageObject{}}
iex> update_cms_page_object(cms_page_object, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_cms_page_object(%CmsPageObject{} = cms_page_object, attrs) do
cms_page_object
|> CmsPageObject.changeset(attrs)
|> Repo.update()
end
def clone_and_update_cms_page_object(%CmsPageObject{} = cms_page_object, attrs) do
%CmsPageObject{}
|> CmsPageObject.changeset(Map.from_struct(cms_page_object))
|> CmsPageObject.changeset(attrs)
|> Repo.insert()
end
def update_cms_page_objects([], [], _new_version) do
# IO.puts("==== All page objects processed. ====")
end
def update_cms_page_objects(
[cms_page_object | cms_page_objects],
[attrs | attrses],
new_version
) do
# IO.puts("==== Processing page object #{inspect(cms_page_object)} -> #{inspect(attrs)} ====")
{:ok, _} =
clone_and_update_cms_page_object(
cms_page_object,
Map.put(attrs, "cms_page_version", new_version)
)
update_cms_page_objects(cms_page_objects, attrses, new_version)
end
# @doc """
# Returns an `%Ecto.Changeset{}` for tracking cms_page_object changes.
# ## Examples
# iex> change_cms_page_object(cms_page_object)
# %Ecto.Changeset{source: %CmsPageObject{}}
# """
# def change_cms_page_object(%CmsPageObject{} = cms_page_object) do
# CmsPageObject.changeset(cms_page_object, %{})
# end
@doc """
Returns the list of cms_page_tags.
## Examples
iex> list_cms_page_tags()
[%CmsPageTag{}, ...]
"""
def list_cms_page_tags do
Repo.all(CmsPageTag)
end
@doc """
Gets a single cms_page_tag.
Raises `Ecto.NoResultsError` if the Cms page tag does not exist.
## Examples
iex> get_cms_page_tag!(123)
%CmsPageTag{}
iex> get_cms_page_tag!(456)
** (Ecto.NoResultsError)
"""
def get_cms_page_tag!(id),
do: Repo.get!(CmsPageTag, id)
@doc """
Creates a cms_page_tag.
## Examples
iex> create_cms_page_tag(%{field: value})
{:ok, %CmsPageTag{}}
iex> create_cms_page_tag(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_cms_page_tag(attrs) do
%CmsPageTag{}
|> CmsPageTag.changeset(attrs)
|> Repo.insert()
end
@doc """
Updates a cms_page_tag.
## Examples
iex> update_cms_page_tag(cms_page_tag, %{field: new_value})
{:ok, %CmsPageTag{}}
iex> update_cms_page_tag(cms_page_tag, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_cms_page_tag(%CmsPageTag{} = cms_page_tag, attrs) do
cms_page_tag
|> CmsPageTag.changeset(attrs)
|> Repo.update()
end
@doc """
Deletes a CmsPageTag.
## Examples
iex> delete_cms_page_tag(cms_page_tag)
{:ok, %CmsPageTag{}}
iex> delete_cms_page_tag(cms_page_tag)
{:error, %Ecto.Changeset{}}
"""
def delete_cms_page_tag(%CmsPageTag{} = cms_page_tag) do
Repo.delete(cms_page_tag)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking cms_page_tag changes.
## Examples
iex> change_cms_page_tag(cms_page_tag)
%Ecto.Changeset{source: %CmsPageTag{}}
"""
def change_cms_page_tag(%CmsPageTag{} = cms_page_tag) do
CmsPageTag.changeset(cms_page_tag, %{})
end
end