protected virtual IDictionary <string, FacetGroup> GetFacets(CatalogSearchQuery searchQuery, int totalHits)
        {
            var result     = new Dictionary <string, FacetGroup>();
            var storeId    = searchQuery.StoreId ?? _services.StoreContext.CurrentStore.Id;
            var languageId = searchQuery.LanguageId ?? _services.WorkContext.WorkingLanguage.Id;

            foreach (var key in searchQuery.FacetDescriptors.Keys)
            {
                var descriptor = searchQuery.FacetDescriptors[key];
                var facets     = new List <Facet>();
                var kind       = FacetGroup.GetKindByKey("Catalog", key);

                switch (kind)
                {
                case FacetGroupKind.Category:
                case FacetGroupKind.Brand:
                case FacetGroupKind.DeliveryTime:
                case FacetGroupKind.Rating:
                case FacetGroupKind.Price:
                    if (totalHits == 0 && !descriptor.Values.Any(x => x.IsSelected))
                    {
                        continue;
                    }
                    break;
                }

                if (kind == FacetGroupKind.Category)
                {
                    var categoryTree = _categoryService.GetCategoryTree(0, false, storeId);
                    var categories   = categoryTree.Flatten(false);

                    if (descriptor.MaxChoicesCount > 0)
                    {
                        categories = categories.Take(descriptor.MaxChoicesCount);
                    }

                    var nameQuery = _localizedPropertyRepository.TableUntracked
                                    .Where(x => x.LocaleKeyGroup == "Category" && x.LocaleKey == "Name" && x.LanguageId == languageId);
                    var names = nameQuery.ToList().ToDictionarySafe(x => x.EntityId, x => x.LocaleValue);

                    foreach (var category in categories)
                    {
                        names.TryGetValue(category.Id, out var label);

                        facets.Add(new Facet(new FacetValue(category.Id, IndexTypeCode.Int32)
                        {
                            IsSelected   = descriptor.Values.Any(x => x.IsSelected && x.Value.Equals(category.Id)),
                            Label        = label.HasValue() ? label : category.Name,
                            DisplayOrder = category.DisplayOrder
                        }));
                    }
                }
                else if (kind == FacetGroupKind.Brand)
                {
                    var manufacturers = _manufacturerService.GetAllManufacturers(null, storeId);
                    if (descriptor.MaxChoicesCount > 0)
                    {
                        manufacturers = manufacturers.Take(descriptor.MaxChoicesCount).ToList();
                    }

                    var nameQuery = _localizedPropertyRepository.TableUntracked
                                    .Where(x => x.LocaleKeyGroup == "Manufacturer" && x.LocaleKey == "Name" && x.LanguageId == languageId);
                    var names = nameQuery.ToList().ToDictionarySafe(x => x.EntityId, x => x.LocaleValue);

                    foreach (var manu in manufacturers)
                    {
                        names.TryGetValue(manu.Id, out var label);

                        facets.Add(new Facet(new FacetValue(manu.Id, IndexTypeCode.Int32)
                        {
                            IsSelected   = descriptor.Values.Any(x => x.IsSelected && x.Value.Equals(manu.Id)),
                            Label        = label.HasValue() ? label : manu.Name,
                            DisplayOrder = manu.DisplayOrder
                        }));
                    }
                }
                else if (kind == FacetGroupKind.DeliveryTime)
                {
                    var deliveryTimes = _deliveryTimeService.GetAllDeliveryTimes();
                    var nameQuery     = _localizedPropertyRepository.TableUntracked
                                        .Where(x => x.LocaleKeyGroup == "DeliveryTime" && x.LocaleKey == "Name" && x.LanguageId == languageId);
                    var names = nameQuery.ToList().ToDictionarySafe(x => x.EntityId, x => x.LocaleValue);

                    foreach (var deliveryTime in deliveryTimes)
                    {
                        if (descriptor.MaxChoicesCount > 0 && facets.Count >= descriptor.MaxChoicesCount)
                        {
                            break;
                        }

                        names.TryGetValue(deliveryTime.Id, out var label);

                        facets.Add(new Facet(new FacetValue(deliveryTime.Id, IndexTypeCode.Int32)
                        {
                            IsSelected   = descriptor.Values.Any(x => x.IsSelected && x.Value.Equals(deliveryTime.Id)),
                            Label        = label.HasValue() ? label : deliveryTime.Name,
                            DisplayOrder = deliveryTime.DisplayOrder
                        }));
                    }
                }
                else if (kind == FacetGroupKind.Price)
                {
                    var count = 0;
                    var hasActivePredefinedFacet = false;
                    var minPrice = _productRepository.Table.Where(x => x.Published && !x.Deleted && !x.IsSystemProduct).Min(x => (double)x.Price);
                    var maxPrice = _productRepository.Table.Where(x => x.Published && !x.Deleted && !x.IsSystemProduct).Max(x => (double)x.Price);
                    minPrice = FacetUtility.MakePriceEven(minPrice);
                    maxPrice = FacetUtility.MakePriceEven(maxPrice);

                    for (var i = 0; i < _priceThresholds.Length; ++i)
                    {
                        if (descriptor.MaxChoicesCount > 0 && facets.Count >= descriptor.MaxChoicesCount)
                        {
                            break;
                        }

                        var price = _priceThresholds[i];
                        if (price < minPrice)
                        {
                            continue;
                        }

                        if (price >= maxPrice)
                        {
                            i = int.MaxValue - 1;
                        }

                        var selected = descriptor.Values.Any(x => x.IsSelected && x.Value == null && x.UpperValue != null && (double)x.UpperValue == price);
                        if (selected)
                        {
                            hasActivePredefinedFacet = true;
                        }

                        facets.Add(new Facet(new FacetValue(null, price, IndexTypeCode.Double, false, true)
                        {
                            DisplayOrder = ++count,
                            IsSelected   = selected
                        }));
                    }

                    // Add facet for custom price range.
                    var priceDescriptorValue = descriptor.Values.FirstOrDefault();

                    var customPriceFacetValue = new FacetValue(
                        priceDescriptorValue != null && !hasActivePredefinedFacet ? priceDescriptorValue.Value : null,
                        priceDescriptorValue != null && !hasActivePredefinedFacet ? priceDescriptorValue.UpperValue : null,
                        IndexTypeCode.Double,
                        true,
                        true);

                    customPriceFacetValue.IsSelected = customPriceFacetValue.Value != null || customPriceFacetValue.UpperValue != null;

                    if (!(totalHits == 0 && !customPriceFacetValue.IsSelected))
                    {
                        facets.Insert(0, new Facet("custom", customPriceFacetValue));
                    }
                }
                else if (kind == FacetGroupKind.Rating)
                {
                    foreach (var rating in FacetUtility.GetRatings())
                    {
                        var newFacet = new Facet(rating);
                        newFacet.Value.IsSelected = descriptor.Values.Any(x => x.IsSelected && x.Value.Equals(rating.Value));
                        facets.Add(newFacet);
                    }
                }
                else if (kind == FacetGroupKind.Availability || kind == FacetGroupKind.NewArrivals)
                {
                    var value = descriptor.Values.FirstOrDefault();
                    if (value != null)
                    {
                        if (kind == FacetGroupKind.NewArrivals && totalHits == 0 && !value.IsSelected)
                        {
                            continue;
                        }

                        var newValue = value.Clone();
                        newValue.Value      = true;
                        newValue.TypeCode   = IndexTypeCode.Boolean;
                        newValue.IsRange    = false;
                        newValue.IsSelected = value.IsSelected;

                        facets.Add(new Facet(newValue));
                    }
                }

                if (facets.Any(x => x.Published))
                {
                    //facets.Each(x => $"{key} {x.Value.ToString()}".Dump());

                    result.Add(key, new FacetGroup(
                                   "Catalog",
                                   key,
                                   descriptor.Label,
                                   descriptor.IsMultiSelect,
                                   false,
                                   descriptor.DisplayOrder,
                                   facets.OrderBy(descriptor)));
                }
            }

            return(result);
        }
Exemple #2
0
        protected virtual IDictionary <string, FacetGroup> GetFacets(CatalogSearchQuery searchQuery, int totalHits)
        {
            var result     = new Dictionary <string, FacetGroup>();
            var languageId = searchQuery.LanguageId ?? _services.WorkContext.WorkingLanguage.Id;

            foreach (var key in searchQuery.FacetDescriptors.Keys)
            {
                var descriptor = searchQuery.FacetDescriptors[key];
                var facets     = new List <Facet>();
                var kind       = FacetGroup.GetKindByKey(key);

                if (kind == FacetGroupKind.Category)
                {
                    #region Category

                    // order by product count
                    var categoryQuery =
                        from c in _categoryRepository.TableUntracked
                        where !c.Deleted && c.Published
                        join pc in _productCategoryRepository.TableUntracked on c.Id equals pc.CategoryId into pcm
                        from pc in pcm.DefaultIfEmpty()
                        group c by c.Id into grp
                        orderby grp.Count() descending
                        select new
                    {
                        Id           = grp.FirstOrDefault().Id,
                        Name         = grp.FirstOrDefault().Name,
                        DisplayOrder = grp.FirstOrDefault().DisplayOrder
                    };

                    if (descriptor.MaxChoicesCount > 0)
                    {
                        categoryQuery = categoryQuery.Take(descriptor.MaxChoicesCount);
                    }

                    var categories = categoryQuery.ToList();

                    var nameQuery = _localizedPropertyRepository.TableUntracked
                                    .Where(x => x.LocaleKeyGroup == "Category" && x.LocaleKey == "Name" && x.LanguageId == languageId);

                    var names = nameQuery.ToList().ToDictionarySafe(x => x.EntityId, x => x.LocaleValue);

                    foreach (var category in categories)
                    {
                        var selected = descriptor.Values.Any(x => x.IsSelected && x.Value.Equals(category.Id));
                        if (totalHits == 0 && !selected)
                        {
                            continue;
                        }

                        string label = null;
                        names.TryGetValue(category.Id, out label);

                        facets.Add(new Facet(new FacetValue(category.Id, IndexTypeCode.Int32)
                        {
                            IsSelected   = selected,
                            Label        = label.HasValue() ? label : category.Name,
                            DisplayOrder = category.DisplayOrder
                        }));
                    }

                    #endregion
                }
                else if (kind == FacetGroupKind.Brand)
                {
                    #region Brand

                    // order by product count
                    var manufacturerQuery =
                        from m in _manufacturerRepository.TableUntracked
                        where !m.Deleted && m.Published
                        join pm in _productManufacturerRepository.TableUntracked on m.Id equals pm.ManufacturerId into pmm
                        from pm in pmm.DefaultIfEmpty()
                        group m by m.Id into grp
                        orderby grp.Count() descending
                        select new
                    {
                        Id           = grp.FirstOrDefault().Id,
                        Name         = grp.FirstOrDefault().Name,
                        DisplayOrder = grp.FirstOrDefault().DisplayOrder
                    };

                    if (descriptor.MaxChoicesCount > 0)
                    {
                        manufacturerQuery = manufacturerQuery.Take(descriptor.MaxChoicesCount);
                    }

                    var manufacturers = manufacturerQuery.ToList();

                    var nameQuery = _localizedPropertyRepository.TableUntracked
                                    .Where(x => x.LocaleKeyGroup == "Manufacturer" && x.LocaleKey == "Name" && x.LanguageId == languageId);

                    var names = nameQuery.ToList().ToDictionarySafe(x => x.EntityId, x => x.LocaleValue);

                    foreach (var manu in manufacturers)
                    {
                        var selected = descriptor.Values.Any(x => x.IsSelected && x.Value.Equals(manu.Id));
                        if (totalHits == 0 && !selected)
                        {
                            continue;
                        }

                        string label = null;
                        names.TryGetValue(manu.Id, out label);

                        facets.Add(new Facet(new FacetValue(manu.Id, IndexTypeCode.Int32)
                        {
                            IsSelected   = selected,
                            Label        = label.HasValue() ? label : manu.Name,
                            DisplayOrder = manu.DisplayOrder
                        }));
                    }

                    #endregion
                }
                else if (kind == FacetGroupKind.DeliveryTime)
                {
                    #region Delivery time

                    var deliveryTimes = _deliveryTimeService.GetAllDeliveryTimes();

                    var nameQuery = _localizedPropertyRepository.TableUntracked
                                    .Where(x => x.LocaleKeyGroup == "DeliveryTime" && x.LocaleKey == "Name" && x.LanguageId == languageId);

                    var names = nameQuery.ToList().ToDictionarySafe(x => x.EntityId, x => x.LocaleValue);

                    foreach (var deliveryTime in deliveryTimes)
                    {
                        if (descriptor.MaxChoicesCount > 0 && facets.Count >= descriptor.MaxChoicesCount)
                        {
                            break;
                        }

                        var selected = descriptor.Values.Any(x => x.IsSelected && x.Value.Equals(deliveryTime.Id));
                        if (totalHits == 0 && !selected)
                        {
                            continue;
                        }

                        string label = null;
                        names.TryGetValue(deliveryTime.Id, out label);

                        facets.Add(new Facet(new FacetValue(deliveryTime.Id, IndexTypeCode.Int32)
                        {
                            IsSelected   = selected,
                            Label        = label.HasValue() ? label : deliveryTime.Name,
                            DisplayOrder = deliveryTime.DisplayOrder
                        }));
                    }

                    #endregion
                }
                else if (kind == FacetGroupKind.Price)
                {
                    #region Price

                    var count = 0;
                    var hasActivePredefinedFacet = false;
                    var minPrice = _productRepository.Table.Where(x => !x.Deleted && x.Published).Min(x => (double)x.Price);
                    var maxPrice = _productRepository.Table.Where(x => !x.Deleted && x.Published).Max(x => (double)x.Price);
                    minPrice = FacetUtility.MakePriceEven(minPrice);
                    maxPrice = FacetUtility.MakePriceEven(maxPrice);

                    for (var i = 0; i < _priceThresholds.Length; ++i)
                    {
                        if (descriptor.MaxChoicesCount > 0 && facets.Count >= descriptor.MaxChoicesCount)
                        {
                            break;
                        }

                        var price = _priceThresholds[i];
                        if (price < minPrice)
                        {
                            continue;
                        }

                        if (price >= maxPrice)
                        {
                            i = int.MaxValue - 1;
                        }

                        var selected = descriptor.Values.Any(x => x.IsSelected && x.Value == null && x.UpperValue != null && (double)x.UpperValue == price);
                        if (totalHits == 0 && !selected)
                        {
                            continue;
                        }

                        if (selected)
                        {
                            hasActivePredefinedFacet = true;
                        }

                        facets.Add(new Facet(new FacetValue(null, price, IndexTypeCode.Double, false, true)
                        {
                            DisplayOrder = ++count,
                            IsSelected   = selected
                        }));
                    }

                    // Add facet for custom price range.
                    var priceDescriptorValue = descriptor.Values.FirstOrDefault();

                    var customPriceFacetValue = new FacetValue(
                        priceDescriptorValue != null && !hasActivePredefinedFacet ? priceDescriptorValue.Value : null,
                        priceDescriptorValue != null && !hasActivePredefinedFacet ? priceDescriptorValue.UpperValue : null,
                        IndexTypeCode.Double,
                        true,
                        true);

                    customPriceFacetValue.IsSelected = customPriceFacetValue.Value != null || customPriceFacetValue.UpperValue != null;

                    if (!(totalHits == 0 && !customPriceFacetValue.IsSelected))
                    {
                        facets.Insert(0, new Facet("custom", customPriceFacetValue));
                    }

                    #endregion
                }
                else if (kind == FacetGroupKind.Rating)
                {
                    if (totalHits == 0 && !descriptor.Values.Any(x => x.IsSelected))
                    {
                        continue;
                    }

                    foreach (var rating in FacetUtility.GetRatings())
                    {
                        var newFacet = new Facet(rating);
                        newFacet.Value.IsSelected = descriptor.Values.Any(x => x.IsSelected && x.Value.Equals(rating.Value));
                        facets.Add(newFacet);
                    }
                }
                else if (kind == FacetGroupKind.Availability || kind == FacetGroupKind.NewArrivals)
                {
                    var value = descriptor.Values.FirstOrDefault();
                    if (value != null && !(totalHits == 0 && !value.IsSelected))
                    {
                        var newValue = value.Clone();
                        newValue.Value      = true;
                        newValue.TypeCode   = IndexTypeCode.Boolean;
                        newValue.IsRange    = false;
                        newValue.IsSelected = value.IsSelected;

                        facets.Add(new Facet(newValue));
                    }
                }

                if (facets.Any(x => x.Published))
                {
                    //facets.Each(x => $"{key} {x.Value.ToString()}".Dump());

                    result.Add(key, new FacetGroup(
                                   key,
                                   descriptor.Label,
                                   descriptor.IsMultiSelect,
                                   descriptor.DisplayOrder,
                                   facets.OrderBy(descriptor)));
                }
            }

            return(result);
        }