@@ -17,7 +17,6 @@ import (
1717 user_model "code.gitea.io/gitea/models/user"
1818 "code.gitea.io/gitea/modules/container"
1919 "code.gitea.io/gitea/modules/log"
20- "code.gitea.io/gitea/modules/setting"
2120 api "code.gitea.io/gitea/modules/structs"
2221 "code.gitea.io/gitea/modules/timeutil"
2322 "code.gitea.io/gitea/modules/util"
@@ -96,7 +95,8 @@ type Issue struct {
9695 // TODO: RemoveIssueRef: see "repo/issue/branch_selector_field.tmpl"
9796 Ref string
9897
99- PinOrder int `xorm:"DEFAULT 0"`
98+ PinOrder int `xorm:"-"`
99+ pinOrderLoaded bool `xorm:"-"`
100100
101101 DeadlineUnix timeutil.TimeStamp `xorm:"INDEX"`
102102
@@ -290,6 +290,21 @@ func (issue *Issue) LoadMilestone(ctx context.Context) (err error) {
290290 return nil
291291}
292292
293+ func (issue * Issue ) LoadPinOrder (ctx context.Context ) error {
294+ if issue .pinOrderLoaded || issue .PinOrder > 0 {
295+ return nil
296+ }
297+ issuePin , err := GetIssuePin (ctx , issue )
298+ if err != nil && ! db .IsErrNotExist (err ) {
299+ return err
300+ }
301+ issue .pinOrderLoaded = true
302+ if issuePin != nil {
303+ issue .PinOrder = issuePin .PinOrder
304+ }
305+ return nil
306+ }
307+
293308// LoadAttributes loads the attribute of this issue.
294309func (issue * Issue ) LoadAttributes (ctx context.Context ) (err error ) {
295310 if err = issue .LoadRepo (ctx ); err != nil {
@@ -329,6 +344,10 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) {
329344 return err
330345 }
331346
347+ if err = issue .LoadPinOrder (ctx ); err != nil {
348+ return err
349+ }
350+
332351 if err = issue .Comments .LoadAttributes (ctx ); err != nil {
333352 return err
334353 }
@@ -341,6 +360,11 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) {
341360 return issue .loadReactions (ctx )
342361}
343362
363+ // IsPinned returns if a Issue is pinned
364+ func (issue * Issue ) IsPinned () bool {
365+ return issue .PinOrder != 0
366+ }
367+
344368func (issue * Issue ) ResetAttributesLoaded () {
345369 issue .isLabelsLoaded = false
346370 issue .isMilestoneLoaded = false
@@ -680,190 +704,6 @@ func (issue *Issue) HasOriginalAuthor() bool {
680704 return issue .OriginalAuthor != "" && issue .OriginalAuthorID != 0
681705}
682706
683- var ErrIssueMaxPinReached = util .NewInvalidArgumentErrorf ("the max number of pinned issues has been readched" )
684-
685- // IsPinned returns if a Issue is pinned
686- func (issue * Issue ) IsPinned () bool {
687- return issue .PinOrder != 0
688- }
689-
690- // Pin pins a Issue
691- func (issue * Issue ) Pin (ctx context.Context , user * user_model.User ) error {
692- // If the Issue is already pinned, we don't need to pin it twice
693- if issue .IsPinned () {
694- return nil
695- }
696-
697- var maxPin int
698- _ , err := db .GetEngine (ctx ).SQL ("SELECT MAX(pin_order) FROM issue WHERE repo_id = ? AND is_pull = ?" , issue .RepoID , issue .IsPull ).Get (& maxPin )
699- if err != nil {
700- return err
701- }
702-
703- // Check if the maximum allowed Pins reached
704- if maxPin >= setting .Repository .Issue .MaxPinned {
705- return ErrIssueMaxPinReached
706- }
707-
708- _ , err = db .GetEngine (ctx ).Table ("issue" ).
709- Where ("id = ?" , issue .ID ).
710- Update (map [string ]any {
711- "pin_order" : maxPin + 1 ,
712- })
713- if err != nil {
714- return err
715- }
716-
717- // Add the pin event to the history
718- opts := & CreateCommentOptions {
719- Type : CommentTypePin ,
720- Doer : user ,
721- Repo : issue .Repo ,
722- Issue : issue ,
723- }
724- if _ , err = CreateComment (ctx , opts ); err != nil {
725- return err
726- }
727-
728- return nil
729- }
730-
731- // UnpinIssue unpins a Issue
732- func (issue * Issue ) Unpin (ctx context.Context , user * user_model.User ) error {
733- // If the Issue is not pinned, we don't need to unpin it
734- if ! issue .IsPinned () {
735- return nil
736- }
737-
738- // This sets the Pin for all Issues that come after the unpined Issue to the correct value
739- _ , err := db .GetEngine (ctx ).Exec ("UPDATE issue SET pin_order = pin_order - 1 WHERE repo_id = ? AND is_pull = ? AND pin_order > ?" , issue .RepoID , issue .IsPull , issue .PinOrder )
740- if err != nil {
741- return err
742- }
743-
744- _ , err = db .GetEngine (ctx ).Table ("issue" ).
745- Where ("id = ?" , issue .ID ).
746- Update (map [string ]any {
747- "pin_order" : 0 ,
748- })
749- if err != nil {
750- return err
751- }
752-
753- // Add the unpin event to the history
754- opts := & CreateCommentOptions {
755- Type : CommentTypeUnpin ,
756- Doer : user ,
757- Repo : issue .Repo ,
758- Issue : issue ,
759- }
760- if _ , err = CreateComment (ctx , opts ); err != nil {
761- return err
762- }
763-
764- return nil
765- }
766-
767- // PinOrUnpin pins or unpins a Issue
768- func (issue * Issue ) PinOrUnpin (ctx context.Context , user * user_model.User ) error {
769- if ! issue .IsPinned () {
770- return issue .Pin (ctx , user )
771- }
772-
773- return issue .Unpin (ctx , user )
774- }
775-
776- // MovePin moves a Pinned Issue to a new Position
777- func (issue * Issue ) MovePin (ctx context.Context , newPosition int ) error {
778- // If the Issue is not pinned, we can't move them
779- if ! issue .IsPinned () {
780- return nil
781- }
782-
783- if newPosition < 1 {
784- return fmt .Errorf ("The Position can't be lower than 1" )
785- }
786-
787- dbctx , committer , err := db .TxContext (ctx )
788- if err != nil {
789- return err
790- }
791- defer committer .Close ()
792-
793- var maxPin int
794- _ , err = db .GetEngine (dbctx ).SQL ("SELECT MAX(pin_order) FROM issue WHERE repo_id = ? AND is_pull = ?" , issue .RepoID , issue .IsPull ).Get (& maxPin )
795- if err != nil {
796- return err
797- }
798-
799- // If the new Position bigger than the current Maximum, set it to the Maximum
800- if newPosition > maxPin + 1 {
801- newPosition = maxPin + 1
802- }
803-
804- // Lower the Position of all Pinned Issue that came after the current Position
805- _ , err = db .GetEngine (dbctx ).Exec ("UPDATE issue SET pin_order = pin_order - 1 WHERE repo_id = ? AND is_pull = ? AND pin_order > ?" , issue .RepoID , issue .IsPull , issue .PinOrder )
806- if err != nil {
807- return err
808- }
809-
810- // Higher the Position of all Pinned Issues that comes after the new Position
811- _ , err = db .GetEngine (dbctx ).Exec ("UPDATE issue SET pin_order = pin_order + 1 WHERE repo_id = ? AND is_pull = ? AND pin_order >= ?" , issue .RepoID , issue .IsPull , newPosition )
812- if err != nil {
813- return err
814- }
815-
816- _ , err = db .GetEngine (dbctx ).Table ("issue" ).
817- Where ("id = ?" , issue .ID ).
818- Update (map [string ]any {
819- "pin_order" : newPosition ,
820- })
821- if err != nil {
822- return err
823- }
824-
825- return committer .Commit ()
826- }
827-
828- // GetPinnedIssues returns the pinned Issues for the given Repo and type
829- func GetPinnedIssues (ctx context.Context , repoID int64 , isPull bool ) (IssueList , error ) {
830- issues := make (IssueList , 0 )
831-
832- err := db .GetEngine (ctx ).
833- Table ("issue" ).
834- Where ("repo_id = ?" , repoID ).
835- And ("is_pull = ?" , isPull ).
836- And ("pin_order > 0" ).
837- OrderBy ("pin_order" ).
838- Find (& issues )
839- if err != nil {
840- return nil , err
841- }
842-
843- err = issues .LoadAttributes (ctx )
844- if err != nil {
845- return nil , err
846- }
847-
848- return issues , nil
849- }
850-
851- // IsNewPinAllowed returns if a new Issue or Pull request can be pinned
852- func IsNewPinAllowed (ctx context.Context , repoID int64 , isPull bool ) (bool , error ) {
853- var maxPin int
854- _ , err := db .GetEngine (ctx ).SQL ("SELECT COUNT(pin_order) FROM issue WHERE repo_id = ? AND is_pull = ? AND pin_order > 0" , repoID , isPull ).Get (& maxPin )
855- if err != nil {
856- return false , err
857- }
858-
859- return maxPin < setting .Repository .Issue .MaxPinned , nil
860- }
861-
862- // IsErrIssueMaxPinReached returns if the error is, that the User can't pin more Issues
863- func IsErrIssueMaxPinReached (err error ) bool {
864- return err == ErrIssueMaxPinReached
865- }
866-
867707// InsertIssues insert issues to database
868708func InsertIssues (ctx context.Context , issues ... * Issue ) error {
869709 ctx , committer , err := db .TxContext (ctx )
0 commit comments