From 061388379aae8fa5edc2b41a53512f17adc7a672 Mon Sep 17 00:00:00 2001
From: Lunny Xiao <xiaolunwen@gmail.com>
Date: Wed, 25 Sep 2019 01:39:50 +0800
Subject: [PATCH] Move create issue comment to comments package (#8212)

* move create issue comment to comments package

* extract actions on update/delete comment from models to comment service

* fix lint

* fix lint
---
 models/issue_comment.go              | 117 ++-------------------------
 routers/api/v1/repo/issue_comment.go |   7 +-
 routers/repo/issue.go                |   7 +-
 services/comments/comments.go        | 103 +++++++++++++++++++++++
 4 files changed, 117 insertions(+), 117 deletions(-)

diff --git a/models/issue_comment.go b/models/issue_comment.go
index 6786032f41..e8043c1ec7 100644
--- a/models/issue_comment.go
+++ b/models/issue_comment.go
@@ -169,7 +169,7 @@ func (c *Comment) loadIssue(e Engine) (err error) {
 }
 
 func (c *Comment) loadPoster(e Engine) (err error) {
-	if c.Poster != nil {
+	if c.PosterID <= 0 || c.Poster != nil {
 		return nil
 	}
 
@@ -338,21 +338,7 @@ func (c *Comment) LoadMilestone() error {
 
 // LoadPoster loads comment poster
 func (c *Comment) LoadPoster() error {
-	if c.PosterID <= 0 || c.Poster != nil {
-		return nil
-	}
-
-	var err error
-	c.Poster, err = getUserByID(x, c.PosterID)
-	if err != nil {
-		if IsErrUserNotExist(err) {
-			c.PosterID = -1
-			c.Poster = NewGhostUser()
-		} else {
-			log.Error("getUserByID[%d]: %v", c.ID, err)
-		}
-	}
-	return nil
+	return c.loadPoster(x)
 }
 
 // LoadAttachments loads attachments
@@ -440,7 +426,7 @@ func (c *Comment) checkInvalidation(doer *User, repo *git.Repository, branch str
 	}
 	if c.CommitSHA != "" && c.CommitSHA != commit.ID.String() {
 		c.Invalidated = true
-		return UpdateComment(doer, c, "")
+		return UpdateComment(c, doer)
 	}
 	return nil
 }
@@ -811,35 +797,6 @@ func CreateComment(opts *CreateCommentOptions) (comment *Comment, err error) {
 	return comment, nil
 }
 
-// CreateIssueComment creates a plain issue comment.
-func CreateIssueComment(doer *User, repo *Repository, issue *Issue, content string, attachments []string) (*Comment, error) {
-	comment, err := CreateComment(&CreateCommentOptions{
-		Type:        CommentTypeComment,
-		Doer:        doer,
-		Repo:        repo,
-		Issue:       issue,
-		Content:     content,
-		Attachments: attachments,
-	})
-	if err != nil {
-		return nil, fmt.Errorf("CreateComment: %v", err)
-	}
-
-	mode, _ := AccessLevel(doer, repo)
-	if err = PrepareWebhooks(repo, HookEventIssueComment, &api.IssueCommentPayload{
-		Action:     api.HookIssueCommentCreated,
-		Issue:      issue.APIFormat(),
-		Comment:    comment.APIFormat(),
-		Repository: repo.APIFormat(mode),
-		Sender:     doer.APIFormat(),
-	}); err != nil {
-		log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
-	} else {
-		go HookQueue.Add(repo.ID)
-	}
-	return comment, nil
-}
-
 // CreateRefComment creates a commit reference comment to issue.
 func CreateRefComment(doer *User, repo *Repository, issue *Issue, content, commitSHA string) error {
 	if len(commitSHA) == 0 {
@@ -928,7 +885,7 @@ func FindComments(opts FindCommentsOptions) ([]*Comment, error) {
 }
 
 // UpdateComment updates information of comment.
-func UpdateComment(doer *User, c *Comment, oldContent string) error {
+func UpdateComment(c *Comment, doer *User) error {
 	sess := x.NewSession()
 	defer sess.Close()
 	if err := sess.Begin(); err != nil {
@@ -950,38 +907,12 @@ func UpdateComment(doer *User, c *Comment, oldContent string) error {
 	if err := sess.Commit(); err != nil {
 		return fmt.Errorf("Commit: %v", err)
 	}
-	sess.Close()
-
-	if err := c.LoadPoster(); err != nil {
-		return err
-	}
-	if err := c.Issue.LoadAttributes(); err != nil {
-		return err
-	}
-
-	mode, _ := AccessLevel(doer, c.Issue.Repo)
-	if err := PrepareWebhooks(c.Issue.Repo, HookEventIssueComment, &api.IssueCommentPayload{
-		Action:  api.HookIssueCommentEdited,
-		Issue:   c.Issue.APIFormat(),
-		Comment: c.APIFormat(),
-		Changes: &api.ChangesPayload{
-			Body: &api.ChangesFromPayload{
-				From: oldContent,
-			},
-		},
-		Repository: c.Issue.Repo.APIFormat(mode),
-		Sender:     doer.APIFormat(),
-	}); err != nil {
-		log.Error("PrepareWebhooks [comment_id: %d]: %v", c.ID, err)
-	} else {
-		go HookQueue.Add(c.Issue.Repo.ID)
-	}
 
 	return nil
 }
 
 // DeleteComment deletes the comment
-func DeleteComment(doer *User, comment *Comment) error {
+func DeleteComment(comment *Comment, doer *User) error {
 	sess := x.NewSession()
 	defer sess.Close()
 	if err := sess.Begin(); err != nil {
@@ -1007,43 +938,7 @@ func DeleteComment(doer *User, comment *Comment) error {
 		return err
 	}
 
-	if err := sess.Commit(); err != nil {
-		return err
-	}
-	sess.Close()
-
-	if err := comment.LoadPoster(); err != nil {
-		return err
-	}
-	if err := comment.LoadIssue(); err != nil {
-		return err
-	}
-
-	if err := comment.Issue.LoadAttributes(); err != nil {
-		return err
-	}
-	if err := comment.loadPoster(x); err != nil {
-		return err
-	}
-	if err := comment.neuterCrossReferences(x); err != nil {
-		return err
-	}
-
-	mode, _ := AccessLevel(doer, comment.Issue.Repo)
-
-	if err := PrepareWebhooks(comment.Issue.Repo, HookEventIssueComment, &api.IssueCommentPayload{
-		Action:     api.HookIssueCommentDeleted,
-		Issue:      comment.Issue.APIFormat(),
-		Comment:    comment.APIFormat(),
-		Repository: comment.Issue.Repo.APIFormat(mode),
-		Sender:     doer.APIFormat(),
-	}); err != nil {
-		log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
-	} else {
-		go HookQueue.Add(comment.Issue.Repo.ID)
-	}
-
-	return nil
+	return sess.Commit()
 }
 
 // CodeComments represents comments on code by using this structure: FILENAME -> LINE (+ == proposed; - == previous) -> COMMENTS
diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go
index 18fa1d3eb2..60796031a5 100644
--- a/routers/api/v1/repo/issue_comment.go
+++ b/routers/api/v1/repo/issue_comment.go
@@ -12,6 +12,7 @@ import (
 	"code.gitea.io/gitea/modules/context"
 	"code.gitea.io/gitea/modules/notification"
 	api "code.gitea.io/gitea/modules/structs"
+	comment_service "code.gitea.io/gitea/services/comments"
 )
 
 // ListIssueComments list all the comments of an issue
@@ -189,7 +190,7 @@ func CreateIssueComment(ctx *context.APIContext, form api.CreateIssueCommentOpti
 		return
 	}
 
-	comment, err := models.CreateIssueComment(ctx.User, ctx.Repo.Repository, issue, form.Body, nil)
+	comment, err := comment_service.CreateIssueComment(ctx.User, ctx.Repo.Repository, issue, form.Body, nil)
 	if err != nil {
 		ctx.Error(500, "CreateIssueComment", err)
 		return
@@ -299,7 +300,7 @@ func editIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption)
 
 	oldContent := comment.Content
 	comment.Content = form.Body
-	if err := models.UpdateComment(ctx.User, comment, oldContent); err != nil {
+	if err := comment_service.UpdateComment(comment, ctx.User, oldContent); err != nil {
 		ctx.Error(500, "UpdateComment", err)
 		return
 	}
@@ -390,7 +391,7 @@ func deleteIssueComment(ctx *context.APIContext) {
 		return
 	}
 
-	if err = models.DeleteComment(ctx.User, comment); err != nil {
+	if err = comment_service.DeleteComment(comment, ctx.User); err != nil {
 		ctx.Error(500, "DeleteCommentByID", err)
 		return
 	}
diff --git a/routers/repo/issue.go b/routers/repo/issue.go
index b9083e20e9..1be0b408a6 100644
--- a/routers/repo/issue.go
+++ b/routers/repo/issue.go
@@ -26,6 +26,7 @@ import (
 	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/modules/util"
+	comment_service "code.gitea.io/gitea/services/comments"
 	milestone_service "code.gitea.io/gitea/services/milestone"
 
 	"github.com/unknwon/com"
@@ -1299,7 +1300,7 @@ func NewComment(ctx *context.Context, form auth.CreateCommentForm) {
 		return
 	}
 
-	comment, err := models.CreateIssueComment(ctx.User, ctx.Repo.Repository, issue, form.Content, attachments)
+	comment, err := comment_service.CreateIssueComment(ctx.User, ctx.Repo.Repository, issue, form.Content, attachments)
 	if err != nil {
 		ctx.ServerError("CreateIssueComment", err)
 		return
@@ -1339,7 +1340,7 @@ func UpdateCommentContent(ctx *context.Context) {
 		})
 		return
 	}
-	if err = models.UpdateComment(ctx.User, comment, oldContent); err != nil {
+	if err = comment_service.UpdateComment(comment, ctx.User, oldContent); err != nil {
 		ctx.ServerError("UpdateComment", err)
 		return
 	}
@@ -1372,7 +1373,7 @@ func DeleteComment(ctx *context.Context) {
 		return
 	}
 
-	if err = models.DeleteComment(ctx.User, comment); err != nil {
+	if err = models.DeleteComment(comment, ctx.User); err != nil {
 		ctx.ServerError("DeleteCommentByID", err)
 		return
 	}
diff --git a/services/comments/comments.go b/services/comments/comments.go
index bd261ff0a5..e8448e9065 100644
--- a/services/comments/comments.go
+++ b/services/comments/comments.go
@@ -11,10 +11,41 @@ import (
 
 	"code.gitea.io/gitea/models"
 	"code.gitea.io/gitea/modules/git"
+	"code.gitea.io/gitea/modules/log"
 	"code.gitea.io/gitea/modules/setting"
+	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/services/gitdiff"
 )
 
+// CreateIssueComment creates a plain issue comment.
+func CreateIssueComment(doer *models.User, repo *models.Repository, issue *models.Issue, content string, attachments []string) (*models.Comment, error) {
+	comment, err := models.CreateComment(&models.CreateCommentOptions{
+		Type:        models.CommentTypeComment,
+		Doer:        doer,
+		Repo:        repo,
+		Issue:       issue,
+		Content:     content,
+		Attachments: attachments,
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	mode, _ := models.AccessLevel(doer, repo)
+	if err = models.PrepareWebhooks(repo, models.HookEventIssueComment, &api.IssueCommentPayload{
+		Action:     api.HookIssueCommentCreated,
+		Issue:      issue.APIFormat(),
+		Comment:    comment.APIFormat(),
+		Repository: repo.APIFormat(mode),
+		Sender:     doer.APIFormat(),
+	}); err != nil {
+		log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
+	} else {
+		go models.HookQueue.Add(repo.ID)
+	}
+	return comment, nil
+}
+
 // CreateCodeComment creates a plain code comment at the specified line / path
 func CreateCodeComment(doer *models.User, repo *models.Repository, issue *models.Issue, content, treePath string, line, reviewID int64) (*models.Comment, error) {
 	var commitID, patch string
@@ -67,3 +98,75 @@ func CreateCodeComment(doer *models.User, repo *models.Repository, issue *models
 		Patch:     patch,
 	})
 }
+
+// UpdateComment updates information of comment.
+func UpdateComment(c *models.Comment, doer *models.User, oldContent string) error {
+	if err := models.UpdateComment(c, doer); err != nil {
+		return err
+	}
+
+	if err := c.LoadPoster(); err != nil {
+		return err
+	}
+	if err := c.LoadIssue(); err != nil {
+		return err
+	}
+
+	if err := c.Issue.LoadAttributes(); err != nil {
+		return err
+	}
+
+	mode, _ := models.AccessLevel(doer, c.Issue.Repo)
+	if err := models.PrepareWebhooks(c.Issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{
+		Action:  api.HookIssueCommentEdited,
+		Issue:   c.Issue.APIFormat(),
+		Comment: c.APIFormat(),
+		Changes: &api.ChangesPayload{
+			Body: &api.ChangesFromPayload{
+				From: oldContent,
+			},
+		},
+		Repository: c.Issue.Repo.APIFormat(mode),
+		Sender:     doer.APIFormat(),
+	}); err != nil {
+		log.Error("PrepareWebhooks [comment_id: %d]: %v", c.ID, err)
+	} else {
+		go models.HookQueue.Add(c.Issue.Repo.ID)
+	}
+
+	return nil
+}
+
+// DeleteComment deletes the comment
+func DeleteComment(comment *models.Comment, doer *models.User) error {
+	if err := models.DeleteComment(comment, doer); err != nil {
+		return err
+	}
+
+	if err := comment.LoadPoster(); err != nil {
+		return err
+	}
+	if err := comment.LoadIssue(); err != nil {
+		return err
+	}
+
+	if err := comment.Issue.LoadAttributes(); err != nil {
+		return err
+	}
+
+	mode, _ := models.AccessLevel(doer, comment.Issue.Repo)
+
+	if err := models.PrepareWebhooks(comment.Issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{
+		Action:     api.HookIssueCommentDeleted,
+		Issue:      comment.Issue.APIFormat(),
+		Comment:    comment.APIFormat(),
+		Repository: comment.Issue.Repo.APIFormat(mode),
+		Sender:     doer.APIFormat(),
+	}); err != nil {
+		log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
+	} else {
+		go models.HookQueue.Add(comment.Issue.Repo.ID)
+	}
+
+	return nil
+}