131 lines
3.7 KiB
Elixir
131 lines
3.7 KiB
Elixir
defmodule BDS.Rendering.LinksAndLanguages do
|
|
@moduledoc false
|
|
|
|
import Ecto.Query
|
|
|
|
alias BDS.Media.Media, as: MediaAsset
|
|
alias BDS.Persistence
|
|
alias BDS.PostLinks
|
|
alias BDS.Posts.Post
|
|
alias BDS.Repo
|
|
|
|
def canonical_post_path_by_slug(project_id, main_language) do
|
|
posts =
|
|
Repo.all(
|
|
from post in Post, where: post.project_id == ^project_id and post.status == :published
|
|
)
|
|
|
|
translations =
|
|
Repo.all(
|
|
from translation in BDS.Posts.Translation,
|
|
where: translation.project_id == ^project_id and translation.status == :published
|
|
)
|
|
|
|
post_by_id = Map.new(posts, fn post -> {post.id, post} end)
|
|
|
|
post_paths =
|
|
Enum.into(posts, %{}, fn post ->
|
|
{post.slug, post_path(post, nil)}
|
|
end)
|
|
|
|
Enum.reduce(translations, post_paths, fn translation, acc ->
|
|
case Map.get(post_by_id, translation.translation_for) do
|
|
nil -> acc
|
|
post -> Map.put(acc, post.slug, post_path(post, translation.language, main_language))
|
|
end
|
|
end)
|
|
end
|
|
|
|
def canonical_media_path_by_source_path(project_id) do
|
|
Repo.all(from media in MediaAsset, where: media.project_id == ^project_id)
|
|
|> Enum.reduce(%{}, fn media, acc ->
|
|
datetime = Persistence.from_unix_ms!(media.created_at)
|
|
|
|
source_key =
|
|
Path.join([
|
|
"media",
|
|
Integer.to_string(datetime.year),
|
|
String.pad_leading(Integer.to_string(datetime.month), 2, "0"),
|
|
media.original_name
|
|
])
|
|
|> String.downcase()
|
|
|
|
Map.put(acc, source_key, Path.join("/", media.file_path))
|
|
end)
|
|
end
|
|
|
|
def post_path(post, language_prefix)
|
|
when is_binary(language_prefix) and language_prefix != "" do
|
|
String.trim_trailing(language_prefix, "/") <> post_path(post, nil)
|
|
end
|
|
|
|
def post_path(post, ""), do: post_path(post, nil)
|
|
|
|
def post_path(post, nil) do
|
|
datetime = Persistence.from_unix_ms!(post.created_at)
|
|
|
|
Path.join([
|
|
"/",
|
|
Integer.to_string(datetime.year),
|
|
String.pad_leading(Integer.to_string(datetime.month), 2, "0"),
|
|
String.pad_leading(Integer.to_string(datetime.day), 2, "0"),
|
|
post.slug
|
|
]) <> "/"
|
|
end
|
|
|
|
def post_path(post, language, main_language) do
|
|
prefix = language_prefix(language, main_language)
|
|
post_path(post, prefix)
|
|
end
|
|
|
|
def link_contexts(_project_id, nil, _direction, _main_language), do: []
|
|
|
|
def link_contexts(project_id, post_id, :incoming, main_language) do
|
|
PostLinks.list_incoming_links(post_id)
|
|
|> Enum.map(&link_context(project_id, &1, :incoming, main_language))
|
|
|> Enum.reject(&is_nil/1)
|
|
end
|
|
|
|
def link_contexts(project_id, post_id, :outgoing, main_language) do
|
|
PostLinks.list_outgoing_links(post_id)
|
|
|> Enum.map(&link_context(project_id, &1, :outgoing, main_language))
|
|
|> Enum.reject(&is_nil/1)
|
|
end
|
|
|
|
defp link_context(_project_id, link, direction, main_language) do
|
|
linked_post_id =
|
|
case direction do
|
|
:incoming -> link.source_post_id
|
|
:outgoing -> link.target_post_id
|
|
end
|
|
|
|
case Repo.get(Post, linked_post_id) do
|
|
nil ->
|
|
nil
|
|
|
|
linked_post ->
|
|
%{
|
|
href: post_path(linked_post, nil),
|
|
title: linked_post.title,
|
|
display_slug: linked_post.slug,
|
|
language: normalize_language(linked_post.language, main_language)
|
|
}
|
|
end
|
|
end
|
|
|
|
def language_prefix(language, main_language) when language == main_language, do: ""
|
|
def language_prefix(nil, _main_language), do: ""
|
|
def language_prefix(language, _main_language), do: "/#{language}"
|
|
|
|
def normalize_language(nil, fallback), do: fallback
|
|
def normalize_language("", fallback), do: fallback
|
|
|
|
def normalize_language(language, _fallback) do
|
|
language
|
|
|> to_string()
|
|
|> String.downcase()
|
|
|> String.split("-", parts: 2)
|
|
|> hd()
|
|
end
|
|
end
|