code.gitea.io/gitea@v1.22.3/models/issues/review_list.go (about) 1 // Copyright 2023 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package issues 5 6 import ( 7 "context" 8 9 "code.gitea.io/gitea/models/db" 10 user_model "code.gitea.io/gitea/models/user" 11 "code.gitea.io/gitea/modules/container" 12 "code.gitea.io/gitea/modules/optional" 13 14 "xorm.io/builder" 15 ) 16 17 type ReviewList []*Review 18 19 // LoadReviewers loads reviewers 20 func (reviews ReviewList) LoadReviewers(ctx context.Context) error { 21 reviewerIDs := make([]int64, len(reviews)) 22 for i := 0; i < len(reviews); i++ { 23 reviewerIDs[i] = reviews[i].ReviewerID 24 } 25 reviewers, err := user_model.GetPossibleUserByIDs(ctx, reviewerIDs) 26 if err != nil { 27 return err 28 } 29 30 userMap := make(map[int64]*user_model.User, len(reviewers)) 31 for _, reviewer := range reviewers { 32 userMap[reviewer.ID] = reviewer 33 } 34 for _, review := range reviews { 35 review.Reviewer = userMap[review.ReviewerID] 36 } 37 return nil 38 } 39 40 func (reviews ReviewList) LoadIssues(ctx context.Context) error { 41 issueIDs := container.FilterSlice(reviews, func(review *Review) (int64, bool) { 42 return review.IssueID, true 43 }) 44 45 issues, err := GetIssuesByIDs(ctx, issueIDs) 46 if err != nil { 47 return err 48 } 49 if _, err := issues.LoadRepositories(ctx); err != nil { 50 return err 51 } 52 issueMap := make(map[int64]*Issue, len(issues)) 53 for _, issue := range issues { 54 issueMap[issue.ID] = issue 55 } 56 57 for _, review := range reviews { 58 review.Issue = issueMap[review.IssueID] 59 } 60 return nil 61 } 62 63 // FindReviewOptions represent possible filters to find reviews 64 type FindReviewOptions struct { 65 db.ListOptions 66 Types []ReviewType 67 IssueID int64 68 ReviewerID int64 69 OfficialOnly bool 70 Dismissed optional.Option[bool] 71 } 72 73 func (opts *FindReviewOptions) toCond() builder.Cond { 74 cond := builder.NewCond() 75 if opts.IssueID > 0 { 76 cond = cond.And(builder.Eq{"issue_id": opts.IssueID}) 77 } 78 if opts.ReviewerID > 0 { 79 cond = cond.And(builder.Eq{"reviewer_id": opts.ReviewerID}) 80 } 81 if len(opts.Types) > 0 { 82 cond = cond.And(builder.In("type", opts.Types)) 83 } 84 if opts.OfficialOnly { 85 cond = cond.And(builder.Eq{"official": true}) 86 } 87 if opts.Dismissed.Has() { 88 cond = cond.And(builder.Eq{"dismissed": opts.Dismissed.Value()}) 89 } 90 return cond 91 } 92 93 // FindReviews returns reviews passing FindReviewOptions 94 func FindReviews(ctx context.Context, opts FindReviewOptions) (ReviewList, error) { 95 reviews := make([]*Review, 0, 10) 96 sess := db.GetEngine(ctx).Where(opts.toCond()) 97 if opts.Page > 0 && !opts.IsListAll() { 98 sess = db.SetSessionPagination(sess, &opts) 99 } 100 return reviews, sess. 101 Asc("created_unix"). 102 Asc("id"). 103 Find(&reviews) 104 } 105 106 // FindLatestReviews returns only latest reviews per user, passing FindReviewOptions 107 func FindLatestReviews(ctx context.Context, opts FindReviewOptions) (ReviewList, error) { 108 reviews := make([]*Review, 0, 10) 109 cond := opts.toCond() 110 sess := db.GetEngine(ctx).Where(cond) 111 if opts.Page > 0 { 112 sess = db.SetSessionPagination(sess, &opts) 113 } 114 115 sess.In("id", builder. 116 Select("max(id)"). 117 From("review"). 118 Where(cond). 119 GroupBy("reviewer_id")) 120 121 return reviews, sess. 122 Asc("created_unix"). 123 Asc("id"). 124 Find(&reviews) 125 } 126 127 // CountReviews returns count of reviews passing FindReviewOptions 128 func CountReviews(ctx context.Context, opts FindReviewOptions) (int64, error) { 129 return db.GetEngine(ctx).Where(opts.toCond()).Count(&Review{}) 130 } 131 132 // GetReviewersFromOriginalAuthorsByIssueID gets the latest review of each original authors for a pull request 133 func GetReviewersFromOriginalAuthorsByIssueID(ctx context.Context, issueID int64) (ReviewList, error) { 134 reviews := make([]*Review, 0, 10) 135 136 // Get latest review of each reviewer, sorted in order they were made 137 if err := db.GetEngine(ctx).SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND reviewer_team_id = 0 AND type in (?, ?, ?) AND original_author_id <> 0 GROUP BY issue_id, original_author_id) ORDER BY review.updated_unix ASC", 138 issueID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest). 139 Find(&reviews); err != nil { 140 return nil, err 141 } 142 143 return reviews, nil 144 } 145 146 // GetReviewsByIssueID gets the latest review of each reviewer for a pull request 147 func GetReviewsByIssueID(ctx context.Context, issueID int64) (ReviewList, error) { 148 reviews := make([]*Review, 0, 10) 149 150 sess := db.GetEngine(ctx) 151 152 // Get latest review of each reviewer, sorted in order they were made 153 if err := sess.SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND reviewer_team_id = 0 AND type in (?, ?, ?) AND dismissed = ? AND original_author_id = 0 GROUP BY issue_id, reviewer_id) ORDER BY review.updated_unix ASC", 154 issueID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest, false). 155 Find(&reviews); err != nil { 156 return nil, err 157 } 158 159 teamReviewRequests := make([]*Review, 0, 5) 160 if err := sess.SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND reviewer_team_id <> 0 AND original_author_id = 0 GROUP BY issue_id, reviewer_team_id) ORDER BY review.updated_unix ASC", 161 issueID). 162 Find(&teamReviewRequests); err != nil { 163 return nil, err 164 } 165 166 if len(teamReviewRequests) > 0 { 167 reviews = append(reviews, teamReviewRequests...) 168 } 169 170 return reviews, nil 171 }