From 0e74fc4a84fb27ad7b3aab87e1ef2b9be9d74815 Mon Sep 17 00:00:00 2001
From: CaiCandong <50507092+CaiCandong@users.noreply.github.com>
Date: Tue, 15 Aug 2023 22:50:12 +0800
Subject: [PATCH] Fix project filter bugs (#26490)

related: #26012

### Bugs
1. missing project filter on the issue page.

https://github.com/go-gitea/gitea/blob/1e76a824bcd71acd59cdfb2c4547806bc34b3d86/modules/indexer/issues/dboptions.go#L11-L15
3. incorrect SQL condition: some issue does not belong to a project but
exists on the project_issue table.

https://github.com/go-gitea/gitea/blob/f5dbac9d36f1678b928bee04e85fbd045c725698/models/issues/issue_search.go#L233

### Before:

![before](https://github.com/go-gitea/gitea/assets/50507092/1dcde39e-3e2f-4151-b2c6-4d67bf493c2f)

### After:

![after](https://github.com/go-gitea/gitea/assets/50507092/badfb81f-056d-4a2f-9838-1cba9c15768d)

---------

Co-authored-by: Giteabot <teabot@gitea.io>
---
 models/issues/issue_search.go       | 19 +++++++++++++------
 models/issues/issue_stats.go        |  5 +----
 modules/indexer/issues/dboptions.go |  4 ++++
 3 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/models/issues/issue_search.go b/models/issues/issue_search.go
index 281339044b..3640351a4d 100644
--- a/models/issues/issue_search.go
+++ b/models/issues/issue_search.go
@@ -168,6 +168,18 @@ func applyMilestoneCondition(sess *xorm.Session, opts *IssuesOptions) *xorm.Sess
 	return sess
 }
 
+func applyProjectCondition(sess *xorm.Session, opts *IssuesOptions) *xorm.Session {
+	if opts.ProjectID > 0 { // specific project
+		sess.Join("INNER", "project_issue", "issue.id = project_issue.issue_id").
+			And("project_issue.project_id=?", opts.ProjectID)
+	} else if opts.ProjectID == db.NoConditionID { // show those that are in no project
+		sess.And(builder.NotIn("issue.id", builder.Select("issue_id").From("project_issue").And(builder.Neq{"project_id": 0})))
+	}
+	// opts.ProjectID == 0 means all projects,
+	// do not need to apply any condition
+	return sess
+}
+
 func applyRepoConditions(sess *xorm.Session, opts *IssuesOptions) *xorm.Session {
 	if len(opts.RepoIDs) == 1 {
 		opts.RepoCond = builder.Eq{"issue.repo_id": opts.RepoIDs[0]}
@@ -226,12 +238,7 @@ func applyConditions(sess *xorm.Session, opts *IssuesOptions) *xorm.Session {
 		sess.And(builder.Lte{"issue.updated_unix": opts.UpdatedBeforeUnix})
 	}
 
-	if opts.ProjectID > 0 {
-		sess.Join("INNER", "project_issue", "issue.id = project_issue.issue_id").
-			And("project_issue.project_id=?", opts.ProjectID)
-	} else if opts.ProjectID == db.NoConditionID { // show those that are in no project
-		sess.And(builder.NotIn("issue.id", builder.Select("issue_id").From("project_issue")))
-	}
+	applyProjectCondition(sess, opts)
 
 	if opts.ProjectBoardID != 0 {
 		if opts.ProjectBoardID > 0 {
diff --git a/models/issues/issue_stats.go b/models/issues/issue_stats.go
index d86123a824..6c249c2244 100644
--- a/models/issues/issue_stats.go
+++ b/models/issues/issue_stats.go
@@ -133,10 +133,7 @@ func getIssueStatsChunk(opts *IssuesOptions, issueIDs []int64) (*IssueStats, err
 
 		applyMilestoneCondition(sess, opts)
 
-		if opts.ProjectID > 0 {
-			sess.Join("INNER", "project_issue", "issue.id = project_issue.issue_id").
-				And("project_issue.project_id=?", opts.ProjectID)
-		}
+		applyProjectCondition(sess, opts)
 
 		if opts.AssigneeID > 0 {
 			applyAssigneeCondition(sess, opts.AssigneeID)
diff --git a/modules/indexer/issues/dboptions.go b/modules/indexer/issues/dboptions.go
index 6a41afadd7..d0ef1c96b4 100644
--- a/modules/indexer/issues/dboptions.go
+++ b/modules/indexer/issues/dboptions.go
@@ -17,6 +17,10 @@ func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOp
 		IsClosed:  opts.IsClosed,
 	}
 
+	if opts.ProjectID != 0 {
+		searchOpt.ProjectID = &opts.ProjectID
+	}
+
 	if len(opts.LabelIDs) == 1 && opts.LabelIDs[0] == 0 {
 		searchOpt.NoLabelOnly = true
 	} else {