@@ -6,8 +6,14 @@ package user
66import (
77 "context"
88 "fmt"
9+ "net/url"
10+ "strings"
911
1012 "code.gitea.io/gitea/models/db"
13+ "code.gitea.io/gitea/modules/setting"
14+
15+ "xorm.io/builder"
16+ "xorm.io/xorm"
1117)
1218
1319// Badge represents a user badge
@@ -30,6 +36,10 @@ func init() {
3036 db .RegisterModel (new (UserBadge ))
3137}
3238
39+ func AdminCreateBadge (ctx context.Context , badge * Badge ) error {
40+ return CreateBadge (ctx , badge )
41+ }
42+
3343// GetUserBadges returns the user's badges.
3444func GetUserBadges (ctx context.Context , u * User ) ([]* Badge , int64 , error ) {
3545 sess := db .GetEngine (ctx ).
@@ -42,9 +52,30 @@ func GetUserBadges(ctx context.Context, u *User) ([]*Badge, int64, error) {
4252 return badges , count , err
4353}
4454
55+ // GetBadgeUsers returns the badges users.
56+ func GetBadgeUsers (ctx context.Context , b * Badge ) ([]* User , int64 , error ) {
57+ sess := db .GetEngine (ctx ).
58+ Select ("`user`.*" ).
59+ Join ("INNER" , "user_badge" , "`user_badge`.user_id=user.id" ).
60+ Where ("user_badge.badge_id=?" , b .ID )
61+
62+ users := make ([]* User , 0 , 8 )
63+ count , err := sess .FindAndCount (& users )
64+ return users , count , err
65+ }
66+
4567// CreateBadge creates a new badge.
4668func CreateBadge (ctx context.Context , badge * Badge ) error {
47- _ , err := db .GetEngine (ctx ).Insert (badge )
69+ isExist , err := IsBadgeExist (ctx , 0 , badge .Slug )
70+
71+ if err != nil {
72+ return err
73+ } else if isExist {
74+ return ErrBadgeAlreadyExist {badge .Slug }
75+ }
76+
77+ _ , err = db .GetEngine (ctx ).Insert (badge )
78+
4879 return err
4980}
5081
@@ -58,9 +89,22 @@ func GetBadge(ctx context.Context, slug string) (*Badge, error) {
5889 return badge , err
5990}
6091
92+ // GetBadgeByID returns a badge
93+ func GetBadgeByID (ctx context.Context , id int64 ) (* Badge , error ) {
94+ badge := new (Badge )
95+ has , err := db .GetEngine (ctx ).Where ("id=?" , id ).Get (badge )
96+ if err != nil {
97+ return nil , err
98+ } else if ! has {
99+ return nil , ErrBadgeNotExist {ID : id }
100+ }
101+
102+ return badge , err
103+ }
104+
61105// UpdateBadge updates a badge based on its slug.
62106func UpdateBadge (ctx context.Context , badge * Badge ) error {
63- _ , err := db .GetEngine (ctx ).Where ("slug =?" , badge .Slug ).Update (badge )
107+ _ , err := db .GetEngine (ctx ).Where ("id =?" , badge .ID ). Cols ( "slug" , "description" , "image_url" ).Update (badge )
64108 return err
65109}
66110
@@ -70,6 +114,15 @@ func DeleteBadge(ctx context.Context, badge *Badge) error {
70114 return err
71115}
72116
117+ // DeleteUserBadgeRecord deletes a user badge record.
118+ func DeleteUserBadgeRecord (ctx context.Context , badge * Badge ) error {
119+ userBadge := & UserBadge {
120+ BadgeID : badge .ID ,
121+ }
122+ _ , err := db .GetEngine (ctx ).Where ("badge_id=?" , userBadge .BadgeID ).Delete (userBadge )
123+ return err
124+ }
125+
73126// AddUserBadge adds a badge to a user.
74127func AddUserBadge (ctx context.Context , u * User , badge * Badge ) error {
75128 return AddUserBadges (ctx , u , []* Badge {badge })
@@ -122,3 +175,107 @@ func RemoveAllUserBadges(ctx context.Context, u *User) error {
122175 _ , err := db .GetEngine (ctx ).Where ("user_id=?" , u .ID ).Delete (& UserBadge {})
123176 return err
124177}
178+
179+ // HTMLURL returns the badges full link.
180+ func (u * Badge ) HTMLURL () string {
181+ return setting .AppURL + url .PathEscape (u .Slug )
182+ }
183+
184+ // IsBadgeExist checks if given badge slug exist,
185+ // it is used when creating/updating a badge slug
186+ func IsBadgeExist (ctx context.Context , uid int64 , slug string ) (bool , error ) {
187+ if len (slug ) == 0 {
188+ return false , nil
189+ }
190+ return db .GetEngine (ctx ).
191+ Where ("slug!=?" , uid ).
192+ Get (& Badge {Slug : strings .ToLower (slug )})
193+ }
194+
195+ // SearchBadgeOptions represents the options when fdin badges
196+ type SearchBadgeOptions struct {
197+ db.ListOptions
198+
199+ Keyword string
200+ Slug string
201+ ID int64
202+ OrderBy db.SearchOrderBy
203+ Actor * User // The user doing the search
204+
205+ ExtraParamStrings map [string ]string
206+ }
207+
208+ func (opts * SearchBadgeOptions ) ToConds () builder.Cond {
209+ cond := builder .NewCond ()
210+
211+ if opts .Keyword != "" {
212+ cond = cond .And (builder.Like {"badge.slug" , opts .Keyword })
213+ }
214+
215+ return cond
216+ }
217+
218+ func (opts * SearchBadgeOptions ) ToOrders () string {
219+ orderBy := "badge.slug"
220+ return orderBy
221+ }
222+
223+ func (opts * SearchBadgeOptions ) ToJoins () []db.JoinFunc {
224+ return []db.JoinFunc {
225+ func (e db.Engine ) error {
226+ e .Join ("INNER" , "badge" , "badge.badge_id = badge.id" )
227+ return nil
228+ },
229+ }
230+ }
231+
232+ func SearchBadges (ctx context.Context , opts * SearchBadgeOptions ) (badges []* Badge , _ int64 , _ error ) {
233+ sessCount := opts .toSearchQueryBase (ctx )
234+ defer sessCount .Close ()
235+ count , err := sessCount .Count (new (Badge ))
236+ if err != nil {
237+ return nil , 0 , fmt .Errorf ("count: %w" , err )
238+ }
239+
240+ if len (opts .OrderBy ) == 0 {
241+ opts .OrderBy = db .SearchOrderByID
242+ }
243+
244+ sessQuery := opts .toSearchQueryBase (ctx ).OrderBy (opts .OrderBy .String ())
245+ defer sessQuery .Close ()
246+ if opts .Page != 0 {
247+ sessQuery = db .SetSessionPagination (sessQuery , opts )
248+ }
249+
250+ // the sql may contain JOIN, so we must only select Badge related columns
251+ sessQuery = sessQuery .Select ("`badge`.*" )
252+ badges = make ([]* Badge , 0 , opts .PageSize )
253+ return badges , count , sessQuery .Find (& badges )
254+ }
255+
256+ func (opts * SearchBadgeOptions ) toSearchQueryBase (ctx context.Context ) * xorm.Session {
257+ var cond builder.Cond
258+ cond = builder.Neq {"id" : - 1 }
259+
260+ if len (opts .Keyword ) > 0 {
261+ lowerKeyword := strings .ToLower (opts .Keyword )
262+ keywordCond := builder .Or (
263+ builder.Like {"slug" , lowerKeyword },
264+ builder.Like {"description" , lowerKeyword },
265+ builder.Like {"id" , lowerKeyword },
266+ )
267+ cond = cond .And (keywordCond )
268+ }
269+
270+ if opts .ID > 0 {
271+ cond = cond .And (builder.Eq {"id" : opts .ID })
272+ }
273+
274+ if len (opts .Slug ) > 0 {
275+ cond = cond .And (builder.Eq {"slug" : opts .Slug })
276+ }
277+
278+ e := db .GetEngine (ctx )
279+
280+ return e .Where (cond )
281+ }
0 commit comments