Skip to content

Commit

Permalink
Merge branch 'dev' into test
Browse files Browse the repository at this point in the history
  • Loading branch information
LinkinStars committed Oct 18, 2024
2 parents 1997af8 + 23cc755 commit fe1576b
Show file tree
Hide file tree
Showing 15 changed files with 324 additions and 97 deletions.
4 changes: 2 additions & 2 deletions cmd/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions internal/base/pager/pagination.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,15 @@ func ValPageAndPageSize(page, pageSize int) (int, int) {
}
return page, pageSize
}

// ValPageOutOfRange validate page out of range
func ValPageOutOfRange(total int64, page, pageSize int) bool {
if total <= 0 {
return false
}
if pageSize <= 0 {
return true
}
totalPages := (total + int64(pageSize) - 1) / int64(pageSize)
return page < 1 || page > int(totalPages)
}
4 changes: 4 additions & 0 deletions internal/controller/question_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,10 @@ func (qc *QuestionController) QuestionPage(ctx *gin.Context) {
handler.HandleResponse(ctx, err, nil)
return
}
if pager.ValPageOutOfRange(total, req.Page, req.PageSize) {
handler.HandleResponse(ctx, errors.NotFound(reason.RequestFormatError), nil)
return
}
handler.HandleResponse(ctx, nil, pager.NewPageModel(total, questions))
}

Expand Down
5 changes: 5 additions & 0 deletions internal/controller/tag_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package controller
import (
"github.com/apache/incubator-answer/internal/base/handler"
"github.com/apache/incubator-answer/internal/base/middleware"
"github.com/apache/incubator-answer/internal/base/pager"
"github.com/apache/incubator-answer/internal/base/reason"
"github.com/apache/incubator-answer/internal/schema"
"github.com/apache/incubator-answer/internal/service/permission"
Expand Down Expand Up @@ -269,6 +270,10 @@ func (tc *TagController) GetTagWithPage(ctx *gin.Context) {
req.UserID = middleware.GetLoginUserIDFromContext(ctx)

resp, err := tc.tagService.GetTagWithPage(ctx, req)
if pager.ValPageOutOfRange(resp.Count, req.Page, req.PageSize) {
handler.HandleResponse(ctx, errors.NotFound(reason.RequestFormatError), nil)
return
}
handler.HandleResponse(ctx, err, resp)
}

Expand Down
78 changes: 58 additions & 20 deletions internal/controller/template_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ package controller
import (
"encoding/json"
"fmt"
"github.com/apache/incubator-answer/internal/base/middleware"
"github.com/apache/incubator-answer/internal/base/pager"
"github.com/apache/incubator-answer/internal/service/content"
"github.com/apache/incubator-answer/internal/service/event_queue"
"github.com/apache/incubator-answer/plugin"
Expand Down Expand Up @@ -58,6 +60,7 @@ type TemplateController struct {
siteInfoService siteinfo_common.SiteInfoCommonService
eventQueueService event_queue.EventQueueService
userService *content.UserService
questionService *content.QuestionService
}

// NewTemplateController new controller
Expand All @@ -66,6 +69,7 @@ func NewTemplateController(
siteInfoService siteinfo_common.SiteInfoCommonService,
eventQueueService event_queue.EventQueueService,
userService *content.UserService,
questionService *content.QuestionService,
) *TemplateController {
script, css := GetStyle()
return &TemplateController{
Expand All @@ -75,6 +79,7 @@ func NewTemplateController(
siteInfoService: siteInfoService,
eventQueueService: eventQueueService,
userService: userService,
questionService: questionService,
}
}
func GetStyle() (script []string, css string) {
Expand Down Expand Up @@ -141,11 +146,19 @@ func (tc *TemplateController) Index(ctx *gin.Context) {
var page = req.Page

data, count, err := tc.templateRenderController.Index(ctx, req)
if err != nil {
if err != nil || (len(data) == 0 && pager.ValPageOutOfRange(count, page, req.PageSize)) {
tc.Page404(ctx)
return
}

hotQuestionReq := &schema.QuestionPageReq{
Page: 1,
PageSize: 6,
OrderCond: "hot",
InDays: 7,
}
hotQuestion, _, _ := tc.templateRenderController.Index(ctx, hotQuestionReq)

siteInfo := tc.SiteInfo(ctx)
siteInfo.Canonical = siteInfo.General.SiteUrl

Expand All @@ -156,10 +169,11 @@ func (tc *TemplateController) Index(ctx *gin.Context) {
}
siteInfo.Title = ""
tc.html(ctx, http.StatusOK, "question.html", siteInfo, gin.H{
"data": data,
"useTitle": UrlUseTitle,
"page": templaterender.Paginator(page, req.PageSize, count),
"path": "questions",
"data": data,
"useTitle": UrlUseTitle,
"page": templaterender.Paginator(page, req.PageSize, count),
"path": "questions",
"hotQuestion": hotQuestion,
})
}

Expand All @@ -173,10 +187,19 @@ func (tc *TemplateController) QuestionList(ctx *gin.Context) {
}
var page = req.Page
data, count, err := tc.templateRenderController.Index(ctx, req)
if err != nil {
if err != nil || (len(data) == 0 && pager.ValPageOutOfRange(count, page, req.PageSize)) {
tc.Page404(ctx)
return
}

hotQuestionReq := &schema.QuestionPageReq{
Page: 1,
PageSize: 6,
OrderCond: "hot",
InDays: 7,
}
hotQuestion, _, _ := tc.templateRenderController.Index(ctx, hotQuestionReq)

siteInfo := tc.SiteInfo(ctx)
siteInfo.Canonical = fmt.Sprintf("%s/questions", siteInfo.General.SiteUrl)
if page > 1 {
Expand All @@ -190,13 +213,14 @@ func (tc *TemplateController) QuestionList(ctx *gin.Context) {
}
siteInfo.Title = fmt.Sprintf("%s - %s", translator.Tr(handler.GetLang(ctx), constant.QuestionsTitleTrKey), siteInfo.General.Name)
tc.html(ctx, http.StatusOK, "question.html", siteInfo, gin.H{
"data": data,
"useTitle": UrlUseTitle,
"page": templaterender.Paginator(page, req.PageSize, count),
"data": data,
"useTitle": UrlUseTitle,
"page": templaterender.Paginator(page, req.PageSize, count),
"hotQuestion": hotQuestion,
})
}

func (tc *TemplateController) QuestionInfoeRdirect(ctx *gin.Context, siteInfo *schema.TemplateSiteInfoResp, correctTitle bool) (jump bool, url string) {
func (tc *TemplateController) QuestionInfoRedirect(ctx *gin.Context, siteInfo *schema.TemplateSiteInfoResp, correctTitle bool) (jump bool, url string) {
questionID := ctx.Param("id")
title := ctx.Param("title")
answerID := uid.DeShortID(title)
Expand Down Expand Up @@ -316,7 +340,7 @@ func (tc *TemplateController) QuestionInfo(ctx *gin.Context) {
}

siteInfo := tc.SiteInfo(ctx)
jump, jumpurl := tc.QuestionInfoeRdirect(ctx, siteInfo, correctTitle)
jump, jumpurl := tc.QuestionInfoRedirect(ctx, siteInfo, correctTitle)
if jump {
ctx.Redirect(http.StatusFound, jumpurl)
return
Expand All @@ -337,7 +361,6 @@ func (tc *TemplateController) QuestionInfo(ctx *gin.Context) {
}

// comments

objectIDs := []string{uid.DeShortID(id)}
for _, answer := range answers {
answerID := uid.DeShortID(answer.ID)
Expand All @@ -348,6 +371,17 @@ func (tc *TemplateController) QuestionInfo(ctx *gin.Context) {
tc.Page404(ctx)
return
}

UrlUseTitle := false
if siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitle ||
siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitleByShortID {
UrlUseTitle = true
}

//related question
userID := middleware.GetLoginUserIDFromContext(ctx)
relatedQuestion, _, _ := tc.questionService.SimilarQuestion(ctx, id, userID)

siteInfo.Canonical = fmt.Sprintf("%s/questions/%s/%s", siteInfo.General.SiteUrl, id, encodeTitle)
if siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionID || siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDByShortID {
siteInfo.Canonical = fmt.Sprintf("%s/questions/%s", siteInfo.General.SiteUrl, id)
Expand Down Expand Up @@ -389,7 +423,6 @@ func (tc *TemplateController) QuestionInfo(ctx *gin.Context) {
item.Author.URL = fmt.Sprintf("%s/users/%s", siteInfo.General.SiteUrl, answer.UserInfo.Username)
answerList = append(answerList, item)
}

}
jsonLD.MainEntity.SuggestedAnswer = answerList
jsonLDStr, err := json.Marshal(jsonLD)
Expand All @@ -405,12 +438,14 @@ func (tc *TemplateController) QuestionInfo(ctx *gin.Context) {
siteInfo.Keywords = strings.Replace(strings.Trim(fmt.Sprint(tags), "[]"), " ", ",", -1)
siteInfo.Title = fmt.Sprintf("%s - %s", detail.Title, siteInfo.General.Name)
tc.html(ctx, http.StatusOK, "question-detail.html", siteInfo, gin.H{
"id": id,
"answerid": answerid,
"detail": detail,
"answers": answers,
"comments": comments,
"noindex": detail.Show == entity.QuestionHide,
"id": id,
"answerid": answerid,
"detail": detail,
"answers": answers,
"comments": comments,
"noindex": detail.Show == entity.QuestionHide,
"useTitle": UrlUseTitle,
"relatedQuestion": relatedQuestion,
})
}

Expand All @@ -420,8 +455,11 @@ func (tc *TemplateController) TagList(ctx *gin.Context) {
if handler.BindAndCheck(ctx, req) {
return
}
if req.PageSize == 0 {
req.PageSize = constant.DefaultPageSize
}
data, err := tc.templateRenderController.TagList(ctx, req)
if err != nil {
if err != nil || pager.ValPageOutOfRange(data.Count, req.Page, req.PageSize) {
tc.Page404(ctx)
return
}
Expand Down
4 changes: 4 additions & 0 deletions internal/service/content/question_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@ func (qs *QuestionService) CloseQuestion(ctx context.Context, req *schema.CloseQ
if err != nil {
return err
}
if cf.Key == constant.ReasonADuplicate {
qs.questioncommon.AddQuestionLinkForCloseReason(ctx, questionInfo, req.CloseMsg)
}

qs.activityQueueService.Send(ctx, &schema.ActivityMsg{
UserID: req.UserID,
Expand All @@ -199,6 +202,7 @@ func (qs *QuestionService) ReopenQuestion(ctx context.Context, req *schema.Reope
if err != nil {
return err
}
qs.questioncommon.RemoveQuestionLinkForReopen(ctx, questionInfo)
qs.activityQueueService.Send(ctx, &schema.ActivityMsg{
UserID: req.UserID,
ObjectID: questionInfo.ID,
Expand Down
76 changes: 76 additions & 0 deletions internal/service/question_common/question.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/apache/incubator-answer/internal/service/siteinfo_common"
"math"
"strings"
"time"
Expand Down Expand Up @@ -98,6 +99,7 @@ type QuestionCommon struct {
configService *config.ConfigService
activityQueueService activity_queue.ActivityQueueService
revisionRepo revision.RevisionRepo
siteInfoService siteinfo_common.SiteInfoCommonService
data *data.Data
}

Expand All @@ -113,6 +115,7 @@ func NewQuestionCommon(questionRepo QuestionRepo,
configService *config.ConfigService,
activityQueueService activity_queue.ActivityQueueService,
revisionRepo revision.RevisionRepo,
siteInfoService siteinfo_common.SiteInfoCommonService,
data *data.Data,
) *QuestionCommon {
return &QuestionCommon{
Expand All @@ -128,6 +131,7 @@ func NewQuestionCommon(questionRepo QuestionRepo,
configService: configService,
activityQueueService: activityQueueService,
revisionRepo: revisionRepo,
siteInfoService: siteInfoService,
data: data,
}
}
Expand Down Expand Up @@ -795,3 +799,75 @@ func (qs *QuestionCommon) UpdateQuestionLink(ctx context.Context, questionID, an

return parsedText, nil
}

// AddQuestionLinkForCloseReason When the reason about close question is a question link, add the link to the question
func (qs *QuestionCommon) AddQuestionLinkForCloseReason(ctx context.Context,
questionInfo *entity.Question, closeMsg string) {
questionID := qs.tryToGetQuestionIDFromMsg(ctx, closeMsg)
if len(questionID) == 0 {
return
}

linkedQuestion, exist, err := qs.questionRepo.GetQuestion(ctx, questionID)
if err != nil {
log.Errorf("get question error %s", err)
return
}
if !exist {
return
}
err = qs.questionRepo.LinkQuestion(ctx, &entity.QuestionLink{
FromQuestionID: questionInfo.ID,
ToQuestionID: linkedQuestion.ID,
Status: entity.QuestionLinkStatusAvailable,
})
if err != nil {
log.Errorf("link question error %s", err)
}
}

func (qs *QuestionCommon) RemoveQuestionLinkForReopen(ctx context.Context, questionInfo *entity.Question) {
questionInfo.ID = uid.DeShortID(questionInfo.ID)
metaInfo, err := qs.metaCommonService.GetMetaByObjectIdAndKey(ctx, questionInfo.ID, entity.QuestionCloseReasonKey)
if err != nil {
return
}

closeMsgMeta := &schema.CloseQuestionMeta{}
_ = json.Unmarshal([]byte(metaInfo.Value), closeMsgMeta)

linkedQuestionID := qs.tryToGetQuestionIDFromMsg(ctx, closeMsgMeta.CloseMsg)
if len(linkedQuestionID) == 0 {
return
}
err = qs.questionRepo.RemoveQuestionLink(ctx, &entity.QuestionLink{
FromQuestionID: questionInfo.ID,
ToQuestionID: linkedQuestionID,
})
if err != nil {
log.Errorf("remove question link error %s", err)
}
}

func (qs *QuestionCommon) tryToGetQuestionIDFromMsg(ctx context.Context, closeMsg string) (questionID string) {
siteGeneral, err := qs.siteInfoService.GetSiteGeneral(ctx)
if err != nil {
log.Errorf("get site general error %s", err)
return
}
if !strings.HasPrefix(closeMsg, siteGeneral.SiteUrl) {
return
}
// get question id from url
// the url may like: https://xxx.com/questions/D1401/xxx
// the D1401 is question id
questionID = strings.TrimPrefix(closeMsg, siteGeneral.SiteUrl)
questionID = strings.TrimPrefix(questionID, "/questions/")
t := strings.Split(questionID, "/")
if len(t) < 1 {
return ""
}
questionID = t[0]
questionID = uid.DeShortID(questionID)
return questionID
}
1 change: 0 additions & 1 deletion internal/service/tag/tag_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,6 @@ func (ts *TagService) GetTagWithPage(ctx context.Context, req *schema.GetTagWith
}
item.GetExcerpt()
resp = append(resp, item)

}
return pager.NewPageModel(total, resp), nil
}
Expand Down
Loading

0 comments on commit fe1576b

Please sign in to comment.