mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-03 18:22:57 +00:00
238 lines
6.1 KiB
Go
238 lines
6.1 KiB
Go
package controllers
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// QueryHelper provides query parameter parsing and filtering utilities
|
|
type QueryHelper struct{}
|
|
|
|
// SortParams represents sorting parameters
|
|
type SortParams struct {
|
|
Field string
|
|
Order string // "asc" or "desc"
|
|
}
|
|
|
|
// FilterParams represents generic filter parameters
|
|
type FilterParams map[string]interface{}
|
|
|
|
// NewQueryHelper creates a new QueryHelper instance
|
|
func NewQueryHelper() *QueryHelper {
|
|
return &QueryHelper{}
|
|
}
|
|
|
|
// GetSortParams extracts sort parameters from the request
|
|
// Expects: ?sort=field:order (e.g., ?sort=created_at:desc)
|
|
func (qh *QueryHelper) GetSortParams(c *gin.Context, defaultField, defaultOrder string) SortParams {
|
|
sortQuery := c.Query("sort")
|
|
if sortQuery == "" {
|
|
return SortParams{
|
|
Field: defaultField,
|
|
Order: defaultOrder,
|
|
}
|
|
}
|
|
|
|
parts := strings.Split(sortQuery, ":")
|
|
field := parts[0]
|
|
order := defaultOrder
|
|
|
|
if len(parts) > 1 {
|
|
order = strings.ToLower(parts[1])
|
|
if order != "asc" && order != "desc" {
|
|
order = defaultOrder
|
|
}
|
|
}
|
|
|
|
return SortParams{
|
|
Field: field,
|
|
Order: order,
|
|
}
|
|
}
|
|
|
|
// ApplySort applies sorting to a GORM query
|
|
func (qh *QueryHelper) ApplySort(db *gorm.DB, params SortParams) *gorm.DB {
|
|
if params.Field != "" {
|
|
return db.Order(params.Field + " " + params.Order)
|
|
}
|
|
return db
|
|
}
|
|
|
|
// ApplySortFromContext extracts sort params from context and applies them
|
|
func (qh *QueryHelper) ApplySortFromContext(c *gin.Context, db *gorm.DB, defaultField, defaultOrder string) *gorm.DB {
|
|
params := qh.GetSortParams(c, defaultField, defaultOrder)
|
|
return qh.ApplySort(db, params)
|
|
}
|
|
|
|
// GetSearchQuery extracts search query from request
|
|
// Expects: ?search=term or ?q=term
|
|
func (qh *QueryHelper) GetSearchQuery(c *gin.Context) string {
|
|
search := c.Query("search")
|
|
if search == "" {
|
|
search = c.Query("q")
|
|
}
|
|
return strings.TrimSpace(search)
|
|
}
|
|
|
|
// ApplySearch applies search to specified fields using LIKE
|
|
func (qh *QueryHelper) ApplySearch(db *gorm.DB, searchTerm string, fields ...string) *gorm.DB {
|
|
if searchTerm == "" || len(fields) == 0 {
|
|
return db
|
|
}
|
|
|
|
searchPattern := "%" + searchTerm + "%"
|
|
query := db
|
|
|
|
// Build OR conditions for each field
|
|
for i, field := range fields {
|
|
if i == 0 {
|
|
query = query.Where(field+" LIKE ?", searchPattern)
|
|
} else {
|
|
query = query.Or(field+" LIKE ?", searchPattern)
|
|
}
|
|
}
|
|
|
|
return query
|
|
}
|
|
|
|
// ApplySearchFromContext extracts search query and applies it
|
|
func (qh *QueryHelper) ApplySearchFromContext(c *gin.Context, db *gorm.DB, fields ...string) *gorm.DB {
|
|
searchTerm := qh.GetSearchQuery(c)
|
|
return qh.ApplySearch(db, searchTerm, fields...)
|
|
}
|
|
|
|
// GetBoolQuery extracts a boolean query parameter
|
|
func (qh *QueryHelper) GetBoolQuery(c *gin.Context, key string) *bool {
|
|
value := c.Query(key)
|
|
if value == "" {
|
|
return nil
|
|
}
|
|
|
|
boolValue := strings.ToLower(value) == "true" || value == "1"
|
|
return &boolValue
|
|
}
|
|
|
|
// ApplyBoolFilter applies a boolean filter if the parameter exists
|
|
func (qh *QueryHelper) ApplyBoolFilter(db *gorm.DB, c *gin.Context, paramKey, dbField string) *gorm.DB {
|
|
value := qh.GetBoolQuery(c, paramKey)
|
|
if value != nil {
|
|
return db.Where(dbField+" = ?", *value)
|
|
}
|
|
return db
|
|
}
|
|
|
|
// GetIDsFromQuery extracts comma-separated IDs from query parameter
|
|
// Expects: ?ids=1,2,3,4
|
|
func (qh *QueryHelper) GetIDsFromQuery(c *gin.Context, key string) []uint {
|
|
idsStr := c.Query(key)
|
|
if idsStr == "" {
|
|
return nil
|
|
}
|
|
|
|
parts := strings.Split(idsStr, ",")
|
|
ids := make([]uint, 0, len(parts))
|
|
|
|
for _, part := range parts {
|
|
part = strings.TrimSpace(part)
|
|
if part == "" {
|
|
continue
|
|
}
|
|
|
|
// Parse as uint
|
|
var id uint
|
|
if _, err := fmt.Sscanf(part, "%d", &id); err == nil {
|
|
ids = append(ids, id)
|
|
}
|
|
}
|
|
|
|
return ids
|
|
}
|
|
|
|
// ApplyIDsFilter applies IN filter for IDs
|
|
func (qh *QueryHelper) ApplyIDsFilter(db *gorm.DB, c *gin.Context, paramKey, dbField string) *gorm.DB {
|
|
ids := qh.GetIDsFromQuery(c, paramKey)
|
|
if len(ids) > 0 {
|
|
return db.Where(dbField+" IN ?", ids)
|
|
}
|
|
return db
|
|
}
|
|
|
|
// GetDateRange extracts date range from query parameters
|
|
// Expects: ?from=2024-01-01&to=2024-12-31
|
|
func (qh *QueryHelper) GetDateRange(c *gin.Context) (from, to string) {
|
|
from = c.Query("from")
|
|
to = c.Query("to")
|
|
return
|
|
}
|
|
|
|
// ApplyDateRangeFilter applies date range filter
|
|
func (qh *QueryHelper) ApplyDateRangeFilter(db *gorm.DB, c *gin.Context, dbField string) *gorm.DB {
|
|
from, to := qh.GetDateRange(c)
|
|
|
|
if from != "" {
|
|
db = db.Where(dbField+" >= ?", from)
|
|
}
|
|
if to != "" {
|
|
db = db.Where(dbField+" <= ?", to)
|
|
}
|
|
|
|
return db
|
|
}
|
|
|
|
// BuildQueryChain combines multiple query operations
|
|
func (qh *QueryHelper) BuildQueryChain(c *gin.Context, db *gorm.DB) *QueryChainBuilder {
|
|
return &QueryChainBuilder{
|
|
ctx: c,
|
|
query: db,
|
|
qh: qh,
|
|
}
|
|
}
|
|
|
|
// QueryChainBuilder provides a fluent interface for building queries
|
|
type QueryChainBuilder struct {
|
|
ctx *gin.Context
|
|
query *gorm.DB
|
|
qh *QueryHelper
|
|
}
|
|
|
|
// WithSort adds sorting
|
|
func (qcb *QueryChainBuilder) WithSort(defaultField, defaultOrder string) *QueryChainBuilder {
|
|
qcb.query = qcb.qh.ApplySortFromContext(qcb.ctx, qcb.query, defaultField, defaultOrder)
|
|
return qcb
|
|
}
|
|
|
|
// WithSearch adds search across fields
|
|
func (qcb *QueryChainBuilder) WithSearch(fields ...string) *QueryChainBuilder {
|
|
qcb.query = qcb.qh.ApplySearchFromContext(qcb.ctx, qcb.query, fields...)
|
|
return qcb
|
|
}
|
|
|
|
// WithBoolFilter adds a boolean filter
|
|
func (qcb *QueryChainBuilder) WithBoolFilter(paramKey, dbField string) *QueryChainBuilder {
|
|
qcb.query = qcb.qh.ApplyBoolFilter(qcb.query, qcb.ctx, paramKey, dbField)
|
|
return qcb
|
|
}
|
|
|
|
// WithIDsFilter adds an IDs filter
|
|
func (qcb *QueryChainBuilder) WithIDsFilter(paramKey, dbField string) *QueryChainBuilder {
|
|
qcb.query = qcb.qh.ApplyIDsFilter(qcb.query, qcb.ctx, paramKey, dbField)
|
|
return qcb
|
|
}
|
|
|
|
// WithDateRange adds date range filter
|
|
func (qcb *QueryChainBuilder) WithDateRange(dbField string) *QueryChainBuilder {
|
|
qcb.query = qcb.qh.ApplyDateRangeFilter(qcb.query, qcb.ctx, dbField)
|
|
return qcb
|
|
}
|
|
|
|
// Build returns the final query
|
|
func (qcb *QueryChainBuilder) Build() *gorm.DB {
|
|
return qcb.query
|
|
}
|
|
|
|
// Global QueryHelper instance for convenience
|
|
var QueryParser = NewQueryHelper()
|