mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	Move reaction to models/issues/ (#19264)
* Move reaction to models/issues/ * Fix test * move the function * improve code * Update models/issues/reaction.go Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
		@@ -10,6 +10,7 @@ import (
 | 
			
		||||
	"code.gitea.io/gitea/models/db"
 | 
			
		||||
	repo_model "code.gitea.io/gitea/models/repo"
 | 
			
		||||
	user_model "code.gitea.io/gitea/models/user"
 | 
			
		||||
	"code.gitea.io/gitea/modules/container"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ActionList defines a list of actions
 | 
			
		||||
@@ -22,7 +23,7 @@ func (actions ActionList) getUserIDs() []int64 {
 | 
			
		||||
			userIDs[action.ActUserID] = struct{}{}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return keysInt64(userIDs)
 | 
			
		||||
	return container.KeysInt64(userIDs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (actions ActionList) loadUsers(e db.Engine) (map[int64]*user_model.User, error) {
 | 
			
		||||
@@ -52,7 +53,7 @@ func (actions ActionList) getRepoIDs() []int64 {
 | 
			
		||||
			repoIDs[action.RepoID] = struct{}{}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return keysInt64(repoIDs)
 | 
			
		||||
	return container.KeysInt64(repoIDs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (actions ActionList) loadRepositories(e db.Engine) error {
 | 
			
		||||
 
 | 
			
		||||
@@ -765,36 +765,6 @@ func (err ErrPullWasClosed) Error() string {
 | 
			
		||||
	return fmt.Sprintf("Pull request [%d] %d was already closed", err.ID, err.Index)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrForbiddenIssueReaction is used when a forbidden reaction was try to created
 | 
			
		||||
type ErrForbiddenIssueReaction struct {
 | 
			
		||||
	Reaction string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsErrForbiddenIssueReaction checks if an error is a ErrForbiddenIssueReaction.
 | 
			
		||||
func IsErrForbiddenIssueReaction(err error) bool {
 | 
			
		||||
	_, ok := err.(ErrForbiddenIssueReaction)
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (err ErrForbiddenIssueReaction) Error() string {
 | 
			
		||||
	return fmt.Sprintf("'%s' is not an allowed reaction", err.Reaction)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrReactionAlreadyExist is used when a existing reaction was try to created
 | 
			
		||||
type ErrReactionAlreadyExist struct {
 | 
			
		||||
	Reaction string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsErrReactionAlreadyExist checks if an error is a ErrReactionAlreadyExist.
 | 
			
		||||
func IsErrReactionAlreadyExist(err error) bool {
 | 
			
		||||
	_, ok := err.(ErrReactionAlreadyExist)
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (err ErrReactionAlreadyExist) Error() string {
 | 
			
		||||
	return fmt.Sprintf("reaction '%s' already exists", err.Reaction)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// __________      .__  .__ __________                                     __
 | 
			
		||||
// \______   \__ __|  | |  |\______   \ ____  ________ __   ____   _______/  |_
 | 
			
		||||
//  |     ___/  |  \  | |  | |       _// __ \/ ____/  |  \_/ __ \ /  ___/\   __\
 | 
			
		||||
 
 | 
			
		||||
@@ -6,17 +6,8 @@ package models
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	repo_model "code.gitea.io/gitea/models/repo"
 | 
			
		||||
	user_model "code.gitea.io/gitea/models/user"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func keysInt64(m map[int64]struct{}) []int64 {
 | 
			
		||||
	keys := make([]int64, 0, len(m))
 | 
			
		||||
	for k := range m {
 | 
			
		||||
		keys = append(keys, k)
 | 
			
		||||
	}
 | 
			
		||||
	return keys
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func valuesRepository(m map[int64]*repo_model.Repository) []*repo_model.Repository {
 | 
			
		||||
	values := make([]*repo_model.Repository, 0, len(m))
 | 
			
		||||
	for _, v := range m {
 | 
			
		||||
@@ -24,11 +15,3 @@ func valuesRepository(m map[int64]*repo_model.Repository) []*repo_model.Reposito
 | 
			
		||||
	}
 | 
			
		||||
	return values
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func valuesUser(m map[int64]*user_model.User) []*user_model.User {
 | 
			
		||||
	values := make([]*user_model.User, 0, len(m))
 | 
			
		||||
	for _, v := range m {
 | 
			
		||||
		values = append(values, v)
 | 
			
		||||
	}
 | 
			
		||||
	return values
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -72,7 +72,7 @@ type Issue struct {
 | 
			
		||||
 | 
			
		||||
	Attachments      []*repo_model.Attachment           `xorm:"-"`
 | 
			
		||||
	Comments         []*Comment                         `xorm:"-"`
 | 
			
		||||
	Reactions        ReactionList                       `xorm:"-"`
 | 
			
		||||
	Reactions        issues.ReactionList                `xorm:"-"`
 | 
			
		||||
	TotalTrackedTime int64                              `xorm:"-"`
 | 
			
		||||
	Assignees        []*user_model.User                 `xorm:"-"`
 | 
			
		||||
	ForeignReference *foreignreference.ForeignReference `xorm:"-"`
 | 
			
		||||
@@ -244,8 +244,7 @@ func (issue *Issue) loadReactions(ctx context.Context) (err error) {
 | 
			
		||||
	if issue.Reactions != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	e := db.GetEngine(ctx)
 | 
			
		||||
	reactions, _, err := findReactions(e, FindReactionsOptions{
 | 
			
		||||
	reactions, _, err := issues.FindReactions(ctx, issues.FindReactionsOptions{
 | 
			
		||||
		IssueID: issue.ID,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -255,7 +254,7 @@ func (issue *Issue) loadReactions(ctx context.Context) (err error) {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	// Load reaction user data
 | 
			
		||||
	if _, err := ReactionList(reactions).loadUsers(e, issue.Repo); err != nil {
 | 
			
		||||
	if _, err := issues.ReactionList(reactions).LoadUsers(ctx, issue.Repo); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -2111,7 +2110,7 @@ func deleteIssue(ctx context.Context, issue *Issue) error {
 | 
			
		||||
		&IssueAssignees{},
 | 
			
		||||
		&IssueUser{},
 | 
			
		||||
		&Notification{},
 | 
			
		||||
		&Reaction{},
 | 
			
		||||
		&issues.Reaction{},
 | 
			
		||||
		&IssueWatch{},
 | 
			
		||||
		&Stopwatch{},
 | 
			
		||||
		&TrackedTime{},
 | 
			
		||||
@@ -2429,7 +2428,7 @@ func deleteIssuesByRepoID(sess db.Engine, repoID int64) (attachmentPaths []strin
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if _, err = sess.In("issue_id", deleteCond).
 | 
			
		||||
		Delete(&Reaction{}); err != nil {
 | 
			
		||||
		Delete(&issues.Reaction{}); err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -244,7 +244,7 @@ type Comment struct {
 | 
			
		||||
	CommitSHA string `xorm:"VARCHAR(40)"`
 | 
			
		||||
 | 
			
		||||
	Attachments []*repo_model.Attachment `xorm:"-"`
 | 
			
		||||
	Reactions   ReactionList             `xorm:"-"`
 | 
			
		||||
	Reactions   issues.ReactionList      `xorm:"-"`
 | 
			
		||||
 | 
			
		||||
	// For view issue page.
 | 
			
		||||
	ShowRole RoleDescriptor `xorm:"-"`
 | 
			
		||||
@@ -631,11 +631,11 @@ func (c *Comment) LoadTime() error {
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Comment) loadReactions(e db.Engine, repo *repo_model.Repository) (err error) {
 | 
			
		||||
func (c *Comment) loadReactions(ctx context.Context, repo *repo_model.Repository) (err error) {
 | 
			
		||||
	if c.Reactions != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	c.Reactions, _, err = findReactions(e, FindReactionsOptions{
 | 
			
		||||
	c.Reactions, _, err = issues.FindReactions(ctx, issues.FindReactionsOptions{
 | 
			
		||||
		IssueID:   c.IssueID,
 | 
			
		||||
		CommentID: c.ID,
 | 
			
		||||
	})
 | 
			
		||||
@@ -643,7 +643,7 @@ func (c *Comment) loadReactions(e db.Engine, repo *repo_model.Repository) (err e
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	// Load reaction user data
 | 
			
		||||
	if _, err := c.Reactions.loadUsers(e, repo); err != nil {
 | 
			
		||||
	if _, err := c.Reactions.LoadUsers(ctx, repo); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
@@ -651,7 +651,7 @@ func (c *Comment) loadReactions(e db.Engine, repo *repo_model.Repository) (err e
 | 
			
		||||
 | 
			
		||||
// LoadReactions loads comment reactions
 | 
			
		||||
func (c *Comment) LoadReactions(repo *repo_model.Repository) error {
 | 
			
		||||
	return c.loadReactions(db.GetEngine(db.DefaultContext), repo)
 | 
			
		||||
	return c.loadReactions(db.DefaultContext, repo)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Comment) loadReview(e db.Engine) (err error) {
 | 
			
		||||
@@ -1146,14 +1146,15 @@ func DeleteComment(comment *Comment) error {
 | 
			
		||||
	}
 | 
			
		||||
	defer committer.Close()
 | 
			
		||||
 | 
			
		||||
	if err := deleteComment(db.GetEngine(ctx), comment); err != nil {
 | 
			
		||||
	if err := deleteComment(ctx, comment); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return committer.Commit()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func deleteComment(e db.Engine, comment *Comment) error {
 | 
			
		||||
func deleteComment(ctx context.Context, comment *Comment) error {
 | 
			
		||||
	e := db.GetEngine(ctx)
 | 
			
		||||
	if _, err := e.ID(comment.ID).NoAutoCondition().Delete(comment); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@@ -1177,7 +1178,7 @@ func deleteComment(e db.Engine, comment *Comment) error {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return deleteReaction(e, &ReactionOptions{Comment: comment})
 | 
			
		||||
	return issues.DeleteReaction(ctx, &issues.ReactionOptions{CommentID: comment.ID})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CodeComments represents comments on code by using this structure: FILENAME -> LINE (+ == proposed; - == previous) -> COMMENTS
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@ import (
 | 
			
		||||
	"code.gitea.io/gitea/models/db"
 | 
			
		||||
	repo_model "code.gitea.io/gitea/models/repo"
 | 
			
		||||
	user_model "code.gitea.io/gitea/models/user"
 | 
			
		||||
	"code.gitea.io/gitea/modules/container"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CommentList defines a list of comments
 | 
			
		||||
@@ -22,7 +23,7 @@ func (comments CommentList) getPosterIDs() []int64 {
 | 
			
		||||
			posterIDs[comment.PosterID] = struct{}{}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return keysInt64(posterIDs)
 | 
			
		||||
	return container.KeysInt64(posterIDs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (comments CommentList) loadPosters(e db.Engine) error {
 | 
			
		||||
@@ -75,7 +76,7 @@ func (comments CommentList) getLabelIDs() []int64 {
 | 
			
		||||
			ids[comment.LabelID] = struct{}{}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return keysInt64(ids)
 | 
			
		||||
	return container.KeysInt64(ids)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (comments CommentList) loadLabels(e db.Engine) error {
 | 
			
		||||
@@ -125,7 +126,7 @@ func (comments CommentList) getMilestoneIDs() []int64 {
 | 
			
		||||
			ids[comment.MilestoneID] = struct{}{}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return keysInt64(ids)
 | 
			
		||||
	return container.KeysInt64(ids)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (comments CommentList) loadMilestones(e db.Engine) error {
 | 
			
		||||
@@ -168,7 +169,7 @@ func (comments CommentList) getOldMilestoneIDs() []int64 {
 | 
			
		||||
			ids[comment.OldMilestoneID] = struct{}{}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return keysInt64(ids)
 | 
			
		||||
	return container.KeysInt64(ids)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (comments CommentList) loadOldMilestones(e db.Engine) error {
 | 
			
		||||
@@ -211,7 +212,7 @@ func (comments CommentList) getAssigneeIDs() []int64 {
 | 
			
		||||
			ids[comment.AssigneeID] = struct{}{}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return keysInt64(ids)
 | 
			
		||||
	return container.KeysInt64(ids)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (comments CommentList) loadAssignees(e db.Engine) error {
 | 
			
		||||
@@ -267,7 +268,7 @@ func (comments CommentList) getIssueIDs() []int64 {
 | 
			
		||||
			ids[comment.IssueID] = struct{}{}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return keysInt64(ids)
 | 
			
		||||
	return container.KeysInt64(ids)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Issues returns all the issues of comments
 | 
			
		||||
@@ -342,7 +343,7 @@ func (comments CommentList) getDependentIssueIDs() []int64 {
 | 
			
		||||
			ids[comment.DependentIssueID] = struct{}{}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return keysInt64(ids)
 | 
			
		||||
	return container.KeysInt64(ids)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (comments CommentList) loadDependentIssues(ctx context.Context) error {
 | 
			
		||||
@@ -444,7 +445,7 @@ func (comments CommentList) getReviewIDs() []int64 {
 | 
			
		||||
			ids[comment.ReviewID] = struct{}{}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return keysInt64(ids)
 | 
			
		||||
	return container.KeysInt64(ids)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (comments CommentList) loadReviews(e db.Engine) error {
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@ import (
 | 
			
		||||
	"code.gitea.io/gitea/models/db"
 | 
			
		||||
	repo_model "code.gitea.io/gitea/models/repo"
 | 
			
		||||
	user_model "code.gitea.io/gitea/models/user"
 | 
			
		||||
	"code.gitea.io/gitea/modules/container"
 | 
			
		||||
 | 
			
		||||
	"xorm.io/builder"
 | 
			
		||||
)
 | 
			
		||||
@@ -32,7 +33,7 @@ func (issues IssueList) getRepoIDs() []int64 {
 | 
			
		||||
			repoIDs[issue.RepoID] = struct{}{}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return keysInt64(repoIDs)
 | 
			
		||||
	return container.KeysInt64(repoIDs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (issues IssueList) loadRepositories(e db.Engine) ([]*repo_model.Repository, error) {
 | 
			
		||||
@@ -83,7 +84,7 @@ func (issues IssueList) getPosterIDs() []int64 {
 | 
			
		||||
			posterIDs[issue.PosterID] = struct{}{}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return keysInt64(posterIDs)
 | 
			
		||||
	return container.KeysInt64(posterIDs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (issues IssueList) loadPosters(e db.Engine) error {
 | 
			
		||||
@@ -189,7 +190,7 @@ func (issues IssueList) getMilestoneIDs() []int64 {
 | 
			
		||||
			ids[issue.MilestoneID] = struct{}{}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return keysInt64(ids)
 | 
			
		||||
	return container.KeysInt64(ids)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (issues IssueList) loadMilestones(e db.Engine) error {
 | 
			
		||||
 
 | 
			
		||||
@@ -9,8 +9,18 @@ import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models/unittest"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestMain(m *testing.M) {
 | 
			
		||||
	unittest.MainTest(m, filepath.Join("..", ".."), "")
 | 
			
		||||
func init() {
 | 
			
		||||
	setting.SetCustomPathAndConf("", "", "")
 | 
			
		||||
	setting.LoadForTest()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMain(m *testing.M) {
 | 
			
		||||
	unittest.MainTest(m, filepath.Join("..", ".."),
 | 
			
		||||
		"reaction.yml",
 | 
			
		||||
		"user.yml",
 | 
			
		||||
		"repository.yml",
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,21 +2,53 @@
 | 
			
		||||
// Use of this source code is governed by a MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package models
 | 
			
		||||
package issues
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"context"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models/db"
 | 
			
		||||
	repo_model "code.gitea.io/gitea/models/repo"
 | 
			
		||||
	user_model "code.gitea.io/gitea/models/user"
 | 
			
		||||
	"code.gitea.io/gitea/modules/container"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
	"code.gitea.io/gitea/modules/timeutil"
 | 
			
		||||
 | 
			
		||||
	"xorm.io/builder"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ErrForbiddenIssueReaction is used when a forbidden reaction was try to created
 | 
			
		||||
type ErrForbiddenIssueReaction struct {
 | 
			
		||||
	Reaction string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsErrForbiddenIssueReaction checks if an error is a ErrForbiddenIssueReaction.
 | 
			
		||||
func IsErrForbiddenIssueReaction(err error) bool {
 | 
			
		||||
	_, ok := err.(ErrForbiddenIssueReaction)
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (err ErrForbiddenIssueReaction) Error() string {
 | 
			
		||||
	return fmt.Sprintf("'%s' is not an allowed reaction", err.Reaction)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrReactionAlreadyExist is used when a existing reaction was try to created
 | 
			
		||||
type ErrReactionAlreadyExist struct {
 | 
			
		||||
	Reaction string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsErrReactionAlreadyExist checks if an error is a ErrReactionAlreadyExist.
 | 
			
		||||
func IsErrReactionAlreadyExist(err error) bool {
 | 
			
		||||
	_, ok := err.(ErrReactionAlreadyExist)
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (err ErrReactionAlreadyExist) Error() string {
 | 
			
		||||
	return fmt.Sprintf("reaction '%s' already exists", err.Reaction)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Reaction represents a reactions on issues and comments.
 | 
			
		||||
type Reaction struct {
 | 
			
		||||
	ID               int64              `xorm:"pk autoincr"`
 | 
			
		||||
@@ -30,6 +62,36 @@ type Reaction struct {
 | 
			
		||||
	CreatedUnix      timeutil.TimeStamp `xorm:"INDEX created"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LoadUser load user of reaction
 | 
			
		||||
func (r *Reaction) LoadUser() (*user_model.User, error) {
 | 
			
		||||
	if r.User != nil {
 | 
			
		||||
		return r.User, nil
 | 
			
		||||
	}
 | 
			
		||||
	user, err := user_model.GetUserByIDCtx(db.DefaultContext, r.UserID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	r.User = user
 | 
			
		||||
	return user, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RemapExternalUser ExternalUserRemappable interface
 | 
			
		||||
func (r *Reaction) RemapExternalUser(externalName string, externalID, userID int64) error {
 | 
			
		||||
	r.OriginalAuthor = externalName
 | 
			
		||||
	r.OriginalAuthorID = externalID
 | 
			
		||||
	r.UserID = userID
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetUserID ExternalUserRemappable interface
 | 
			
		||||
func (r *Reaction) GetUserID() int64 { return r.UserID }
 | 
			
		||||
 | 
			
		||||
// GetExternalName ExternalUserRemappable interface
 | 
			
		||||
func (r *Reaction) GetExternalName() string { return r.OriginalAuthor }
 | 
			
		||||
 | 
			
		||||
// GetExternalID ExternalUserRemappable interface
 | 
			
		||||
func (r *Reaction) GetExternalID() int64 { return r.OriginalAuthorID }
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	db.RegisterModel(new(Reaction))
 | 
			
		||||
}
 | 
			
		||||
@@ -71,24 +133,25 @@ func (opts *FindReactionsOptions) toConds() builder.Cond {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FindCommentReactions returns a ReactionList of all reactions from an comment
 | 
			
		||||
func FindCommentReactions(comment *Comment) (ReactionList, int64, error) {
 | 
			
		||||
	return findReactions(db.GetEngine(db.DefaultContext), FindReactionsOptions{
 | 
			
		||||
		IssueID:   comment.IssueID,
 | 
			
		||||
		CommentID: comment.ID,
 | 
			
		||||
func FindCommentReactions(issueID, commentID int64) (ReactionList, int64, error) {
 | 
			
		||||
	return FindReactions(db.DefaultContext, FindReactionsOptions{
 | 
			
		||||
		IssueID:   issueID,
 | 
			
		||||
		CommentID: commentID,
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FindIssueReactions returns a ReactionList of all reactions from an issue
 | 
			
		||||
func FindIssueReactions(issue *Issue, listOptions db.ListOptions) (ReactionList, int64, error) {
 | 
			
		||||
	return findReactions(db.GetEngine(db.DefaultContext), FindReactionsOptions{
 | 
			
		||||
func FindIssueReactions(issueID int64, listOptions db.ListOptions) (ReactionList, int64, error) {
 | 
			
		||||
	return FindReactions(db.DefaultContext, FindReactionsOptions{
 | 
			
		||||
		ListOptions: listOptions,
 | 
			
		||||
		IssueID:     issue.ID,
 | 
			
		||||
		IssueID:     issueID,
 | 
			
		||||
		CommentID:   -1,
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func findReactions(e db.Engine, opts FindReactionsOptions) ([]*Reaction, int64, error) {
 | 
			
		||||
	sess := e.
 | 
			
		||||
// FindReactions returns a ReactionList of all reactions from an issue or a comment
 | 
			
		||||
func FindReactions(ctx context.Context, opts FindReactionsOptions) (ReactionList, int64, error) {
 | 
			
		||||
	sess := db.GetEngine(ctx).
 | 
			
		||||
		Where(opts.toConds()).
 | 
			
		||||
		In("reaction.`type`", setting.UI.Reactions).
 | 
			
		||||
		Asc("reaction.issue_id", "reaction.comment_id", "reaction.created_unix", "reaction.id")
 | 
			
		||||
@@ -105,24 +168,21 @@ func findReactions(e db.Engine, opts FindReactionsOptions) ([]*Reaction, int64,
 | 
			
		||||
	return reactions, count, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func createReaction(e db.Engine, opts *ReactionOptions) (*Reaction, error) {
 | 
			
		||||
func createReaction(ctx context.Context, opts *ReactionOptions) (*Reaction, error) {
 | 
			
		||||
	reaction := &Reaction{
 | 
			
		||||
		Type:    opts.Type,
 | 
			
		||||
		UserID:  opts.Doer.ID,
 | 
			
		||||
		IssueID: opts.Issue.ID,
 | 
			
		||||
		Type:      opts.Type,
 | 
			
		||||
		UserID:    opts.DoerID,
 | 
			
		||||
		IssueID:   opts.IssueID,
 | 
			
		||||
		CommentID: opts.CommentID,
 | 
			
		||||
	}
 | 
			
		||||
	findOpts := FindReactionsOptions{
 | 
			
		||||
		IssueID:   opts.Issue.ID,
 | 
			
		||||
		CommentID: -1, // reaction to issue only
 | 
			
		||||
		IssueID:   opts.IssueID,
 | 
			
		||||
		CommentID: opts.CommentID,
 | 
			
		||||
		Reaction:  opts.Type,
 | 
			
		||||
		UserID:    opts.Doer.ID,
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Comment != nil {
 | 
			
		||||
		reaction.CommentID = opts.Comment.ID
 | 
			
		||||
		findOpts.CommentID = opts.Comment.ID
 | 
			
		||||
		UserID:    opts.DoerID,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	existingR, _, err := findReactions(e, findOpts)
 | 
			
		||||
	existingR, _, err := FindReactions(ctx, findOpts)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -130,7 +190,7 @@ func createReaction(e db.Engine, opts *ReactionOptions) (*Reaction, error) {
 | 
			
		||||
		return existingR[0], ErrReactionAlreadyExist{Reaction: opts.Type}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if _, err := e.Insert(reaction); err != nil {
 | 
			
		||||
	if err := db.Insert(ctx, reaction); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -139,10 +199,10 @@ func createReaction(e db.Engine, opts *ReactionOptions) (*Reaction, error) {
 | 
			
		||||
 | 
			
		||||
// ReactionOptions defines options for creating or deleting reactions
 | 
			
		||||
type ReactionOptions struct {
 | 
			
		||||
	Type    string
 | 
			
		||||
	Doer    *user_model.User
 | 
			
		||||
	Issue   *Issue
 | 
			
		||||
	Comment *Comment
 | 
			
		||||
	Type      string
 | 
			
		||||
	DoerID    int64
 | 
			
		||||
	IssueID   int64
 | 
			
		||||
	CommentID int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateReaction creates reaction for issue or comment.
 | 
			
		||||
@@ -157,7 +217,7 @@ func CreateReaction(opts *ReactionOptions) (*Reaction, error) {
 | 
			
		||||
	}
 | 
			
		||||
	defer committer.Close()
 | 
			
		||||
 | 
			
		||||
	reaction, err := createReaction(db.GetEngine(ctx), opts)
 | 
			
		||||
	reaction, err := createReaction(ctx, opts)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return reaction, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -169,88 +229,56 @@ func CreateReaction(opts *ReactionOptions) (*Reaction, error) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateIssueReaction creates a reaction on issue.
 | 
			
		||||
func CreateIssueReaction(doer *user_model.User, issue *Issue, content string) (*Reaction, error) {
 | 
			
		||||
func CreateIssueReaction(doerID, issueID int64, content string) (*Reaction, error) {
 | 
			
		||||
	return CreateReaction(&ReactionOptions{
 | 
			
		||||
		Type:  content,
 | 
			
		||||
		Doer:  doer,
 | 
			
		||||
		Issue: issue,
 | 
			
		||||
		Type:    content,
 | 
			
		||||
		DoerID:  doerID,
 | 
			
		||||
		IssueID: issueID,
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateCommentReaction creates a reaction on comment.
 | 
			
		||||
func CreateCommentReaction(doer *user_model.User, issue *Issue, comment *Comment, content string) (*Reaction, error) {
 | 
			
		||||
func CreateCommentReaction(doerID, issueID, commentID int64, content string) (*Reaction, error) {
 | 
			
		||||
	return CreateReaction(&ReactionOptions{
 | 
			
		||||
		Type:    content,
 | 
			
		||||
		Doer:    doer,
 | 
			
		||||
		Issue:   issue,
 | 
			
		||||
		Comment: comment,
 | 
			
		||||
		Type:      content,
 | 
			
		||||
		DoerID:    doerID,
 | 
			
		||||
		IssueID:   issueID,
 | 
			
		||||
		CommentID: commentID,
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func deleteReaction(e db.Engine, opts *ReactionOptions) error {
 | 
			
		||||
// DeleteReaction deletes reaction for issue or comment.
 | 
			
		||||
func DeleteReaction(ctx context.Context, opts *ReactionOptions) error {
 | 
			
		||||
	reaction := &Reaction{
 | 
			
		||||
		Type: opts.Type,
 | 
			
		||||
		Type:      opts.Type,
 | 
			
		||||
		UserID:    opts.DoerID,
 | 
			
		||||
		IssueID:   opts.IssueID,
 | 
			
		||||
		CommentID: opts.CommentID,
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Doer != nil {
 | 
			
		||||
		reaction.UserID = opts.Doer.ID
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Issue != nil {
 | 
			
		||||
		reaction.IssueID = opts.Issue.ID
 | 
			
		||||
	}
 | 
			
		||||
	if opts.Comment != nil {
 | 
			
		||||
		reaction.CommentID = opts.Comment.ID
 | 
			
		||||
	}
 | 
			
		||||
	_, err := e.Where("original_author_id = 0").Delete(reaction)
 | 
			
		||||
 | 
			
		||||
	_, err := db.GetEngine(ctx).Where("original_author_id = 0").Delete(reaction)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteReaction deletes reaction for issue or comment.
 | 
			
		||||
func DeleteReaction(opts *ReactionOptions) error {
 | 
			
		||||
	ctx, committer, err := db.TxContext()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer committer.Close()
 | 
			
		||||
 | 
			
		||||
	if err := deleteReaction(db.GetEngine(ctx), opts); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return committer.Commit()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteIssueReaction deletes a reaction on issue.
 | 
			
		||||
func DeleteIssueReaction(doer *user_model.User, issue *Issue, content string) error {
 | 
			
		||||
	return DeleteReaction(&ReactionOptions{
 | 
			
		||||
		Type:  content,
 | 
			
		||||
		Doer:  doer,
 | 
			
		||||
		Issue: issue,
 | 
			
		||||
func DeleteIssueReaction(doerID, issueID int64, content string) error {
 | 
			
		||||
	return DeleteReaction(db.DefaultContext, &ReactionOptions{
 | 
			
		||||
		Type:    content,
 | 
			
		||||
		DoerID:  doerID,
 | 
			
		||||
		IssueID: issueID,
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteCommentReaction deletes a reaction on comment.
 | 
			
		||||
func DeleteCommentReaction(doer *user_model.User, issue *Issue, comment *Comment, content string) error {
 | 
			
		||||
	return DeleteReaction(&ReactionOptions{
 | 
			
		||||
		Type:    content,
 | 
			
		||||
		Doer:    doer,
 | 
			
		||||
		Issue:   issue,
 | 
			
		||||
		Comment: comment,
 | 
			
		||||
func DeleteCommentReaction(doerID, issueID, commentID int64, content string) error {
 | 
			
		||||
	return DeleteReaction(db.DefaultContext, &ReactionOptions{
 | 
			
		||||
		Type:      content,
 | 
			
		||||
		DoerID:    doerID,
 | 
			
		||||
		IssueID:   issueID,
 | 
			
		||||
		CommentID: commentID,
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LoadUser load user of reaction
 | 
			
		||||
func (r *Reaction) LoadUser() (*user_model.User, error) {
 | 
			
		||||
	if r.User != nil {
 | 
			
		||||
		return r.User, nil
 | 
			
		||||
	}
 | 
			
		||||
	user, err := user_model.GetUserByIDCtx(db.DefaultContext, r.UserID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	r.User = user
 | 
			
		||||
	return user, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReactionList represents list of reactions
 | 
			
		||||
type ReactionList []*Reaction
 | 
			
		||||
 | 
			
		||||
@@ -286,17 +314,26 @@ func (list ReactionList) getUserIDs() []int64 {
 | 
			
		||||
			userIDs[reaction.UserID] = struct{}{}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return keysInt64(userIDs)
 | 
			
		||||
	return container.KeysInt64(userIDs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (list ReactionList) loadUsers(e db.Engine, repo *repo_model.Repository) ([]*user_model.User, error) {
 | 
			
		||||
func valuesUser(m map[int64]*user_model.User) []*user_model.User {
 | 
			
		||||
	values := make([]*user_model.User, 0, len(m))
 | 
			
		||||
	for _, v := range m {
 | 
			
		||||
		values = append(values, v)
 | 
			
		||||
	}
 | 
			
		||||
	return values
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LoadUsers loads reactions' all users
 | 
			
		||||
func (list ReactionList) LoadUsers(ctx context.Context, repo *repo_model.Repository) ([]*user_model.User, error) {
 | 
			
		||||
	if len(list) == 0 {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	userIDs := list.getUserIDs()
 | 
			
		||||
	userMaps := make(map[int64]*user_model.User, len(userIDs))
 | 
			
		||||
	err := e.
 | 
			
		||||
	err := db.GetEngine(ctx).
 | 
			
		||||
		In("id", userIDs).
 | 
			
		||||
		Find(&userMaps)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -315,11 +352,6 @@ func (list ReactionList) loadUsers(e db.Engine, repo *repo_model.Repository) ([]
 | 
			
		||||
	return valuesUser(userMaps), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LoadUsers loads reactions' all users
 | 
			
		||||
func (list ReactionList) LoadUsers(repo *repo_model.Repository) ([]*user_model.User, error) {
 | 
			
		||||
	return list.loadUsers(db.GetEngine(db.DefaultContext), repo)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetFirstUsers returns first reacted user display names separated by comma
 | 
			
		||||
func (list ReactionList) GetFirstUsers() string {
 | 
			
		||||
	var buffer bytes.Buffer
 | 
			
		||||
@@ -343,20 +375,3 @@ func (list ReactionList) GetMoreUserCount() int {
 | 
			
		||||
	}
 | 
			
		||||
	return len(list) - setting.UI.ReactionMaxUserNum
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RemapExternalUser ExternalUserRemappable interface
 | 
			
		||||
func (r *Reaction) RemapExternalUser(externalName string, externalID, userID int64) error {
 | 
			
		||||
	r.OriginalAuthor = externalName
 | 
			
		||||
	r.OriginalAuthorID = externalID
 | 
			
		||||
	r.UserID = userID
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetUserID ExternalUserRemappable interface
 | 
			
		||||
func (r *Reaction) GetUserID() int64 { return r.UserID }
 | 
			
		||||
 | 
			
		||||
// GetExternalName ExternalUserRemappable interface
 | 
			
		||||
func (r *Reaction) GetExternalName() string { return r.OriginalAuthor }
 | 
			
		||||
 | 
			
		||||
// GetExternalID ExternalUserRemappable interface
 | 
			
		||||
func (r *Reaction) GetExternalID() int64 { return r.OriginalAuthorID }
 | 
			
		||||
@@ -1,7 +1,8 @@
 | 
			
		||||
// Copyright 2017 The Gitea Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
package models
 | 
			
		||||
 | 
			
		||||
package issues
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
@@ -15,13 +16,13 @@ import (
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func addReaction(t *testing.T, doer *user_model.User, issue *Issue, comment *Comment, content string) {
 | 
			
		||||
func addReaction(t *testing.T, doerID, issueID, commentID int64, content string) {
 | 
			
		||||
	var reaction *Reaction
 | 
			
		||||
	var err error
 | 
			
		||||
	if comment == nil {
 | 
			
		||||
		reaction, err = CreateIssueReaction(doer, issue, content)
 | 
			
		||||
	if commentID == 0 {
 | 
			
		||||
		reaction, err = CreateIssueReaction(doerID, issueID, content)
 | 
			
		||||
	} else {
 | 
			
		||||
		reaction, err = CreateCommentReaction(doer, issue, comment, content)
 | 
			
		||||
		reaction, err = CreateCommentReaction(doerID, issueID, commentID, content)
 | 
			
		||||
	}
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.NotNil(t, reaction)
 | 
			
		||||
@@ -32,11 +33,11 @@ func TestIssueAddReaction(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}).(*user_model.User)
 | 
			
		||||
 | 
			
		||||
	issue1 := unittest.AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)
 | 
			
		||||
	var issue1ID int64 = 1
 | 
			
		||||
 | 
			
		||||
	addReaction(t, user1, issue1, nil, "heart")
 | 
			
		||||
	addReaction(t, user1.ID, issue1ID, 0, "heart")
 | 
			
		||||
 | 
			
		||||
	unittest.AssertExistsAndLoadBean(t, &Reaction{Type: "heart", UserID: user1.ID, IssueID: issue1.ID})
 | 
			
		||||
	unittest.AssertExistsAndLoadBean(t, &Reaction{Type: "heart", UserID: user1.ID, IssueID: issue1ID})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestIssueAddDuplicateReaction(t *testing.T) {
 | 
			
		||||
@@ -44,19 +45,19 @@ func TestIssueAddDuplicateReaction(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}).(*user_model.User)
 | 
			
		||||
 | 
			
		||||
	issue1 := unittest.AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)
 | 
			
		||||
	var issue1ID int64 = 1
 | 
			
		||||
 | 
			
		||||
	addReaction(t, user1, issue1, nil, "heart")
 | 
			
		||||
	addReaction(t, user1.ID, issue1ID, 0, "heart")
 | 
			
		||||
 | 
			
		||||
	reaction, err := CreateReaction(&ReactionOptions{
 | 
			
		||||
		Doer:  user1,
 | 
			
		||||
		Issue: issue1,
 | 
			
		||||
		Type:  "heart",
 | 
			
		||||
		DoerID:  user1.ID,
 | 
			
		||||
		IssueID: issue1ID,
 | 
			
		||||
		Type:    "heart",
 | 
			
		||||
	})
 | 
			
		||||
	assert.Error(t, err)
 | 
			
		||||
	assert.Equal(t, ErrReactionAlreadyExist{Reaction: "heart"}, err)
 | 
			
		||||
 | 
			
		||||
	existingR := unittest.AssertExistsAndLoadBean(t, &Reaction{Type: "heart", UserID: user1.ID, IssueID: issue1.ID}).(*Reaction)
 | 
			
		||||
	existingR := unittest.AssertExistsAndLoadBean(t, &Reaction{Type: "heart", UserID: user1.ID, IssueID: issue1ID}).(*Reaction)
 | 
			
		||||
	assert.Equal(t, existingR.ID, reaction.ID)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -65,14 +66,14 @@ func TestIssueDeleteReaction(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}).(*user_model.User)
 | 
			
		||||
 | 
			
		||||
	issue1 := unittest.AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)
 | 
			
		||||
	var issue1ID int64 = 1
 | 
			
		||||
 | 
			
		||||
	addReaction(t, user1, issue1, nil, "heart")
 | 
			
		||||
	addReaction(t, user1.ID, issue1ID, 0, "heart")
 | 
			
		||||
 | 
			
		||||
	err := DeleteIssueReaction(user1, issue1, "heart")
 | 
			
		||||
	err := DeleteIssueReaction(user1.ID, issue1ID, "heart")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	unittest.AssertNotExistsBean(t, &Reaction{Type: "heart", UserID: user1.ID, IssueID: issue1.ID})
 | 
			
		||||
	unittest.AssertNotExistsBean(t, &Reaction{Type: "heart", UserID: user1.ID, IssueID: issue1ID})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestIssueReactionCount(t *testing.T) {
 | 
			
		||||
@@ -86,22 +87,26 @@ func TestIssueReactionCount(t *testing.T) {
 | 
			
		||||
	user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}).(*user_model.User)
 | 
			
		||||
	ghost := user_model.NewGhostUser()
 | 
			
		||||
 | 
			
		||||
	issue := unittest.AssertExistsAndLoadBean(t, &Issue{ID: 2}).(*Issue)
 | 
			
		||||
	var issueID int64 = 2
 | 
			
		||||
	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}).(*repo_model.Repository)
 | 
			
		||||
 | 
			
		||||
	addReaction(t, user1, issue, nil, "heart")
 | 
			
		||||
	addReaction(t, user2, issue, nil, "heart")
 | 
			
		||||
	addReaction(t, user3, issue, nil, "heart")
 | 
			
		||||
	addReaction(t, user3, issue, nil, "+1")
 | 
			
		||||
	addReaction(t, user4, issue, nil, "+1")
 | 
			
		||||
	addReaction(t, user4, issue, nil, "heart")
 | 
			
		||||
	addReaction(t, ghost, issue, nil, "-1")
 | 
			
		||||
	addReaction(t, user1.ID, issueID, 0, "heart")
 | 
			
		||||
	addReaction(t, user2.ID, issueID, 0, "heart")
 | 
			
		||||
	addReaction(t, user3.ID, issueID, 0, "heart")
 | 
			
		||||
	addReaction(t, user3.ID, issueID, 0, "+1")
 | 
			
		||||
	addReaction(t, user4.ID, issueID, 0, "+1")
 | 
			
		||||
	addReaction(t, user4.ID, issueID, 0, "heart")
 | 
			
		||||
	addReaction(t, ghost.ID, issueID, 0, "-1")
 | 
			
		||||
 | 
			
		||||
	err := issue.loadReactions(db.DefaultContext)
 | 
			
		||||
	reactionsList, _, err := FindReactions(db.DefaultContext, FindReactionsOptions{
 | 
			
		||||
		IssueID: issueID,
 | 
			
		||||
	})
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.Len(t, reactionsList, 7)
 | 
			
		||||
	_, err = reactionsList.LoadUsers(db.DefaultContext, repo)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	assert.Len(t, issue.Reactions, 7)
 | 
			
		||||
 | 
			
		||||
	reactions := issue.Reactions.GroupByType()
 | 
			
		||||
	reactions := reactionsList.GroupByType()
 | 
			
		||||
	assert.Len(t, reactions["heart"], 4)
 | 
			
		||||
	assert.Equal(t, 2, reactions["heart"].GetMoreUserCount())
 | 
			
		||||
	assert.Equal(t, user1.DisplayName()+", "+user2.DisplayName(), reactions["heart"].GetFirstUsers())
 | 
			
		||||
@@ -118,13 +123,12 @@ func TestIssueCommentAddReaction(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}).(*user_model.User)
 | 
			
		||||
 | 
			
		||||
	issue1 := unittest.AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)
 | 
			
		||||
	var issue1ID int64 = 1
 | 
			
		||||
	var comment1ID int64 = 1
 | 
			
		||||
 | 
			
		||||
	comment1 := unittest.AssertExistsAndLoadBean(t, &Comment{ID: 1}).(*Comment)
 | 
			
		||||
	addReaction(t, user1.ID, issue1ID, comment1ID, "heart")
 | 
			
		||||
 | 
			
		||||
	addReaction(t, user1, issue1, comment1, "heart")
 | 
			
		||||
 | 
			
		||||
	unittest.AssertExistsAndLoadBean(t, &Reaction{Type: "heart", UserID: user1.ID, IssueID: issue1.ID, CommentID: comment1.ID})
 | 
			
		||||
	unittest.AssertExistsAndLoadBean(t, &Reaction{Type: "heart", UserID: user1.ID, IssueID: issue1ID, CommentID: comment1ID})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestIssueCommentDeleteReaction(t *testing.T) {
 | 
			
		||||
@@ -135,21 +139,22 @@ func TestIssueCommentDeleteReaction(t *testing.T) {
 | 
			
		||||
	user3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}).(*user_model.User)
 | 
			
		||||
	user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}).(*user_model.User)
 | 
			
		||||
 | 
			
		||||
	issue1 := unittest.AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)
 | 
			
		||||
	repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue1.RepoID}).(*repo_model.Repository)
 | 
			
		||||
	var issue1ID int64 = 1
 | 
			
		||||
	var comment1ID int64 = 1
 | 
			
		||||
 | 
			
		||||
	comment1 := unittest.AssertExistsAndLoadBean(t, &Comment{ID: 1}).(*Comment)
 | 
			
		||||
	addReaction(t, user1.ID, issue1ID, comment1ID, "heart")
 | 
			
		||||
	addReaction(t, user2.ID, issue1ID, comment1ID, "heart")
 | 
			
		||||
	addReaction(t, user3.ID, issue1ID, comment1ID, "heart")
 | 
			
		||||
	addReaction(t, user4.ID, issue1ID, comment1ID, "+1")
 | 
			
		||||
 | 
			
		||||
	addReaction(t, user1, issue1, comment1, "heart")
 | 
			
		||||
	addReaction(t, user2, issue1, comment1, "heart")
 | 
			
		||||
	addReaction(t, user3, issue1, comment1, "heart")
 | 
			
		||||
	addReaction(t, user4, issue1, comment1, "+1")
 | 
			
		||||
 | 
			
		||||
	err := comment1.LoadReactions(repo1)
 | 
			
		||||
	reactionsList, _, err := FindReactions(db.DefaultContext, FindReactionsOptions{
 | 
			
		||||
		IssueID:   issue1ID,
 | 
			
		||||
		CommentID: comment1ID,
 | 
			
		||||
	})
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.Len(t, comment1.Reactions, 4)
 | 
			
		||||
	assert.Len(t, reactionsList, 4)
 | 
			
		||||
 | 
			
		||||
	reactions := comment1.Reactions.GroupByType()
 | 
			
		||||
	reactions := reactionsList.GroupByType()
 | 
			
		||||
	assert.Len(t, reactions["heart"], 3)
 | 
			
		||||
	assert.Len(t, reactions["+1"], 1)
 | 
			
		||||
}
 | 
			
		||||
@@ -159,12 +164,11 @@ func TestIssueCommentReactionCount(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}).(*user_model.User)
 | 
			
		||||
 | 
			
		||||
	issue1 := unittest.AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)
 | 
			
		||||
	var issue1ID int64 = 1
 | 
			
		||||
	var comment1ID int64 = 1
 | 
			
		||||
 | 
			
		||||
	comment1 := unittest.AssertExistsAndLoadBean(t, &Comment{ID: 1}).(*Comment)
 | 
			
		||||
	addReaction(t, user1.ID, issue1ID, comment1ID, "heart")
 | 
			
		||||
	assert.NoError(t, DeleteCommentReaction(user1.ID, issue1ID, comment1ID, "heart"))
 | 
			
		||||
 | 
			
		||||
	addReaction(t, user1, issue1, comment1, "heart")
 | 
			
		||||
	assert.NoError(t, DeleteCommentReaction(user1, issue1, comment1, "heart"))
 | 
			
		||||
 | 
			
		||||
	unittest.AssertNotExistsBean(t, &Reaction{Type: "heart", UserID: user1.ID, IssueID: issue1.ID, CommentID: comment1.ID})
 | 
			
		||||
	unittest.AssertNotExistsBean(t, &Reaction{Type: "heart", UserID: user1.ID, IssueID: issue1ID, CommentID: comment1ID})
 | 
			
		||||
}
 | 
			
		||||
@@ -9,6 +9,7 @@ import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models/foreignreference"
 | 
			
		||||
	issues_model "code.gitea.io/gitea/models/issues"
 | 
			
		||||
	repo_model "code.gitea.io/gitea/models/repo"
 | 
			
		||||
	"code.gitea.io/gitea/models/unittest"
 | 
			
		||||
	user_model "code.gitea.io/gitea/models/user"
 | 
			
		||||
@@ -42,7 +43,7 @@ func assertCreateIssues(t *testing.T, isPull bool) {
 | 
			
		||||
	label := unittest.AssertExistsAndLoadBean(t, &Label{ID: 1}).(*Label)
 | 
			
		||||
	milestone := unittest.AssertExistsAndLoadBean(t, &Milestone{ID: 1}).(*Milestone)
 | 
			
		||||
	assert.EqualValues(t, milestone.ID, 1)
 | 
			
		||||
	reaction := &Reaction{
 | 
			
		||||
	reaction := &issues_model.Reaction{
 | 
			
		||||
		Type:   "heart",
 | 
			
		||||
		UserID: owner.ID,
 | 
			
		||||
	}
 | 
			
		||||
@@ -60,7 +61,7 @@ func assertCreateIssues(t *testing.T, isPull bool) {
 | 
			
		||||
		Poster:      owner,
 | 
			
		||||
		IsClosed:    true,
 | 
			
		||||
		Labels:      []*Label{label},
 | 
			
		||||
		Reactions:   []*Reaction{reaction},
 | 
			
		||||
		Reactions:   []*issues_model.Reaction{reaction},
 | 
			
		||||
		ForeignReference: &foreignreference.ForeignReference{
 | 
			
		||||
			ForeignIndex: strconv.FormatInt(foreignIndex, 10),
 | 
			
		||||
			RepoID:       repo.ID,
 | 
			
		||||
@@ -75,7 +76,7 @@ func assertCreateIssues(t *testing.T, isPull bool) {
 | 
			
		||||
	err = i.LoadAttributes()
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.EqualValues(t, strconv.FormatInt(foreignIndex, 10), i.ForeignReference.ForeignIndex)
 | 
			
		||||
	unittest.AssertExistsAndLoadBean(t, &Reaction{Type: "heart", UserID: owner.ID, IssueID: i.ID})
 | 
			
		||||
	unittest.AssertExistsAndLoadBean(t, &issues_model.Reaction{Type: "heart", UserID: owner.ID, IssueID: i.ID})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMigrate_CreateIssuesIsPullFalse(t *testing.T) {
 | 
			
		||||
@@ -91,7 +92,7 @@ func TestMigrate_InsertIssueComments(t *testing.T) {
 | 
			
		||||
	issue := unittest.AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)
 | 
			
		||||
	_ = issue.LoadRepo()
 | 
			
		||||
	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: issue.Repo.OwnerID}).(*user_model.User)
 | 
			
		||||
	reaction := &Reaction{
 | 
			
		||||
	reaction := &issues_model.Reaction{
 | 
			
		||||
		Type:   "heart",
 | 
			
		||||
		UserID: owner.ID,
 | 
			
		||||
	}
 | 
			
		||||
@@ -101,7 +102,7 @@ func TestMigrate_InsertIssueComments(t *testing.T) {
 | 
			
		||||
		Poster:    owner,
 | 
			
		||||
		IssueID:   issue.ID,
 | 
			
		||||
		Issue:     issue,
 | 
			
		||||
		Reactions: []*Reaction{reaction},
 | 
			
		||||
		Reactions: []*issues_model.Reaction{reaction},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := InsertIssueComments([]*Comment{comment})
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ import (
 | 
			
		||||
	repo_model "code.gitea.io/gitea/models/repo"
 | 
			
		||||
	"code.gitea.io/gitea/models/unit"
 | 
			
		||||
	user_model "code.gitea.io/gitea/models/user"
 | 
			
		||||
	"code.gitea.io/gitea/modules/container"
 | 
			
		||||
	"code.gitea.io/gitea/modules/log"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
	"code.gitea.io/gitea/modules/timeutil"
 | 
			
		||||
@@ -520,7 +521,7 @@ func (nl NotificationList) getPendingRepoIDs() []int64 {
 | 
			
		||||
			ids[notification.RepoID] = struct{}{}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return keysInt64(ids)
 | 
			
		||||
	return container.KeysInt64(ids)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LoadRepos loads repositories from database
 | 
			
		||||
@@ -596,7 +597,7 @@ func (nl NotificationList) getPendingIssueIDs() []int64 {
 | 
			
		||||
			ids[notification.IssueID] = struct{}{}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return keysInt64(ids)
 | 
			
		||||
	return container.KeysInt64(ids)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LoadIssues loads issues from database
 | 
			
		||||
@@ -682,7 +683,7 @@ func (nl NotificationList) getPendingCommentIDs() []int64 {
 | 
			
		||||
			ids[notification.CommentID] = struct{}{}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return keysInt64(ids)
 | 
			
		||||
	return container.KeysInt64(ids)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LoadComments loads comments from database
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@ import (
 | 
			
		||||
	repo_model "code.gitea.io/gitea/models/repo"
 | 
			
		||||
	"code.gitea.io/gitea/models/unit"
 | 
			
		||||
	user_model "code.gitea.io/gitea/models/user"
 | 
			
		||||
	"code.gitea.io/gitea/modules/container"
 | 
			
		||||
	"code.gitea.io/gitea/modules/structs"
 | 
			
		||||
	"code.gitea.io/gitea/modules/util"
 | 
			
		||||
 | 
			
		||||
@@ -62,7 +63,7 @@ func (repos RepositoryList) loadAttributes(e db.Engine) error {
 | 
			
		||||
	users := make(map[int64]*user_model.User, len(set))
 | 
			
		||||
	if err := e.
 | 
			
		||||
		Where("id > 0").
 | 
			
		||||
		In("id", keysInt64(set)).
 | 
			
		||||
		In("id", container.KeysInt64(set)).
 | 
			
		||||
		Find(&users); err != nil {
 | 
			
		||||
		return fmt.Errorf("find users: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ import (
 | 
			
		||||
 | 
			
		||||
	asymkey_model "code.gitea.io/gitea/models/asymkey"
 | 
			
		||||
	"code.gitea.io/gitea/models/db"
 | 
			
		||||
	"code.gitea.io/gitea/models/issues"
 | 
			
		||||
	"code.gitea.io/gitea/models/organization"
 | 
			
		||||
	repo_model "code.gitea.io/gitea/models/repo"
 | 
			
		||||
	user_model "code.gitea.io/gitea/models/user"
 | 
			
		||||
@@ -76,7 +77,7 @@ func DeleteUser(ctx context.Context, u *user_model.User) (err error) {
 | 
			
		||||
		&IssueUser{UID: u.ID},
 | 
			
		||||
		&user_model.EmailAddress{UID: u.ID},
 | 
			
		||||
		&user_model.UserOpenID{UID: u.ID},
 | 
			
		||||
		&Reaction{UserID: u.ID},
 | 
			
		||||
		&issues.Reaction{UserID: u.ID},
 | 
			
		||||
		&organization.TeamUser{UID: u.ID},
 | 
			
		||||
		&Collaboration{UserID: u.ID},
 | 
			
		||||
		&Stopwatch{UserID: u.ID},
 | 
			
		||||
@@ -100,14 +101,14 @@ func DeleteUser(ctx context.Context, u *user_model.User) (err error) {
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for _, comment := range comments {
 | 
			
		||||
				if err = deleteComment(e, comment); err != nil {
 | 
			
		||||
				if err = deleteComment(ctx, comment); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Delete Reactions
 | 
			
		||||
		if err = deleteReaction(e, &ReactionOptions{Doer: u}); err != nil {
 | 
			
		||||
		if err = issues.DeleteReaction(ctx, &issues.ReactionOptions{DoerID: u.ID}); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								modules/container/map.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								modules/container/map.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
// Copyright 2022 The Gitea Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package container
 | 
			
		||||
 | 
			
		||||
// KeysInt64 returns keys slice for a map with int64 key
 | 
			
		||||
func KeysInt64(m map[int64]struct{}) []int64 {
 | 
			
		||||
	keys := make([]int64, 0, len(m))
 | 
			
		||||
	for k := range m {
 | 
			
		||||
		keys = append(keys, k)
 | 
			
		||||
	}
 | 
			
		||||
	return keys
 | 
			
		||||
}
 | 
			
		||||
@@ -9,6 +9,7 @@ import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models"
 | 
			
		||||
	issues_model "code.gitea.io/gitea/models/issues"
 | 
			
		||||
	"code.gitea.io/gitea/modules/context"
 | 
			
		||||
	"code.gitea.io/gitea/modules/convert"
 | 
			
		||||
	api "code.gitea.io/gitea/modules/structs"
 | 
			
		||||
@@ -67,12 +68,12 @@ func GetIssueCommentReactions(ctx *context.APIContext) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	reactions, _, err := models.FindCommentReactions(comment)
 | 
			
		||||
	reactions, _, err := issues_model.FindCommentReactions(comment.IssueID, comment.ID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.Error(http.StatusInternalServerError, "FindCommentReactions", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, err = reactions.LoadUsers(ctx.Repo.Repository)
 | 
			
		||||
	_, err = reactions.LoadUsers(ctx, ctx.Repo.Repository)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.Error(http.StatusInternalServerError, "ReactionList.LoadUsers()", err)
 | 
			
		||||
		return
 | 
			
		||||
@@ -197,11 +198,11 @@ func changeIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOp
 | 
			
		||||
 | 
			
		||||
	if isCreateType {
 | 
			
		||||
		// PostIssueCommentReaction part
 | 
			
		||||
		reaction, err := models.CreateCommentReaction(ctx.Doer, comment.Issue, comment, form.Reaction)
 | 
			
		||||
		reaction, err := issues_model.CreateCommentReaction(ctx.Doer.ID, comment.Issue.ID, comment.ID, form.Reaction)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if models.IsErrForbiddenIssueReaction(err) {
 | 
			
		||||
			if issues_model.IsErrForbiddenIssueReaction(err) {
 | 
			
		||||
				ctx.Error(http.StatusForbidden, err.Error(), err)
 | 
			
		||||
			} else if models.IsErrReactionAlreadyExist(err) {
 | 
			
		||||
			} else if issues_model.IsErrReactionAlreadyExist(err) {
 | 
			
		||||
				ctx.JSON(http.StatusOK, api.Reaction{
 | 
			
		||||
					User:     convert.ToUser(ctx.Doer, ctx.Doer),
 | 
			
		||||
					Reaction: reaction.Type,
 | 
			
		||||
@@ -220,7 +221,7 @@ func changeIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOp
 | 
			
		||||
		})
 | 
			
		||||
	} else {
 | 
			
		||||
		// DeleteIssueCommentReaction part
 | 
			
		||||
		err = models.DeleteCommentReaction(ctx.Doer, comment.Issue, comment, form.Reaction)
 | 
			
		||||
		err = issues_model.DeleteCommentReaction(ctx.Doer.ID, comment.Issue.ID, comment.ID, form.Reaction)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			ctx.Error(http.StatusInternalServerError, "DeleteCommentReaction", err)
 | 
			
		||||
			return
 | 
			
		||||
@@ -285,12 +286,12 @@ func GetIssueReactions(ctx *context.APIContext) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	reactions, count, err := models.FindIssueReactions(issue, utils.GetListOptions(ctx))
 | 
			
		||||
	reactions, count, err := issues_model.FindIssueReactions(issue.ID, utils.GetListOptions(ctx))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.Error(http.StatusInternalServerError, "FindIssueReactions", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, err = reactions.LoadUsers(ctx.Repo.Repository)
 | 
			
		||||
	_, err = reactions.LoadUsers(ctx, ctx.Repo.Repository)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.Error(http.StatusInternalServerError, "ReactionList.LoadUsers()", err)
 | 
			
		||||
		return
 | 
			
		||||
@@ -407,11 +408,11 @@ func changeIssueReaction(ctx *context.APIContext, form api.EditReactionOption, i
 | 
			
		||||
 | 
			
		||||
	if isCreateType {
 | 
			
		||||
		// PostIssueReaction part
 | 
			
		||||
		reaction, err := models.CreateIssueReaction(ctx.Doer, issue, form.Reaction)
 | 
			
		||||
		reaction, err := issues_model.CreateIssueReaction(ctx.Doer.ID, issue.ID, form.Reaction)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if models.IsErrForbiddenIssueReaction(err) {
 | 
			
		||||
			if issues_model.IsErrForbiddenIssueReaction(err) {
 | 
			
		||||
				ctx.Error(http.StatusForbidden, err.Error(), err)
 | 
			
		||||
			} else if models.IsErrReactionAlreadyExist(err) {
 | 
			
		||||
			} else if issues_model.IsErrReactionAlreadyExist(err) {
 | 
			
		||||
				ctx.JSON(http.StatusOK, api.Reaction{
 | 
			
		||||
					User:     convert.ToUser(ctx.Doer, ctx.Doer),
 | 
			
		||||
					Reaction: reaction.Type,
 | 
			
		||||
@@ -430,7 +431,7 @@ func changeIssueReaction(ctx *context.APIContext, form api.EditReactionOption, i
 | 
			
		||||
		})
 | 
			
		||||
	} else {
 | 
			
		||||
		// DeleteIssueReaction part
 | 
			
		||||
		err = models.DeleteIssueReaction(ctx.Doer, issue, form.Reaction)
 | 
			
		||||
		err = issues_model.DeleteIssueReaction(ctx.Doer.ID, issue.ID, form.Reaction)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			ctx.Error(http.StatusInternalServerError, "DeleteIssueReaction", err)
 | 
			
		||||
			return
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@ import (
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models"
 | 
			
		||||
	"code.gitea.io/gitea/models/db"
 | 
			
		||||
	issues_model "code.gitea.io/gitea/models/issues"
 | 
			
		||||
	"code.gitea.io/gitea/models/organization"
 | 
			
		||||
	project_model "code.gitea.io/gitea/models/project"
 | 
			
		||||
	repo_model "code.gitea.io/gitea/models/repo"
 | 
			
		||||
@@ -2349,9 +2350,9 @@ func ChangeIssueReaction(ctx *context.Context) {
 | 
			
		||||
 | 
			
		||||
	switch ctx.Params(":action") {
 | 
			
		||||
	case "react":
 | 
			
		||||
		reaction, err := models.CreateIssueReaction(ctx.Doer, issue, form.Content)
 | 
			
		||||
		reaction, err := issues_model.CreateIssueReaction(ctx.Doer.ID, issue.ID, form.Content)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if models.IsErrForbiddenIssueReaction(err) {
 | 
			
		||||
			if issues_model.IsErrForbiddenIssueReaction(err) {
 | 
			
		||||
				ctx.ServerError("ChangeIssueReaction", err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
@@ -2367,7 +2368,7 @@ func ChangeIssueReaction(ctx *context.Context) {
 | 
			
		||||
 | 
			
		||||
		log.Trace("Reaction for issue created: %d/%d/%d", ctx.Repo.Repository.ID, issue.ID, reaction.ID)
 | 
			
		||||
	case "unreact":
 | 
			
		||||
		if err := models.DeleteIssueReaction(ctx.Doer, issue, form.Content); err != nil {
 | 
			
		||||
		if err := issues_model.DeleteIssueReaction(ctx.Doer.ID, issue.ID, form.Content); err != nil {
 | 
			
		||||
			ctx.ServerError("DeleteIssueReaction", err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
@@ -2451,9 +2452,9 @@ func ChangeCommentReaction(ctx *context.Context) {
 | 
			
		||||
 | 
			
		||||
	switch ctx.Params(":action") {
 | 
			
		||||
	case "react":
 | 
			
		||||
		reaction, err := models.CreateCommentReaction(ctx.Doer, comment.Issue, comment, form.Content)
 | 
			
		||||
		reaction, err := issues_model.CreateCommentReaction(ctx.Doer.ID, comment.Issue.ID, comment.ID, form.Content)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if models.IsErrForbiddenIssueReaction(err) {
 | 
			
		||||
			if issues_model.IsErrForbiddenIssueReaction(err) {
 | 
			
		||||
				ctx.ServerError("ChangeIssueReaction", err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
@@ -2469,7 +2470,7 @@ func ChangeCommentReaction(ctx *context.Context) {
 | 
			
		||||
 | 
			
		||||
		log.Trace("Reaction for comment created: %d/%d/%d/%d", ctx.Repo.Repository.ID, comment.Issue.ID, comment.ID, reaction.ID)
 | 
			
		||||
	case "unreact":
 | 
			
		||||
		if err := models.DeleteCommentReaction(ctx.Doer, comment.Issue, comment, form.Content); err != nil {
 | 
			
		||||
		if err := issues_model.DeleteCommentReaction(ctx.Doer.ID, comment.Issue.ID, comment.ID, form.Content); err != nil {
 | 
			
		||||
			ctx.ServerError("DeleteCommentReaction", err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ import (
 | 
			
		||||
	"code.gitea.io/gitea/models"
 | 
			
		||||
	"code.gitea.io/gitea/models/db"
 | 
			
		||||
	"code.gitea.io/gitea/models/foreignreference"
 | 
			
		||||
	issues_model "code.gitea.io/gitea/models/issues"
 | 
			
		||||
	repo_model "code.gitea.io/gitea/models/repo"
 | 
			
		||||
	user_model "code.gitea.io/gitea/models/user"
 | 
			
		||||
	"code.gitea.io/gitea/modules/git"
 | 
			
		||||
@@ -392,7 +393,7 @@ func (g *GiteaLocalUploader) CreateIssues(issues ...*base.Issue) error {
 | 
			
		||||
		}
 | 
			
		||||
		// add reactions
 | 
			
		||||
		for _, reaction := range issue.Reactions {
 | 
			
		||||
			res := models.Reaction{
 | 
			
		||||
			res := issues_model.Reaction{
 | 
			
		||||
				Type:        reaction.Content,
 | 
			
		||||
				CreatedUnix: timeutil.TimeStampNow(),
 | 
			
		||||
			}
 | 
			
		||||
@@ -448,7 +449,7 @@ func (g *GiteaLocalUploader) CreateComments(comments ...*base.Comment) error {
 | 
			
		||||
 | 
			
		||||
		// add reactions
 | 
			
		||||
		for _, reaction := range comment.Reactions {
 | 
			
		||||
			res := models.Reaction{
 | 
			
		||||
			res := issues_model.Reaction{
 | 
			
		||||
				Type:        reaction.Content,
 | 
			
		||||
				CreatedUnix: timeutil.TimeStampNow(),
 | 
			
		||||
			}
 | 
			
		||||
@@ -646,7 +647,7 @@ func (g *GiteaLocalUploader) newPullRequest(pr *base.PullRequest) (*models.PullR
 | 
			
		||||
 | 
			
		||||
	// add reactions
 | 
			
		||||
	for _, reaction := range pr.Reactions {
 | 
			
		||||
		res := models.Reaction{
 | 
			
		||||
		res := issues_model.Reaction{
 | 
			
		||||
			Type:        reaction.Content,
 | 
			
		||||
			CreatedUnix: timeutil.TimeStampNow(),
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user