/
querycommand.go
114 lines (95 loc) · 3.28 KB
/
querycommand.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package controller
import (
"context"
"net/url"
"strconv"
"flamingo.me/flamingo/v3/framework/web"
"flamingo.me/flamingo-commerce/v3/category/domain"
productApplication "flamingo.me/flamingo-commerce/v3/product/application"
searchApplication "flamingo.me/flamingo-commerce/v3/search/application"
searchDomain "flamingo.me/flamingo-commerce/v3/search/domain"
"flamingo.me/flamingo-commerce/v3/search/utils"
)
type (
// QueryHandler provides the base command logic that is agnostic to the actual view type
QueryHandler interface {
Execute(ctx context.Context, req Request) (*Result, *RedirectResult, error)
}
// ProductSearchService interface that describes the expected dependency. (Is fulfilled by the product package)
ProductSearchService interface {
Find(ctx context.Context, searchRequest *searchApplication.SearchRequest) (*productApplication.SearchResult, error)
}
// QueryHandlerImpl is the default implementation of QueryHandler
QueryHandlerImpl struct {
categoryService domain.CategoryService
productSearchService ProductSearchService
}
// Request is a request for a category view
Request struct {
Code string
Name string
QueryAll url.Values
URL url.URL
}
// Result for found category
Result struct {
ProductSearchResult *productApplication.SearchResult
Category domain.Category
CategoryTree domain.Tree
SearchMeta searchDomain.SearchMeta
PaginationInfo utils.PaginationInfo
}
// RedirectResult signals that a request for a category view shall be redirected using the defined parameters
RedirectResult struct {
Code string
Name string
}
)
var _ QueryHandler = (*QueryHandlerImpl)(nil)
// Inject injects dependencies
func (c *QueryHandlerImpl) Inject(
categoryService domain.CategoryService,
searchService ProductSearchService,
) {
c.categoryService = categoryService
c.productSearchService = searchService
}
// Execute Action to display a category page for any view
// error might be domain.ErrNotFound to indicate that the category was not found
func (c *QueryHandlerImpl) Execute(ctx context.Context, req Request) (*Result, *RedirectResult, error) {
treeRoot, err := c.categoryService.Tree(ctx, req.Code)
if err != nil {
return nil, nil, err
}
currentCategory, err := c.categoryService.Get(ctx, req.Code)
if err != nil {
return nil, nil, err
}
// Normalize url if required:
expectedName := web.URLTitle(currentCategory.Name())
if expectedName != req.Name {
return nil, &RedirectResult{Code: currentCategory.Code(), Name: expectedName}, nil
}
searchRequest := &searchApplication.SearchRequest{}
for k, v := range req.QueryAll {
switch k {
case "page":
page, _ := strconv.ParseInt(v[0], 10, 64)
searchRequest.SetAdditionalFilter(searchDomain.NewPaginationPageFilter(int(page)))
default:
searchRequest.SetAdditionalFilter(searchDomain.NewKeyValueFilter(k, v))
}
}
searchRequest.SetAdditionalFilter(domain.NewCategoryFacet(currentCategory.Code()))
products, err := c.productSearchService.Find(ctx, searchRequest)
if err != nil {
return nil, nil, err
}
return &Result{
Category: currentCategory,
CategoryTree: treeRoot,
ProductSearchResult: products,
SearchMeta: products.SearchMeta,
PaginationInfo: products.PaginationInfo,
}, nil, nil
}