Skip to content
This repository was archived by the owner on Nov 8, 2022. It is now read-only.

Commit 52934d4

Browse files
committed
refactor(cite-task): support cite artilce in side comment
1 parent e4e266b commit 52934d4

File tree

10 files changed

+163
-27
lines changed

10 files changed

+163
-27
lines changed

lib/groupher_server/cms/delegates/article_curd.ex

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,10 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
164164
|> Multi.run(:update_user_published_meta, fn _, _ ->
165165
Accounts.update_published_states(uid, thread)
166166
end)
167-
|> Multi.run(:block_tasks, fn _, %{create_article: article} ->
167+
|> Multi.run(:after_tasks, fn _, %{create_article: article} ->
168168
Later.run({CiteTasks, :handle, [article]})
169+
Later.run({__MODULE__, :notify_admin_new_article, [article]})
169170
end)
170-
# TODO: run mini tasks
171171
|> Multi.run(:mention_users, fn _, %{create_article: article} ->
172172
# article.body |> Jason.decode!() |> 各种小 task
173173
Delivery.mention_from_content(community.raw, thread, article, attrs, %User{id: uid})
@@ -223,6 +223,9 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
223223
|> Multi.run(:update_edit_status, fn _, %{update_article: update_article} ->
224224
ArticleCommunity.update_edit_status(update_article)
225225
end)
226+
|> Multi.run(:after_tasks, fn _, %{update_article: update_article} ->
227+
Later.run({CiteTasks, :handle, [update_article]})
228+
end)
226229
|> Repo.transaction()
227230
|> result()
228231
end
@@ -449,7 +452,6 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
449452

450453
# create done
451454
defp result({:ok, %{set_active_at_timestamp: result}}) do
452-
Later.run({__MODULE__, :notify_admin_new_article, [result]})
453455
{:ok, result}
454456
end
455457

lib/groupher_server/cms/delegates/cite_tasks.ex

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ defmodule GroupherServer.CMS.Delegate.CiteTasks do
2929
import Helper.ErrorCode
3030

3131
alias GroupherServer.{CMS, Repo}
32-
alias CMS.Model.CitedContent
32+
alias CMS.Model.{CitedContent, Comment}
3333
alias Helper.ORM
3434

3535
alias Ecto.Multi
@@ -38,16 +38,16 @@ defmodule GroupherServer.CMS.Delegate.CiteTasks do
3838
@article_threads get_config(:article, :threads)
3939
@valid_article_prefix Enum.map(@article_threads, &"#{@site_host}/#{&1}/")
4040

41-
def handle(%{body: body} = article) do
41+
def handle(%{body: body} = content) do
4242
with {:ok, %{"blocks" => blocks}} <- Jason.decode(body),
43-
article <- Repo.preload(article, author: :user) do
43+
content <- preload_content_author(content) do
4444
Multi.new()
4545
|> Multi.run(:delete_all_cited_contents, fn _, _ ->
46-
delete_all_cited_contents(article)
46+
delete_all_cited_contents(content)
4747
end)
4848
|> Multi.run(:update_cited_info, fn _, _ ->
4949
blocks
50-
|> Enum.reduce([], &(&2 ++ parse_cited_info_per_block(article, &1)))
50+
|> Enum.reduce([], &(&2 ++ parse_cited_info_per_block(content, &1)))
5151
|> merge_same_cited_article_block
5252
|> update_cited_info
5353
end)
@@ -56,9 +56,17 @@ defmodule GroupherServer.CMS.Delegate.CiteTasks do
5656
end
5757
end
5858

59+
def preload_content_author(%Comment{} = comment), do: comment
60+
def preload_content_author(article), do: Repo.preload(article, author: :user)
61+
5962
# delete all records before insert_all, this will dynamiclly update
6063
# those cited info when update article
6164
# 插入引用记录之前先全部清除,这样可以在更新文章的时候自动计算引用信息
65+
defp delete_all_cited_contents(%Comment{} = comment) do
66+
query = from(c in CitedContent, where: c.comment_id == ^comment.id)
67+
ORM.delete_all(query, :if_exist)
68+
end
69+
6270
defp delete_all_cited_contents(article) do
6371
with {:ok, thread} <- thread_of_article(article),
6472
{:ok, info} <- match(thread) do
@@ -73,6 +81,8 @@ defmodule GroupherServer.CMS.Delegate.CiteTasks do
7381
defp update_cited_info(cited_contents) do
7482
clean_cited_contents = Enum.map(cited_contents, &Map.delete(&1, :cited_article))
7583
# IO.inspect(clean_cited_contents, label: "clean_cited_contents")
84+
# IO.inspect(cited_contents, label: "cited_contents")
85+
7686
with true <- {0, nil} !== Repo.insert_all(CitedContent, clean_cited_contents) do
7787
update_citing_count(cited_contents)
7888
else
@@ -148,9 +158,27 @@ defmodule GroupherServer.CMS.Delegate.CiteTasks do
148158
]
149159
"""
150160
defp parse_cited_info_per_block(article, %{"id" => block_id, "data" => %{"text" => text}}) do
151-
links_in_block = Floki.find(text, "a[href]")
161+
links = Floki.find(text, "a[href]")
162+
163+
do_parse_cited_info(article, block_id, links)
164+
end
165+
166+
defp do_parse_cited_info(%Comment{} = comment, block_id, links) do
167+
Enum.reduce(links, [], fn link, acc ->
168+
with {:ok, cited_article} <- parse_cited_article(link) do
169+
List.insert_at(acc, 0, shape_cited_content(comment, cited_article, block_id))
170+
else
171+
_ -> acc
172+
end
173+
end)
174+
|> Enum.uniq()
175+
end
152176

153-
Enum.reduce(links_in_block, [], fn link, acc ->
177+
# links Floki parsed fmt
178+
# e.g:
179+
# [{"a", [{"href", "https://coderplanets.com/post/195675"}], []},]
180+
defp do_parse_cited_info(article, block_id, links) do
181+
Enum.reduce(links, [], fn link, acc ->
154182
with {:ok, cited_article} <- parse_cited_article(link),
155183
# do not cite artilce itself
156184
true <- article.id !== cited_article.id do
@@ -162,6 +190,20 @@ defmodule GroupherServer.CMS.Delegate.CiteTasks do
162190
|> Enum.uniq()
163191
end
164192

193+
# 在评论中引用文章的情况
194+
defp shape_cited_content(%Comment{} = comment, cited_article, block_id) do
195+
%{
196+
cited_by_id: cited_article.id,
197+
cited_by_type: cited_article.meta.thread,
198+
# used for updating citing_count, avoid load again
199+
cited_article: cited_article,
200+
comment_id: comment.id,
201+
block_linker: [block_id],
202+
user_id: comment.author_id
203+
}
204+
end
205+
206+
# 文章之间相互引用的情况
165207
defp shape_cited_content(article, cited_article, block_id) do
166208
{:ok, thread} = thread_of_article(article)
167209
{:ok, info} = match(thread)

lib/groupher_server/cms/delegates/comment_curd.ex

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ defmodule GroupherServer.CMS.Delegate.CommentCurd do
1111
import ShortMaps
1212

1313
alias Helper.Types, as: T
14-
alias Helper.{ORM, QueryBuilder, Converter}
14+
alias Helper.{Later, ORM, QueryBuilder, Converter}
1515
alias GroupherServer.{Accounts, CMS, Repo}
1616
alias CMS.Model.Post
1717

@@ -113,6 +113,9 @@ defmodule GroupherServer.CMS.Delegate.CommentCurd do
113113
false -> CMS.update_active_timestamp(thread, article)
114114
end
115115
end)
116+
|> Multi.run(:block_tasks, fn _, %{create_comment: create_comment} ->
117+
Later.run({CiteTasks, :handle, [create_comment]})
118+
end)
116119
|> Repo.transaction()
117120
|> result()
118121
else

test/groupher_server/cms/cite_contents/cite_blog_test.exs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,37 @@ defmodule GroupherServer.Test.CMS.CiteContent.Blog do
7373
{:ok, blog} = ORM.find(Blog, blog.id)
7474
assert blog.meta.citing_count == 0
7575
end
76+
77+
@tag :wip
78+
test "can cited blog inside a comment", ~m(user blog blog2 blog3 blog4 blog5)a do
79+
comment_body =
80+
mock_rich_text(
81+
~s(the <a href=#{@site_host}/blog/#{blog2.id} /> and <a href=#{@site_host}/blog/#{
82+
blog2.id
83+
}>same la</a> is awesome, the <a href=#{@site_host}/blog/#{blog3.id}></a> is awesome too.),
84+
# second paragraph
85+
~s(the paragraph 2 <a href=#{@site_host}/blog/#{blog2.id} class=#{blog2.title}> again</a>, the paragraph 2 <a href=#{
86+
@site_host
87+
}/blog/#{blog4.id}> again</a>, the paragraph 2 <a href=#{@site_host}/blog/#{blog5.id}> again</a>)
88+
)
89+
90+
{:ok, comment} = CMS.create_comment(:blog, blog.id, comment_body, user)
91+
CiteTasks.handle(comment)
92+
93+
comment_body = mock_rich_text(~s(the <a href=#{@site_host}/blog/#{blog3.id} />))
94+
{:ok, comment} = CMS.create_comment(:blog, blog.id, comment_body, user)
95+
96+
CiteTasks.handle(comment)
97+
98+
{:ok, blog2} = ORM.find(Blog, blog2.id)
99+
{:ok, blog3} = ORM.find(Blog, blog3.id)
100+
{:ok, blog4} = ORM.find(Blog, blog4.id)
101+
{:ok, blog5} = ORM.find(Blog, blog5.id)
102+
103+
assert blog2.meta.citing_count == 1
104+
assert blog3.meta.citing_count == 2
105+
assert blog4.meta.citing_count == 1
106+
assert blog5.meta.citing_count == 1
107+
end
76108
end
77109
end

test/groupher_server/cms/cite_contents/cite_job_test.exs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,37 @@ defmodule GroupherServer.Test.CMS.CiteContent.Job do
7373
{:ok, job} = ORM.find(Job, job.id)
7474
assert job.meta.citing_count == 0
7575
end
76+
77+
@tag :wip
78+
test "can cited job inside a comment", ~m(user job job2 job3 job4 job5)a do
79+
comment_body =
80+
mock_rich_text(
81+
~s(the <a href=#{@site_host}/job/#{job2.id} /> and <a href=#{@site_host}/job/#{job2.id}>same la</a> is awesome, the <a href=#{
82+
@site_host
83+
}/job/#{job3.id}></a> is awesome too.),
84+
# second paragraph
85+
~s(the paragraph 2 <a href=#{@site_host}/job/#{job2.id} class=#{job2.title}> again</a>, the paragraph 2 <a href=#{
86+
@site_host
87+
}/job/#{job4.id}> again</a>, the paragraph 2 <a href=#{@site_host}/job/#{job5.id}> again</a>)
88+
)
89+
90+
{:ok, comment} = CMS.create_comment(:job, job.id, comment_body, user)
91+
CiteTasks.handle(comment)
92+
93+
comment_body = mock_rich_text(~s(the <a href=#{@site_host}/job/#{job3.id} />))
94+
{:ok, comment} = CMS.create_comment(:job, job.id, comment_body, user)
95+
96+
CiteTasks.handle(comment)
97+
98+
{:ok, job2} = ORM.find(Job, job2.id)
99+
{:ok, job3} = ORM.find(Job, job3.id)
100+
{:ok, job4} = ORM.find(Job, job4.id)
101+
{:ok, job5} = ORM.find(Job, job5.id)
102+
103+
assert job2.meta.citing_count == 1
104+
assert job3.meta.citing_count == 2
105+
assert job4.meta.citing_count == 1
106+
assert job5.meta.citing_count == 1
107+
end
76108
end
77109
end

test/groupher_server/cms/cite_contents/cite_post_test.exs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ defmodule GroupherServer.Test.CMS.CiteContent.Post do
2929
end
3030

3131
describe "[cite basic]" do
32+
# @tag :wip
3233
test "cited multi post should work", ~m(user community post2 post3 post4 post5 post_attrs)a do
3334
body =
3435
mock_rich_text(
@@ -73,5 +74,37 @@ defmodule GroupherServer.Test.CMS.CiteContent.Post do
7374
{:ok, post} = ORM.find(Post, post.id)
7475
assert post.meta.citing_count == 0
7576
end
77+
78+
@tag :wip
79+
test "can cited post inside a comment", ~m(user post post2 post3 post4 post5)a do
80+
comment_body =
81+
mock_rich_text(
82+
~s(the <a href=#{@site_host}/post/#{post2.id} /> and <a href=#{@site_host}/post/#{
83+
post2.id
84+
}>same la</a> is awesome, the <a href=#{@site_host}/post/#{post3.id}></a> is awesome too.),
85+
# second paragraph
86+
~s(the paragraph 2 <a href=#{@site_host}/post/#{post2.id} class=#{post2.title}> again</a>, the paragraph 2 <a href=#{
87+
@site_host
88+
}/post/#{post4.id}> again</a>, the paragraph 2 <a href=#{@site_host}/post/#{post5.id}> again</a>)
89+
)
90+
91+
{:ok, comment} = CMS.create_comment(:post, post.id, comment_body, user)
92+
CiteTasks.handle(comment)
93+
94+
comment_body = mock_rich_text(~s(the <a href=#{@site_host}/post/#{post3.id} />))
95+
{:ok, comment} = CMS.create_comment(:post, post.id, comment_body, user)
96+
97+
CiteTasks.handle(comment)
98+
99+
{:ok, post2} = ORM.find(Post, post2.id)
100+
{:ok, post3} = ORM.find(Post, post3.id)
101+
{:ok, post4} = ORM.find(Post, post4.id)
102+
{:ok, post5} = ORM.find(Post, post5.id)
103+
104+
assert post2.meta.citing_count == 1
105+
assert post3.meta.citing_count == 2
106+
assert post4.meta.citing_count == 1
107+
assert post5.meta.citing_count == 1
108+
end
76109
end
77110
end

test/groupher_server_web/mutation/cms/comments/blog_comment_test.exs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ defmodule GroupherServer.Test.Mutation.Comments.BlogComment do
279279
}
280280
}
281281
"""
282-
@tag :wip
282+
283283
test "can pin a blog's comment", ~m(owner_conn blog user)a do
284284
{:ok, comment} = CMS.create_comment(:blog, blog.id, mock_comment(), user)
285285

@@ -290,7 +290,6 @@ defmodule GroupherServer.Test.Mutation.Comments.BlogComment do
290290
assert result["isPinned"]
291291
end
292292

293-
@tag :wip
294293
test "unauth user fails.", ~m(guest_conn blog user)a do
295294
{:ok, comment} = CMS.create_comment(:blog, blog.id, mock_comment(), user)
296295
variables = %{id: comment.id}
@@ -306,7 +305,7 @@ defmodule GroupherServer.Test.Mutation.Comments.BlogComment do
306305
}
307306
}
308307
"""
309-
@tag :wip
308+
310309
test "can undo pin a blog's comment", ~m(owner_conn blog user)a do
311310
{:ok, comment} = CMS.create_comment(:blog, blog.id, mock_comment(), user)
312311
{:ok, _} = CMS.pin_comment(comment.id)
@@ -318,7 +317,6 @@ defmodule GroupherServer.Test.Mutation.Comments.BlogComment do
318317
assert not result["isPinned"]
319318
end
320319

321-
@tag :wip
322320
test "unauth user undo fails.", ~m(guest_conn blog user)a do
323321
{:ok, comment} = CMS.create_comment(:blog, blog.id, mock_comment(), user)
324322
{:ok, _} = CMS.pin_comment(comment.id)

test/groupher_server_web/mutation/cms/comments/job_comment_test.exs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ defmodule GroupherServer.Test.Mutation.Comments.JobComment do
279279
}
280280
}
281281
"""
282-
@tag :wip
282+
283283
test "can pin a job's comment", ~m(owner_conn job user)a do
284284
{:ok, comment} = CMS.create_comment(:job, job.id, mock_comment(), user)
285285

@@ -290,7 +290,6 @@ defmodule GroupherServer.Test.Mutation.Comments.JobComment do
290290
assert result["isPinned"]
291291
end
292292

293-
@tag :wip
294293
test "unauth user fails.", ~m(guest_conn job user)a do
295294
{:ok, comment} = CMS.create_comment(:job, job.id, mock_comment(), user)
296295
variables = %{id: comment.id}
@@ -306,7 +305,7 @@ defmodule GroupherServer.Test.Mutation.Comments.JobComment do
306305
}
307306
}
308307
"""
309-
@tag :wip
308+
310309
test "can undo pin a job's comment", ~m(owner_conn job user)a do
311310
{:ok, comment} = CMS.create_comment(:job, job.id, mock_comment(), user)
312311
{:ok, _} = CMS.pin_comment(comment.id)
@@ -318,7 +317,6 @@ defmodule GroupherServer.Test.Mutation.Comments.JobComment do
318317
assert not result["isPinned"]
319318
end
320319

321-
@tag :wip
322320
test "unauth user undo fails.", ~m(guest_conn job user)a do
323321
{:ok, comment} = CMS.create_comment(:job, job.id, mock_comment(), user)
324322
{:ok, _} = CMS.pin_comment(comment.id)

test/groupher_server_web/mutation/cms/comments/post_comment_test.exs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ defmodule GroupherServer.Test.Mutation.Comments.PostComment do
280280
}
281281
}
282282
"""
283-
@tag :wip
283+
284284
test "can pin a post's comment", ~m(owner_conn post user)a do
285285
{:ok, comment} = CMS.create_comment(:post, post.id, mock_comment(), user)
286286

@@ -291,7 +291,6 @@ defmodule GroupherServer.Test.Mutation.Comments.PostComment do
291291
assert result["isPinned"]
292292
end
293293

294-
@tag :wip
295294
test "unauth user fails.", ~m(guest_conn post user)a do
296295
{:ok, comment} = CMS.create_comment(:post, post.id, mock_comment(), user)
297296
variables = %{id: comment.id}
@@ -307,7 +306,7 @@ defmodule GroupherServer.Test.Mutation.Comments.PostComment do
307306
}
308307
}
309308
"""
310-
@tag :wip
309+
311310
test "can undo pin a post's comment", ~m(owner_conn post user)a do
312311
{:ok, comment} = CMS.create_comment(:post, post.id, mock_comment(), user)
313312
{:ok, _} = CMS.pin_comment(comment.id)
@@ -319,7 +318,6 @@ defmodule GroupherServer.Test.Mutation.Comments.PostComment do
319318
assert not result["isPinned"]
320319
end
321320

322-
@tag :wip
323321
test "unauth user undo fails.", ~m(guest_conn post user)a do
324322
{:ok, comment} = CMS.create_comment(:post, post.id, mock_comment(), user)
325323
{:ok, _} = CMS.pin_comment(comment.id)

0 commit comments

Comments
 (0)