Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
This repository was archived by the owner on Nov 8, 2022. It is now read-only.

feat: article document concept#409

Merged
mydearxym merged 13 commits intodevfromarticle-document
Jun 24, 2021
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
Show all changes
13 commits
Select commitHold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletionsconfig/config.exs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -66,6 +66,8 @@ config :groupher_server, :customization,
sidebar_communities_index: %{}

config :groupher_server, :article,
min_length: 10,
max_length: 20_000,
# NOTE: do not change unless you know what you are doing
threads: [:post, :job, :repo, :blog],
# in this period, paged articles will sort front if non-article-author commented
Expand Down
2 changes: 2 additions & 0 deletionslib/groupher_server/cms/cms.ex
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -92,6 +92,8 @@ defmodule GroupherServer.CMS do

defdelegate mark_delete_article(thread, id), to: ArticleCURD
defdelegate undo_mark_delete_article(thread, id), to: ArticleCURD
defdelegate remove_article(thread, id), to: ArticleCURD
defdelegate remove_article(thread, id, reason), to: ArticleCURD

defdelegate update_active_timestamp(thread, article), to: ArticleCURD
defdelegate sink_article(thread, id), to: ArticleCURD
Expand Down
86 changes: 63 additions & 23 deletionslib/groupher_server/cms/delegates/article_curd.ex
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,12 +18,14 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do

alias Accounts.Model.User
alias CMS.Model.{Author, Community, PinnedArticle, Embeds}
alias CMS.Model.Repo, as: CMSRepo

alias CMS.Delegate.{
ArticleCommunity,
CommentCurd,
ArticleTag,
CommunityCURD,
Document,
Hooks
}

Expand All@@ -32,6 +34,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
@active_period get_config(:article, :active_period_days)
@default_emotions Embeds.ArticleEmotion.default_emotions()
@default_article_meta Embeds.ArticleMeta.default_meta()
@remove_article_hint "The content does not comply with the community norms"

@doc """
read articles for un-logined user
Expand All@@ -40,7 +43,10 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
with {:ok, info} <- match(thread) do
Multi.new()
|> Multi.run(:inc_views, fn _, _ -> ORM.read(info.model, id, inc: :views) end)
|> Multi.run(:update_article_meta, fn _, %{inc_views: article} ->
|> Multi.run(:load_html, fn _, %{inc_views: article} ->
article |> Repo.preload(:document) |> done
end)
|> Multi.run(:update_article_meta, fn _, %{load_html: article} ->
article_meta = ensure(article.meta, @default_article_meta)
meta = Map.merge(article_meta, %{can_undo_sink: in_active_period?(thread, article)})

Expand All@@ -57,17 +63,11 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
def read_article(thread, id, %User{id: user_id}) do
with {:ok, info} <- match(thread) do
Multi.new()
|> Multi.run(:inc_views, fn _, _ -> ORM.read(info.model, id, inc: :views) end)
|> Multi.run(:update_article_meta, fn _, %{inc_views: article} ->
article_meta = ensure(article.meta, @default_article_meta)
meta = Map.merge(article_meta, %{can_undo_sink: in_active_period?(thread, article)})

ORM.update_meta(article, meta)
end)
|> Multi.run(:add_viewed_user, fn _, %{inc_views: article} ->
|> Multi.run(:normal_read, fn _, _ -> read_article(thread, id) end)
|> Multi.run(:add_viewed_user, fn _, %{normal_read: article} ->
update_viewed_user_list(article, user_id)
end)
|> Multi.run(:set_viewer_has_states, fn _, %{inc_views: article} ->
|> Multi.run(:set_viewer_has_states, fn _, %{normal_read: article} ->
article_meta = if is_nil(article.meta), do: @default_article_meta, else: article.meta

viewer_has_states = %{
Expand All@@ -76,7 +76,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
viewer_has_reported: user_id in article_meta.reported_user_ids
}

{:ok,Map.merge(article,viewer_has_states)}
article |>Map.merge(viewer_has_states) |> done
end)
|> Repo.transaction()
|> result()
Expand DownExpand Up@@ -156,6 +156,9 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
|> Multi.run(:create_article, fn _, _ ->
do_create_article(info.model, attrs, author, community)
end)
|> Multi.run(:create_document, fn _, %{create_article: article} ->
Document.create(article, attrs)
end)
|> Multi.run(:mirror_article, fn _, %{create_article: article} ->
ArticleCommunity.mirror_article(thread, article.id, community.id)
end)
Expand DownExpand Up@@ -211,14 +214,17 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
@doc """
update a article(post/job ...)
"""
def update_article(article,args) do
def update_article(article,attrs) do
Multi.new()
|> Multi.run(:update_article, fn _, _ ->
do_update_article(article, args)
do_update_article(article, attrs)
end)
|> Multi.run(:update_document, fn _, %{update_article: update_article} ->
Document.update(update_article, attrs)
end)
|> Multi.run(:update_comment_question_flag_if_need, fn _, %{update_article: update_article} ->
# 如果帖子的类型变了,那么 update 所有的 flag
case Map.has_key?(args, :is_question) do
case Map.has_key?(attrs, :is_question) do
true -> CommentCurd.batch_update_question_flag(update_article)
false -> {:ok, :pass}
end
Expand DownExpand Up@@ -319,6 +325,31 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
end
end

@doc """
remove article forever
"""
def remove_article(thread, id, reason \\ @remove_article_hint) do
with {:ok, info} <- match(thread),
{:ok, article} <- ORM.find(info.model, id, preload: [:communities, [author: :user]]) do
Multi.new()
|> Multi.run(:remove_article, fn _, _ ->
article |> ORM.delete()
end)
|> Multi.run(:update_community_article_count, fn _, _ ->
CommunityCURD.update_community_count_field(article.communities, thread)
end)
|> Multi.run(:update_user_published_meta, fn _, _ ->
Accounts.update_published_states(article.author.user.id, thread)
end)
|> Multi.run(:delete_document, fn _, _ ->
Document.remove(thread, id)
end)
# TODO: notify author
|> Repo.transaction()
|> result()
end
end

@spec ensure_author_exists(User.t()) :: {:ok, User.t()}
def ensure_author_exists(%User{} = user) do
# unique_constraint: avoid race conditions, make sure user_id unique
Expand DownExpand Up@@ -392,13 +423,12 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
end

# for create artilce step in Multi.new
defp do_create_article(model, attrs, %Author{id: author_id}, %Community{id: community_id}) do
# special article like Repo do not have :body, assign it with default-empty rich text
body = Map.get(attrs, :body, Converter.Article.default_rich_text())
defp do_create_article(model,%{body: _body} =attrs, %Author{id: author_id}, %Community{
id: community_id
}) do
meta = @default_article_meta |> Map.merge(%{thread: module_to_upcase(model)})
attrs = attrs |> Map.merge(%{body: body})

with {:ok, attrs} <-add_rich_text_attrs(attrs) do
with {:ok, attrs} <-add_digest_attrs(attrs) do
model.__struct__
|> model.changeset(attrs)
|> Ecto.Changeset.put_change(:emotions, @default_emotions)
Expand All@@ -409,26 +439,35 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
end
end

# Github Repo 没有传统的 body, 需要特殊处理
# 赋值一个空的 body, 后续在 document 中处理
# 注意:digest 那里也要特殊处理
defp do_create_article(CMSRepo, attrs, author, community) do
body = Map.get(attrs, :body, Converter.Article.default_rich_text())
attrs = Map.put(attrs, :body, body)

do_create_article(CMSRepo, attrs, author, community)
end

defp do_update_article(article, %{body: _} = attrs) do
with {:ok, attrs} <-add_rich_text_attrs(attrs) do
with {:ok, attrs} <-add_digest_attrs(attrs) do
ORM.update(article, attrs)
end
end

defp do_update_article(article, attrs), do: ORM.update(article, attrs)

# is update or create article with body field, parsed and extand it into attrs
defpadd_rich_text_attrs(%{body: body} = attrs) when not is_nil(body) do
defpadd_digest_attrs(%{body: body} = attrs) when not is_nil(body) do
with {:ok, parsed} <- Converter.Article.parse_body(body),
{:ok, digest} <- Converter.Article.parse_digest(parsed.body_map) do
attrs
|> Map.merge(Map.take(parsed, [:body, :body_html]))
|> Map.merge(%{digest: digest})
|> done
end
end

defpadd_rich_text_attrs(attrs), do: attrs
defpadd_digest_attrs(attrs), do: attrs

defp update_viewed_user_list(%{meta: nil} = article, user_id) do
new_ids = Enum.uniq([user_id] ++ @default_article_meta.viewed_user_ids)
Expand DownExpand Up@@ -458,6 +497,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do

defp result({:ok, %{update_edit_status: result}}), do: {:ok, result}
defp result({:ok, %{update_article: result}}), do: {:ok, result}
defp result({:ok, %{remove_article: result}}), do: {:ok, result}
# NOTE: for read article, order is import
defp result({:ok, %{set_viewer_has_states: result}}), do: result |> done()
defp result({:ok, %{update_article_meta: result}}), do: {:ok, result}
Expand Down
124 changes: 124 additions & 0 deletionslib/groupher_server/cms/delegates/document.ex
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
defmodule GroupherServer.CMS.Delegate.Document do
@moduledoc """
CURD operation on post/job ...
"""
import Ecto.Query, warn: false
import Helper.Utils, only: [done: 1, thread_of_article: 2, get_config: 2]

import Helper.ErrorCode
import ShortMaps

alias Helper.{ORM, Converter}
alias GroupherServer.{CMS, Repo}

alias CMS.Model.ArticleDocument
alias Ecto.Multi

# alias Helper.Converter.MdToEditor
alias GroupherServer.Support.Factory

# TODO: spec repo logic
def create(article, %{readme: readme} = attrs) do
# .parse(markdown)
# body = MdToEditor.mock_rich_text(readme)
body = Factory.mock_rich_text(readme)
attrs = attrs |> Map.drop([:readme]) |> Map.put(:body, body)
create(article, attrs)
end

# for create artilce step in Multi.new
def create(article, %{body: body} = attrs) do
with {:ok, article_thread} <- thread_of_article(article, :upcase),
{:ok, parsed} <- Converter.Article.parse_body(body) do
attrs = Map.take(parsed, [:body, :body_html])

Multi.new()
|> Multi.run(:create_article_document, fn _, _ ->
document_attrs =
Map.merge(attrs, %{
thread: article_thread,
article_id: article.id,
title: article.title
})

ArticleDocument |> ORM.create(document_attrs)
end)
|> Multi.run(:create_thread_document, fn _, _ ->
attrs = attrs |> Map.put(foreign_key(article_thread), article.id)

CMS.Model
|> Module.concat("#{Recase.to_title(article_thread)}Document")
|> ORM.create(attrs)
end)
|> Repo.transaction()
|> result()
end
end

@doc """
update both article and thread document
"""
def update(article, %{body: body} = attrs) when not is_nil(body) do
with {:ok, article_thread} <- thread_of_article(article, :upcase),
{:ok, article_doc} <- find_article_document(article_thread, article),
{:ok, thread_doc} <- find_thread_document(article_thread, article),
{:ok, parsed} <- Converter.Article.parse_body(body) do
attrs = Map.take(parsed, [:body, :body_html])

Multi.new()
|> Multi.run(:update_article_document, fn _, _ ->
case Map.has_key?(attrs, :title) do
true -> article_doc |> ORM.update(Map.merge(attrs, %{title: attrs.title}))
false -> article_doc |> ORM.update(attrs)
end
end)
|> Multi.run(:update_thread_document, fn _, _ ->
thread_doc |> ORM.update(attrs)
end)
|> Repo.transaction()
|> result()
end
end

# 只更新 title 的情况
def update(article, %{title: title} = attrs) do
with {:ok, article_thread} <- thread_of_article(article, :upcase),
{:ok, article_doc} <- find_article_document(article_thread, article) do
article_doc |> ORM.update(%{title: attrs.title})
end
end

def update(article, _), do: {:ok, article}

defp find_article_document(article_thread, article) do
ORM.find_by(ArticleDocument, %{article_id: article.id, thread: article_thread})
end

defp find_thread_document(article_thread, article) do
CMS.Model
|> Module.concat("#{Recase.to_title(article_thread)}Document")
|> ORM.find_by(Map.put(%{}, foreign_key(article_thread), article.id))
end

@doc """
remove article document foever
"""
def remove(thread, id) do
thread = thread |> to_string |> String.upcase()

ArticleDocument |> ORM.findby_delete!(%{thread: thread, article_id: id})
end

defp foreign_key(article_thread) do
thread_atom = article_thread |> String.downcase() |> String.to_atom()

:"#{thread_atom}_id"
end

defp result({:ok, %{create_thread_document: result}}), do: {:ok, result}
defp result({:ok, %{update_article_document: result}}), do: {:ok, result}

defp result({:error, _, _result, _steps}) do
{:error, [message: "create document", code: ecode(:create_fails)]}
end
end
6 changes: 6 additions & 0 deletionslib/groupher_server/cms/delegates/hooks/cite.ex
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,6 +65,12 @@ defmodule GroupherServer.CMS.Delegate.Hooks.Cite do
end
end

def handle(%{document: document} = article) do
body = Repo.preload(article, :document) |> get_in([:document, :body])
article = article |> Map.put(:body, body)
handle(article)
end

@doc """
return fmt like:
[
Expand Down
6 changes: 6 additions & 0 deletionslib/groupher_server/cms/delegates/hooks/mention.ex
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,12 @@ defmodule GroupherServer.CMS.Delegate.Hooks.Mention do
end
end

def handle(%{document: document} = article) do
body = Repo.preload(article, :document) |> get_in([:document, :body])
article = article |> Map.put(:body, body)
handle(article)
end

defp handle_mentions(mentions, artiment) do
with {:ok, author} <- author_of(artiment) do
Delivery.send(:mention, artiment, mentions, author)
Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp