예제 #1
0
        public virtual T AsCriteria <T>(string storeId, string catalog, ISearchFilter[] filters)
            where T : CatalogItemSearchCriteria, new()
        {
            var criteria = AbstractTypeFactory <T> .TryCreateInstance();

            criteria.Ids               = ProductIds;
            criteria.Currency          = Currency;
            criteria.Pricelists        = PriceLists;
            criteria.SearchPhrase      = SearchPhrase;
            criteria.Locale            = Locale;
            criteria.StartingRecord    = Skip;
            criteria.RecordsToRetrieve = Take;

            // add outline
            if (!string.IsNullOrEmpty(Outline))
            {
                criteria.Outlines.Add(string.Join("/", catalog, Outline));
            }
            else
            {
                criteria.Outlines.Add(catalog ?? string.Empty);
            }

            // Add all filters
            foreach (var filter in filters)
            {
                criteria.Add(filter);
            }

            #region Filters

            var terms = Terms.AsKeyValues();
            if (terms.Any())
            {
                var filtersWithValues = filters
                                        .Where(x => (!(x is PriceRangeFilter) || ((PriceRangeFilter)x).Currency.Equals(Currency, StringComparison.OrdinalIgnoreCase)))
                                        .Select(x => new { Filter = x, Values = x.GetValues() })
                                        .ToList();

                foreach (var term in terms)
                {
                    var filter = filters.SingleOrDefault(x => x.Key.Equals(term.Key, StringComparison.OrdinalIgnoreCase) &&
                                                         (!(x is PriceRangeFilter) || ((PriceRangeFilter)x).Currency.Equals(criteria.Currency, StringComparison.OrdinalIgnoreCase)));

                    // handle special filter term with a key = "tags", it contains just values and we need to determine which filter to use
                    if (filter == null && term.Key == "tags")
                    {
                        foreach (var termValue in term.Values)
                        {
                            // try to find filter by value
                            var foundFilter = filtersWithValues.FirstOrDefault(x => x.Values.Any(y => y.Id.Equals(termValue)));

                            if (foundFilter != null)
                            {
                                filter = foundFilter.Filter;

                                var appliedFilter = BrowseFilterHelper.Convert(filter, term.Values);
                                criteria.Apply(appliedFilter);
                            }
                        }
                    }
                    else if (filter != null) // predefined filter
                    {
                        var attributeFilter = filter as AttributeFilter;
                        if (attributeFilter != null && attributeFilter.Values == null)
                        {
                            filter = new AttributeFilter
                            {
                                Key          = attributeFilter.Key,
                                Values       = BrowseFilterHelper.CreateAttributeFilterValues(term.Values),
                                IsLocalized  = attributeFilter.IsLocalized,
                                DisplayNames = attributeFilter.DisplayNames,
                            };
                        }

                        var appliedFilter = BrowseFilterHelper.Convert(filter, term.Values);
                        criteria.Apply(appliedFilter);
                    }
                    else // custom term
                    {
                        if (!term.Key.StartsWith("_")) // ignore system terms, we can't filter by them
                        {
                            var attr = new AttributeFilter {
                                Key = term.Key, Values = BrowseFilterHelper.CreateAttributeFilterValues(term.Values)
                            };
                            criteria.Apply(attr);
                        }
                    }
                }
            }

            #endregion

            #region Sorting

            var categoryId        = Outline.AsCategoryId();
            var sorts             = Sort.AsSortInfoes();
            var sortFields        = new List <SearchSortField>();
            var priorityFieldName = string.Format(CultureInfo.InvariantCulture, "priority_{0}_{1}", catalog, categoryId).ToLower();

            if (!sorts.IsNullOrEmpty())
            {
                foreach (var sortInfo in sorts)
                {
                    var fieldName    = sortInfo.SortColumn.ToLowerInvariant();
                    var isDescending = sortInfo.SortDirection == SortDirection.Descending;

                    switch (fieldName)
                    {
                    case "price":
                        if (criteria.Pricelists != null)
                        {
                            sortFields.AddRange(
                                criteria.Pricelists.Select(
                                    priceList =>
                                    new SearchSortField(string.Format(CultureInfo.InvariantCulture, "price_{0}_{1}", criteria.Currency.ToLower(), priceList.ToLower()))
                            {
                                IgnoredUnmapped = true,
                                IsDescending    = isDescending,
                                DataType        = SearchSortField.DOUBLE
                            })
                                .ToArray());
                        }
                        break;

                    case "priority":
                        sortFields.Add(new SearchSortField(priorityFieldName, isDescending)
                        {
                            IgnoredUnmapped = true
                        });
                        sortFields.Add(new SearchSortField("priority", isDescending));
                        break;

                    case "name":
                    case "title":
                        sortFields.Add(new SearchSortField("name", isDescending));
                        break;

                    default:
                        sortFields.Add(new SearchSortField(fieldName, isDescending));
                        break;
                    }
                }
            }

            if (!sortFields.Any())
            {
                sortFields.Add(new SearchSortField(priorityFieldName, true)
                {
                    IgnoredUnmapped = true
                });
                sortFields.Add(new SearchSortField("priority", true));
                sortFields.AddRange(CatalogItemSearchCriteria.DefaultSortOrder.GetSort());
            }

            criteria.Sort = new SearchSort(sortFields.ToArray());

            #endregion

            return(criteria);
        }