163 lines
4.5 KiB
Elixir
163 lines
4.5 KiB
Elixir
|
defmodule BallsPDS.Ecto.Schema.CollectionObject do
|
||
|
use Ecto.Schema
|
||
|
import Ecto.Query
|
||
|
import Ecto.Changeset
|
||
|
alias BallsPDS.Repo
|
||
|
alias BallsPDS.Ecto.Schema.Object
|
||
|
|
||
|
schema "collection_objects" do
|
||
|
belongs_to(:collection, BallsPDS.Ecto.Schema.Object, foreign_key: :collection_id)
|
||
|
belongs_to(:object, BallsPDS.Ecto.Schema.Object, foreign_key: :object_id)
|
||
|
field(:remote_id, :string)
|
||
|
field(:order_num, :integer)
|
||
|
|
||
|
timestamps()
|
||
|
end
|
||
|
|
||
|
def changeset(struct, params \\ %{}) do
|
||
|
struct
|
||
|
|> cast(params, [
|
||
|
:collection_id,
|
||
|
:remote_id,
|
||
|
:object_id
|
||
|
])
|
||
|
|> validate_required([:collection_id])
|
||
|
|> foreign_key_constraint(:collection_id)
|
||
|
|> foreign_key_constraint(:object_id)
|
||
|
end
|
||
|
|
||
|
def delete(%Object{id: collection_id}, object_id) when is_integer(object_id) do
|
||
|
from(co in __MODULE__,
|
||
|
where: co.collection_id == ^collection_id,
|
||
|
where: co.object_id == ^object_id
|
||
|
)
|
||
|
|> Repo.delete_all()
|
||
|
end
|
||
|
|
||
|
# FIXME: handle if local id passed
|
||
|
def delete(%Object{id: collection_id}, remote_id) when is_binary(remote_id) do
|
||
|
from(co in __MODULE__,
|
||
|
where: co.collection_id == ^collection_id,
|
||
|
where: co.remote_id == ^remote_id
|
||
|
)
|
||
|
|> Repo.delete_all()
|
||
|
end
|
||
|
|
||
|
def delete_all(%Object{id: collection_id}) do
|
||
|
from(co in __MODULE__,
|
||
|
where: co.collection_id == ^collection_id
|
||
|
)
|
||
|
|> Repo.delete_all()
|
||
|
end
|
||
|
|
||
|
def delete_all(%Object{id: collection_id}, ids) when is_list(ids) do
|
||
|
{object_ids, remote_ids} = ids |> Enum.map(&resolve_id/1) |> Enum.reduce({[], []}, fn
|
||
|
nil, acc -> acc
|
||
|
|
||
|
object_id, {object_ids, remote_ids} when is_integer(object_id) -> {[object_id | object_ids], remote_ids}
|
||
|
|
||
|
remote_id, {object_ids, remote_ids} when is_binary(remote_id) -> {object_ids, [remote_id | remote_ids]}
|
||
|
end)
|
||
|
|
||
|
from(co in __MODULE__,
|
||
|
where: co.collection_id == ^collection_id and (co.object_id in ^object_ids or co.remote_id in ^remote_ids)
|
||
|
)
|
||
|
|> Repo.delete_all()
|
||
|
end
|
||
|
|
||
|
def get_ids(%Object{id: object_id}) do
|
||
|
from(co in __MODULE__,
|
||
|
left_join: o in Object,
|
||
|
on: o.id == co.object_id,
|
||
|
where: co.collection_id == ^object_id,
|
||
|
order_by: co.order_num,
|
||
|
select: {o.id, o.path, co.remote_id}
|
||
|
)
|
||
|
|> Repo.query()
|
||
|
end
|
||
|
|
||
|
def get_highest_order_num(%Object{id: object_id}) do
|
||
|
from(co in __MODULE__,
|
||
|
where: co.collection_id == ^object_id,
|
||
|
select: max(co.order_num)
|
||
|
)
|
||
|
|> Repo.one()
|
||
|
|> case do
|
||
|
nil -> 0
|
||
|
order_num -> order_num
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def insert(%Object{id: collection_id} = collection_object, object_id, order_num)
|
||
|
when is_integer(object_id) do
|
||
|
next_order_num =
|
||
|
if order_num == nil do
|
||
|
current_highest_order_num = get_highest_order_num(collection_object)
|
||
|
current_highest_order_num + 100
|
||
|
else
|
||
|
order_num
|
||
|
end
|
||
|
|
||
|
cs =
|
||
|
changeset(%__MODULE__{}, %{
|
||
|
collection_id: collection_id,
|
||
|
object_id: object_id,
|
||
|
order_num: next_order_num
|
||
|
})
|
||
|
|
||
|
Repo.insert(cs)
|
||
|
end
|
||
|
|
||
|
def insert(%Object{id: collection_id} = collection_object, remote_id, order_num)
|
||
|
when is_binary(remote_id) do
|
||
|
next_order_num =
|
||
|
if order_num == nil do
|
||
|
current_highest_order_num = get_highest_order_num(collection_object)
|
||
|
current_highest_order_num + 100
|
||
|
else
|
||
|
order_num
|
||
|
end
|
||
|
|
||
|
cs =
|
||
|
changeset(%__MODULE__{}, %{
|
||
|
collection_id: collection_id,
|
||
|
remote_id: remote_id,
|
||
|
order_num: next_order_num
|
||
|
})
|
||
|
|
||
|
Repo.insert(cs)
|
||
|
end
|
||
|
|
||
|
def insert_all(%Object{} = collection_object, ids) when is_list(ids) do
|
||
|
ids = ids |> Enum.map(&resolve_id/1) |> Enum.filter(fn val -> val == nil end)
|
||
|
|
||
|
current_highest_order_num = get_highest_order_num(collection_object)
|
||
|
next_order_num = current_highest_order_num + 100
|
||
|
|
||
|
Enum.reduce(ids, next_order_num, fn id, next_order_num ->
|
||
|
insert(collection_object, id, next_order_num)
|
||
|
next_order_num + 100
|
||
|
end)
|
||
|
end
|
||
|
|
||
|
defp resolve_id(ap_id) when is_binary(ap_id) do
|
||
|
owner_id = Application.get_env(:balls_pds, :owner_ap_id)
|
||
|
|
||
|
case ap_id do
|
||
|
^owner_id <> suffix ->
|
||
|
with {:uri, %URI{:query => query}} <- {:uri, URI.parse(suffix)},
|
||
|
{:rel, %{"relativeRef" => relative_ref, "service" => service}} <-
|
||
|
{:rel, URI.decode_query(query)},
|
||
|
{:service, true} <-
|
||
|
{:service, Application.get_env(:balls_pds, :did_service) == service} do
|
||
|
Object.get_by_path(relative_ref)
|
||
|
else
|
||
|
_ -> nil
|
||
|
end
|
||
|
|
||
|
remote_id ->
|
||
|
remote_id
|
||
|
end
|
||
|
end
|
||
|
end
|