@@ -5,55 +5,97 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
55 import Ecto.Query , warn: false
66
77 import GroupherServer.CMS.Utils.Matcher2
8+ import GroupherServer.CMS.Utils.Matcher , only: [ match_action: 2 ]
89
9- import GroupherServer.CMS.Utils.Matcher , only: [ match_action: 2 , dynamic_where: 2 ]
1010 import Helper.Utils , only: [ done: 1 , pick_by: 2 , integerfy: 1 ]
1111 import Helper.ErrorCode
12- import ShortMaps
1312
13+ alias Helper . { Later , ORM }
1414 alias GroupherServer . { Accounts , CMS , Delivery , Email , Repo , Statistics }
1515
1616 alias Accounts.User
1717 alias CMS . { Author , Community , PinnedArticle , Embeds , Delegate , Tag }
1818
1919 alias Delegate.ArticleOperation
20- alias Helper . { Later , ORM , QueryBuilder }
2120
2221 alias Ecto.Multi
2322
2423 @ default_article_meta Embeds.ArticleMeta . default_meta ( )
2524
2625 @ doc """
27- login user read cms content by add views count and viewer record
26+ read articles for un-logined user
2827 """
29- def read_content ( thread , id , % User { id: user_id } ) do
30- condition = % { user_id: user_id } |> Map . merge ( content_id ( thread , id ) )
31-
32- with { :ok , action } <- match_action ( thread , :self ) ,
33- { :ok , _viewer } <- action . viewer |> ORM . findby_or_insert ( condition , condition ) do
34- action . target |> ORM . read ( id , inc: :views )
28+ def read_article ( thread , id ) do
29+ with { :ok , info } <- match ( thread ) do
30+ ORM . read ( info . model , id , inc: :views )
3531 end
3632 end
3733
3834 @ doc """
39- get paged post / job ...
35+ read articles for logined user
4036 """
41- def paged_contents ( queryable , filter , user ) do
42- queryable
43- |> domain_filter_query ( filter )
44- |> community_with_flag_query ( filter )
45- |> read_state_query ( filter , user )
46- |> ORM . find_all ( filter )
47- |> add_pin_contents_ifneed ( queryable , filter )
37+ def read_article ( thread , id , % User { id: user_id } ) do
38+ with { :ok , info } <- match ( thread ) do
39+ Multi . new ( )
40+ |> Multi . run ( :inc_views , fn _ , _ ->
41+ ORM . read ( info . model , id , inc: :views )
42+ end )
43+ |> Multi . run ( :add_viewed_user , fn _ , % { inc_views: article } ->
44+ update_viewed_user_list ( article , user_id )
45+ end )
46+ |> Repo . transaction ( )
47+ |> read_result ( )
48+ end
4849 end
4950
50- def paged_contents ( queryable , filter ) do
51- queryable
52- |> domain_filter_query ( filter )
53- |> community_with_flag_query ( filter )
54- |> ORM . find_all ( filter )
55- # TODO: if filter has when/sort/length/job... then don't
56- |> add_pin_contents_ifneed ( queryable , filter )
51+ def paged_articles ( thread , filter ) do
52+ with { :ok , info } <- match ( thread ) do
53+ info . model
54+ |> domain_filter_query ( filter )
55+ |> community_with_flag_query ( filter )
56+ |> ORM . find_all ( filter )
57+ |> add_pin_contents_ifneed ( info . model , filter )
58+ end
59+ end
60+
61+ def paged_articles ( thread , filter , % User { } = user ) do
62+ with { :ok , info } <- match ( thread ) do
63+ info . model
64+ |> domain_filter_query ( filter )
65+ |> community_with_flag_query ( filter )
66+ |> ORM . find_all ( filter )
67+ |> add_pin_contents_ifneed ( info . model , filter )
68+ |> mark_viewer_has_states ( user )
69+ end
70+ end
71+
72+ defp mark_viewer_has_states ( { :ok , % { entries: [ ] } = contents } , _ ) , do: { :ok , contents }
73+
74+ defp mark_viewer_has_states ( { :ok , % { entries: entries } = contents } , user ) do
75+ entries = Enum . map ( entries , & Map . merge ( & 1 , do_mark_viewer_has_states ( & 1 . meta , user ) ) )
76+ { :ok , Map . merge ( contents , % { entries: entries } ) }
77+ end
78+
79+ defp mark_viewer_has_states ( { :error , reason } , _ ) , do: { :error , reason }
80+
81+ defp do_mark_viewer_has_states ( nil , _ ) do
82+ % {
83+ viewer_has_collected: false ,
84+ viewer_has_upvoted: false ,
85+ viewer_has_viewed: false ,
86+ viewer_has_reported: false
87+ }
88+ end
89+
90+ defp do_mark_viewer_has_states ( meta , % User { id: user_id } ) do
91+ # TODO: 根据是否付费进一步判断
92+ # user_is_member = true
93+ % {
94+ viewer_has_collected: Enum . member? ( meta . collected_user_ids , user_id ) ,
95+ viewer_has_upvoted: Enum . member? ( meta . upvoted_user_ids , user_id ) ,
96+ viewer_has_viewed: Enum . member? ( meta . viewed_user_ids , user_id ) ,
97+ viewer_has_reported: Enum . member? ( meta . reported_user_ids , user_id )
98+ }
5799 end
58100
59101 @ doc """
@@ -246,19 +288,6 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
246288
247289 defp domain_filter_query ( queryable , _filter ) , do: queryable
248290
249- # query if user has viewed before
250- defp read_state_query ( queryable , % { read: true } = _filter , user ) do
251- queryable
252- |> join ( :inner , [ content , f , c ] , viewers in assoc ( content , :viewers ) )
253- |> where ( [ content , f , c , viewers ] , viewers . user_id == ^ user . id )
254- end
255-
256- defp read_state_query ( queryable , % { read: false } = _filter , _user ) do
257- queryable
258- end
259-
260- defp read_state_query ( queryable , _ , _ ) , do: queryable
261-
262291 defp add_pin_contents_ifneed ( contents , querable , % { community: _community } = filter ) do
263292 with { :ok , _ } <- should_add_pin? ( filter ) ,
264293 { :ok , info } <- match ( querable ) ,
@@ -285,10 +314,10 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
285314 defp add_pin_contents_ifneed ( contents , _querable , _filter ) , do: contents
286315
287316 # if filter contains like: tags, sort.., then don't add pin content
288- defp should_add_pin? ( % { page: 1 , tag: :all , sort: :desc_inserted , read: :all } = filter ) do
317+ defp should_add_pin? ( % { page: 1 , tag: :all , sort: :desc_inserted } = filter ) do
289318 filter
290319 |> Map . keys ( )
291- |> Enum . reject ( fn x -> x in [ :community , :tag , :sort , :read , : page, :size ] end )
320+ |> Enum . reject ( fn x -> x in [ :community , :tag , :sort , :page , :size ] end )
292321 |> case do
293322 [ ] -> { :ok , :pass }
294323 _ -> { :error , :pass }
@@ -355,10 +384,6 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
355384 defp update_content_result ( { :error , :update_content , result , _steps } ) , do: { :error , result }
356385 defp update_content_result ( { :error , :update_tag , result , _steps } ) , do: { :error , result }
357386
358- defp content_id ( :post , id ) , do: % { post_id: id }
359- defp content_id ( :job , id ) , do: % { job_id: id }
360- defp content_id ( :repo , id ) , do: % { repo_id: id }
361-
362387 # for create content step in Multi.new
363388 defp do_create_content ( target , attrs , % Author { id: aid } , % Community { id: cid } ) do
364389 target
@@ -417,4 +442,32 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
417442 end
418443
419444 defp exec_update_tags ( _content , _ ) , do: { :ok , :pass }
445+
446+ defp update_viewed_user_list ( % { meta: nil } = article , user_id ) do
447+ new_ids = Enum . uniq ( [ user_id ] ++ @ default_article_meta . viewed_user_ids )
448+ updated_meta = @ default_article_meta |> Map . merge ( % { viewed_user_ids: new_ids } )
449+
450+ article
451+ |> Ecto.Changeset . change ( )
452+ |> Ecto.Changeset . put_embed ( :meta , updated_meta )
453+ |> Repo . update ( )
454+ end
455+
456+ defp update_viewed_user_list ( % { meta: meta } = article , user_id ) do
457+ new_ids = Enum . uniq ( [ user_id ] ++ meta . viewed_user_ids )
458+
459+ updated_meta =
460+ meta |> Map . merge ( % { viewed_user_ids: new_ids } ) |> Map . from_struct ( ) |> Map . delete ( :id )
461+
462+ article
463+ |> Ecto.Changeset . change ( )
464+ |> Ecto.Changeset . put_embed ( :meta , updated_meta )
465+ |> Repo . update ( )
466+ end
467+
468+ defp read_result ( { :ok , % { inc_views: result } } ) , do: result |> done ( )
469+
470+ defp read_result ( { :error , _ , result , _steps } ) do
471+ { :error , result }
472+ end
420473end
0 commit comments