flamingo.me/flamingo-commerce/v3@v3.11.0/category/interfaces/controller/querycommand.go (about)

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