@@ -12,8 +12,9 @@ defmodule GroupherServer.CMS.Delegate.ArticleCommunity do
12
12
alias Helper.Types , as: T
13
13
alias Helper.ORM
14
14
15
- alias GroupherServer.CMS.Model . { Embeds , Community , PinnedArticle }
16
- alias GroupherServer.Repo
15
+ alias GroupherServer . { CMS , Repo }
16
+ alias CMS.Model . { Embeds , Community , PinnedArticle }
17
+ alias CMS.Delegate . { ArticleTag }
17
18
18
19
alias Ecto.Multi
19
20
@@ -58,33 +59,45 @@ defmodule GroupherServer.CMS.Delegate.ArticleCommunity do
58
59
@ doc """
59
60
mirror article to other community
60
61
"""
61
- def mirror_article ( thread , article_id , community_id ) do
62
+ def mirror_article ( thread , article_id , community_id , article_tag_ids \\ [ ] ) do
62
63
with { :ok , info } <- match ( thread ) ,
63
64
{ :ok , article } <- ORM . find ( info . model , article_id , preload: :communities ) ,
64
65
{ :ok , community } <- ORM . find ( Community , community_id ) do
65
- article
66
- |> Ecto.Changeset . change ( )
67
- |> Ecto.Changeset . put_assoc ( :communities , article . communities ++ [ community ] )
68
- |> Repo . update ( )
66
+ Multi . new ( )
67
+ |> Multi . run ( :mirror_target_community , fn _ , _ ->
68
+ article
69
+ |> Ecto.Changeset . change ( )
70
+ |> Ecto.Changeset . put_assoc ( :communities , article . communities ++ [ community ] )
71
+ |> Repo . update ( )
72
+ end )
73
+ |> Multi . run ( :set_target_tags , fn _ , % { mirror_target_community: article } ->
74
+ ArticleTag . set_article_tags ( community , thread , article , % { article_tags: article_tag_ids } )
75
+ end )
76
+ |> Repo . transaction ( )
77
+ |> result ( )
69
78
end
70
79
end
71
80
72
81
@ doc """
73
82
unmirror article to a community
74
83
"""
75
84
def unmirror_article ( thread , article_id , community_id ) do
85
+ preload = [ :communities , :original_community , :article_tags ]
86
+
76
87
with { :ok , info } <- match ( thread ) ,
77
- { :ok , article } <-
78
- ORM . find ( info . model , article_id , preload: [ :communities , :original_community ] ) ,
88
+ { :ok , article } <- ORM . find ( info . model , article_id , preload: preload ) ,
79
89
{ :ok , community } <- ORM . find ( Community , community_id ) do
80
90
case article . original_community . id == community . id do
81
91
true ->
82
92
raise_error ( :mirror_article , "can not unmirror original_community" )
83
93
84
94
false ->
95
+ article_tags = tags_without_community ( article , community )
96
+
85
97
article
86
98
|> Ecto.Changeset . change ( )
87
99
|> Ecto.Changeset . put_assoc ( :communities , article . communities -- [ community ] )
100
+ |> Ecto.Changeset . put_assoc ( :article_tags , article_tags )
88
101
|> Repo . update ( )
89
102
end
90
103
end
@@ -93,40 +106,57 @@ defmodule GroupherServer.CMS.Delegate.ArticleCommunity do
93
106
@ doc """
94
107
move article original community to other community
95
108
"""
96
- def move_article ( thread , article_id , community_id ) do
109
+ def move_article ( thread , article_id , community_id , article_tag_ids \\ [ ] ) do
110
+ preload = [ :communities , :original_community , :article_tags ]
111
+
97
112
with { :ok , info } <- match ( thread ) ,
98
113
{ :ok , community } <- ORM . find ( Community , community_id ) ,
99
- { :ok , article } <-
100
- ORM . find ( info . model , article_id , preload: [ :communities , :original_community ] ) do
101
- cur_original_community = article . original_community
114
+ { :ok , article } <- ORM . find ( info . model , article_id , preload: preload ) do
115
+ original_community = article . original_community
102
116
103
117
Multi . new ( )
104
- |> Multi . run ( :change_original_community , fn _ , _ ->
118
+ |> Multi . run ( :move_article , fn _ , _ ->
119
+ communities = ( article . communities -- [ original_community ] ) ++ [ community ]
120
+ article_tags = tags_without_community ( article , original_community )
121
+
105
122
article
106
123
|> Ecto.Changeset . change ( )
107
124
|> Ecto.Changeset . put_change ( :original_community_id , community . id )
125
+ |> Ecto.Changeset . put_assoc ( :communities , communities )
126
+ |> Ecto.Changeset . put_assoc ( :article_tags , article_tags )
108
127
|> Repo . update ( )
109
128
end )
110
- |> Multi . run ( :unmirror_article , fn _ , % { change_original_community: article } ->
111
- article
112
- |> Ecto.Changeset . change ( )
113
- |> Ecto.Changeset . put_assoc ( :communities , article . communities -- [ cur_original_community ] )
114
- |> Repo . update ( )
129
+ |> Multi . run ( :set_target_tags , fn _ , % { move_article: article } ->
130
+ ArticleTag . set_article_tags ( community , thread , article , % { article_tags: article_tag_ids } )
115
131
end )
116
- |> Multi . run ( :mirror_target_community , fn _ , % { unmirror_article: article } ->
132
+ |> Repo . transaction ( )
133
+ |> result ( )
134
+ end
135
+ end
136
+
137
+ def move_to_blackhole ( thread , article_id , article_tag_ids \\ [ ] ) do
138
+ preload = [ :communities , :original_community , :article_tags ]
139
+
140
+ with { :ok , info } <- match ( thread ) ,
141
+ { :ok , community } <- ORM . find_by ( Community , % { raw: "blackhole" } ) ,
142
+ { :ok , article } <- ORM . find ( info . model , article_id , preload: preload ) do
143
+ Multi . new ( )
144
+ |> Multi . run ( :set_community , fn _ , _ ->
117
145
article
118
146
|> Ecto.Changeset . change ( )
119
- |> Ecto.Changeset . put_assoc ( :communities , article . communities ++ [ community ] )
147
+ |> Ecto.Changeset . put_change ( :original_community_id , community . id )
148
+ |> Ecto.Changeset . put_assoc ( :communities , [ community ] )
149
+ |> Ecto.Changeset . put_assoc ( :article_tags , [ ] )
120
150
|> Repo . update ( )
121
151
end )
152
+ |> Multi . run ( :set_target_tags , fn _ , % { set_community: article } ->
153
+ ArticleTag . set_article_tags ( community , thread , article , % { article_tags: article_tag_ids } )
154
+ end )
122
155
|> Repo . transaction ( )
123
156
|> result ( )
124
157
end
125
158
end
126
159
127
- defp result ( { :ok , % { mirror_target_community: result } } ) , do: result |> done ( )
128
- defp result ( { :error , _ , result , _steps } ) , do: { :error , result }
129
-
130
160
@ doc "update isEdited meta label if needed"
131
161
# TODO: diff history
132
162
def update_edit_status ( % { meta: % Embeds.ArticleMeta { is_edited: _ } = meta } = content ) do
@@ -157,4 +187,14 @@ defmodule GroupherServer.CMS.Delegate.ArticleCommunity do
157
187
_ -> { :ok , :pass }
158
188
end
159
189
end
190
+
191
+ defp tags_without_community ( article , % Community { id: community_id } ) do
192
+ % { article_tags: article_tags } = article
193
+ article_tags -- Enum . filter ( article_tags , & ( & 1 . community_id === community_id ) )
194
+ end
195
+
196
+ defp result ( { :ok , % { set_target_tags: result } } ) , do: result |> done ( )
197
+ defp result ( { :ok , % { mirror_target_community: result } } ) , do: result |> done ( )
198
+
199
+ defp result ( { :error , _ , result , _steps } ) , do: { :error , result }
160
200
end