99 "strings"
1010
1111 "code.gitea.io/gitea/models/db"
12+ "code.gitea.io/gitea/modules/util"
1213
1314 "xorm.io/builder"
14- "xorm.io/xorm"
1515)
1616
1717// Badge represents a user badge
@@ -29,6 +29,50 @@ type UserBadge struct { //nolint:revive
2929 UserID int64 `xorm:"INDEX"`
3030}
3131
32+ // ErrBadgeAlreadyExist represents a "badge already exists" error.
33+ type ErrBadgeAlreadyExist struct {
34+ Slug string
35+ }
36+
37+ // IsErrBadgeAlreadyExist checks if an error is a ErrBadgeAlreadyExist.
38+ func IsErrBadgeAlreadyExist (err error ) bool {
39+ _ , ok := err .(ErrBadgeAlreadyExist )
40+ return ok
41+ }
42+
43+ func (err ErrBadgeAlreadyExist ) Error () string {
44+ return fmt .Sprintf ("badge already exists [slug: %s]" , err .Slug )
45+ }
46+
47+ // Unwrap unwraps this error as a ErrExist error
48+ func (err ErrBadgeAlreadyExist ) Unwrap () error {
49+ return util .ErrAlreadyExist
50+ }
51+
52+ // ErrBadgeNotExist represents a "BadgeNotExist" kind of error.
53+ type ErrBadgeNotExist struct {
54+ Slug string
55+ ID int64
56+ }
57+
58+ func (err ErrBadgeNotExist ) Error () string {
59+ if err .ID > 0 {
60+ return fmt .Sprintf ("badge does not exist [id: %d]" , err .ID )
61+ }
62+ return fmt .Sprintf ("badge does not exist [slug: %s]" , err .Slug )
63+ }
64+
65+ // IsErrBadgeNotExist checks if an error is a ErrBadgeNotExist.
66+ func IsErrBadgeNotExist (err error ) bool {
67+ _ , ok := err .(ErrBadgeNotExist )
68+ return ok
69+ }
70+
71+ // Unwrap unwraps this error as a ErrNotExist error
72+ func (err ErrBadgeNotExist ) Unwrap () error {
73+ return util .ErrNotExist
74+ }
75+
3276func init () {
3377 db .RegisterModel (new (Badge ))
3478 db .RegisterModel (new (UserBadge ))
@@ -73,7 +117,6 @@ func GetBadgeUsers(ctx context.Context, opts *GetBadgeUsersOptions) ([]*User, in
73117func CreateBadge (ctx context.Context , badge * Badge ) error {
74118 // this will fail if the badge already exists due to the UNIQUE constraint
75119 _ , err := db .GetEngine (ctx ).Insert (badge )
76-
77120 return err
78121}
79122
@@ -151,11 +194,14 @@ func RemoveUserBadges(ctx context.Context, u *User, badges []*Badge) error {
151194 slugs [i ] = badge .Slug
152195 }
153196
197+ var badgeIDs []int64
198+ if err := db .GetEngine (ctx ).Table ("badge" ).In ("slug" , slugs ).Cols ("id" ).Find (& badgeIDs ); err != nil {
199+ return err
200+ }
201+
154202 if _ , err := db .GetEngine (ctx ).
155- Table ("user_badge" ).
156- Join ("INNER" , "badge" , "`user_badge`.badge_id = badge.id" ).
157- Where ("`user_badge`.user_id = ?" , u .ID ).
158- And (builder .In ("badge.slug" , slugs )).
203+ Where ("user_id = ?" , u .ID ).
204+ In ("badge_id" , badgeIDs ).
159205 Delete (& UserBadge {}); err != nil {
160206 return err
161207 }
@@ -184,66 +230,29 @@ func (opts *SearchBadgeOptions) ToConds() builder.Cond {
184230 cond := builder .NewCond ()
185231
186232 if opts .Keyword != "" {
187- cond = cond .And (builder.Like {"badge.slug" , opts .Keyword })
188- }
189-
190- return cond
191- }
192-
193- func (opts * SearchBadgeOptions ) ToOrders () string {
194- orderBy := "badge.slug"
195- return orderBy
196- }
197-
198- func SearchBadges (ctx context.Context , opts * SearchBadgeOptions ) (badges []* Badge , _ int64 , _ error ) {
199- sessCount := opts .toSearchQueryBase (ctx )
200- count , err := sessCount .Count (new (Badge ))
201- if err != nil {
202- return nil , 0 , fmt .Errorf ("count: %w" , err )
203- }
204- sessCount .Close ()
205-
206- if len (opts .OrderBy ) == 0 {
207- opts .OrderBy = db .SearchOrderByID
208- }
209-
210- sessQuery := opts .toSearchQueryBase (ctx ).OrderBy (opts .OrderBy .String ())
211- defer sessQuery .Close ()
212- if opts .Page != 0 {
213- sessQuery = db .SetSessionPagination (sessQuery , opts )
214- }
215-
216- // the sql may contain JOIN, so we must only select Badge related columns
217- sessQuery = sessQuery .Select ("`badge`.*" )
218- badges = make ([]* Badge , 0 , opts .PageSize )
219- return badges , count , sessQuery .Find (& badges )
220- }
221-
222- func (opts * SearchBadgeOptions ) toSearchQueryBase (ctx context.Context ) * xorm.Session {
223- var cond builder.Cond
224- cond = builder.Neq {"id" : - 1 }
225-
226- if len (opts .Keyword ) > 0 {
227233 lowerKeyword := strings .ToLower (opts .Keyword )
228234 keywordCond := builder .Or (
229- builder.Like {"slug" , lowerKeyword },
230- builder.Like {"description" , lowerKeyword },
231- builder.Like {"id" , lowerKeyword },
235+ builder.Like {"badge. slug" , lowerKeyword },
236+ builder.Like {"badge. description" , lowerKeyword },
237+ builder.Like {"badge. id" , lowerKeyword },
232238 )
233239 cond = cond .And (keywordCond )
234240 }
235241
236242 if opts .ID > 0 {
237- cond = cond .And (builder.Eq {"id" : opts .ID })
243+ cond = cond .And (builder.Eq {"badge. id" : opts .ID })
238244 }
239245
240246 if len (opts .Slug ) > 0 {
241- cond = cond .And (builder.Eq {"slug" : opts .Slug })
247+ cond = cond .And (builder.Eq {"badge. slug" : opts .Slug })
242248 }
243249
244- e := db .GetEngine (ctx )
250+ return cond
251+ }
245252
246- return e .Where (cond )
253+ // SearchBadges returns badges based on the provided SearchBadgeOptions options
254+ func SearchBadges (ctx context.Context , opts * SearchBadgeOptions ) ([]* Badge , int64 , error ) {
255+ return db .FindAndCount [Badge ](ctx , opts )
247256}
248257
249258// GetBadgeByID returns a specific badge by ID
0 commit comments