diff --git a/api/entry.go b/api/entry.go index f0a0f996..9fcfa603 100644 --- a/api/entry.go +++ b/api/entry.go @@ -111,8 +111,8 @@ func (h *handler) getFeedEntries(w http.ResponseWriter, r *http.Request) { } func (h *handler) getEntries(w http.ResponseWriter, r *http.Request) { - status := request.QueryStringParam(r, "status", "") - if status != "" { + statuses := request.QueryStringParamList(r, "status") + for _, status := range statuses { if err := model.ValidateEntryStatus(status); err != nil { json.BadRequest(w, r, err) return @@ -139,7 +139,7 @@ func (h *handler) getEntries(w http.ResponseWriter, r *http.Request) { } builder := h.store.NewEntryQueryBuilder(request.UserID(r)) - builder.WithStatus(status) + builder.WithStatuses(statuses) builder.WithOrder(order) builder.WithDirection(direction) builder.WithOffset(offset) diff --git a/http/request/params.go b/http/request/params.go index 8218a0d7..5f83aa4b 100644 --- a/http/request/params.go +++ b/http/request/params.go @@ -7,6 +7,7 @@ package request // import "miniflux.app/http/request" import ( "net/http" "strconv" + "strings" "github.com/gorilla/mux" ) @@ -52,6 +53,23 @@ func QueryStringParam(r *http.Request, param, defaultValue string) string { return value } +// QueryStringParamList returns all values associated to the parameter. +func QueryStringParamList(r *http.Request, param string) []string { + var results []string + values := r.URL.Query() + + if _, found := values[param]; found { + for _, value := range values[param] { + value = strings.TrimSpace(value) + if value != "" { + results = append(results, value) + } + } + } + + return results +} + // QueryIntParam returns a query string parameter as integer. func QueryIntParam(r *http.Request, param string, defaultValue int) int { return int(QueryInt64Param(r, param, int64(defaultValue))) diff --git a/storage/entry_query_builder.go b/storage/entry_query_builder.go index 891a4d2e..c1f1defd 100644 --- a/storage/entry_query_builder.go +++ b/storage/entry_query_builder.go @@ -78,14 +78,14 @@ func (e *EntryQueryBuilder) AfterEntryID(entryID int64) *EntryQueryBuilder { return e } -// WithEntryIDs adds a condition to fetch only the given entry IDs. +// WithEntryIDs filter by entry IDs. func (e *EntryQueryBuilder) WithEntryIDs(entryIDs []int64) *EntryQueryBuilder { e.conditions = append(e.conditions, fmt.Sprintf("e.id = ANY($%d)", len(e.args)+1)) - e.args = append(e.args, pq.Array(entryIDs)) + e.args = append(e.args, pq.Int64Array(entryIDs)) return e } -// WithEntryID set the entryID. +// WithEntryID filter by entry ID. func (e *EntryQueryBuilder) WithEntryID(entryID int64) *EntryQueryBuilder { if entryID != 0 { e.conditions = append(e.conditions, fmt.Sprintf("e.id = $%d", len(e.args)+1)) @@ -94,7 +94,7 @@ func (e *EntryQueryBuilder) WithEntryID(entryID int64) *EntryQueryBuilder { return e } -// WithFeedID set the feedID. +// WithFeedID filter by feed ID. func (e *EntryQueryBuilder) WithFeedID(feedID int64) *EntryQueryBuilder { if feedID != 0 { e.conditions = append(e.conditions, fmt.Sprintf("e.feed_id = $%d", len(e.args)+1)) @@ -103,7 +103,7 @@ func (e *EntryQueryBuilder) WithFeedID(feedID int64) *EntryQueryBuilder { return e } -// WithCategoryID set the categoryID. +// WithCategoryID filter by category ID. func (e *EntryQueryBuilder) WithCategoryID(categoryID int64) *EntryQueryBuilder { if categoryID > 0 { e.conditions = append(e.conditions, fmt.Sprintf("f.category_id = $%d", len(e.args)+1)) @@ -112,7 +112,7 @@ func (e *EntryQueryBuilder) WithCategoryID(categoryID int64) *EntryQueryBuilder return e } -// WithStatus set the entry status. +// WithStatus filter by entry status. func (e *EntryQueryBuilder) WithStatus(status string) *EntryQueryBuilder { if status != "" { e.conditions = append(e.conditions, fmt.Sprintf("e.status = $%d", len(e.args)+1)) @@ -121,6 +121,15 @@ func (e *EntryQueryBuilder) WithStatus(status string) *EntryQueryBuilder { return e } +// WithStatuses filter by a list of entry statuses. +func (e *EntryQueryBuilder) WithStatuses(statuses []string) *EntryQueryBuilder { + if len(statuses) > 0 { + e.conditions = append(e.conditions, fmt.Sprintf("e.status = ANY($%d)", len(e.args)+1)) + e.args = append(e.args, pq.StringArray(statuses)) + } + return e +} + // WithoutStatus set the entry status that should not be returned. func (e *EntryQueryBuilder) WithoutStatus(status string) *EntryQueryBuilder { if status != "" {