protected virtual void ConvertAvailability(CatalogSearchQuery query, RouteData routeData, string origin) { bool availability; GetValueFor(query, "a", FacetGroupKind.Availability, out availability); // Setting specifies the logical direction of the filter. That's smarter than just to specify a default value. if (_searchSettings.IncludeNotAvailable) { // False = show, True = hide unavailable products. if (availability) { query.AvailableOnly(true); } } else { // False = hide, True = show unavailable products. if (!availability) { query.AvailableOnly(true); } } AddFacet(query, FacetGroupKind.Availability, true, FacetSorting.LabelAsc, descriptor => { descriptor.MinHitCount = 0; var newValue = availability ? new FacetValue(true, IndexTypeCode.Boolean) : new FacetValue(null, IndexTypeCode.Empty); newValue.IsSelected = availability; newValue.Label = _services.Localization.GetResource(_searchSettings.IncludeNotAvailable ? "Search.Facet.ExcludeOutOfStock" : "Search.Facet.IncludeOutOfStock"); descriptor.AddValue(newValue); }); }
public override void ResolveElementCounts(TreeNode <MenuItem> curNode, bool deep = false) { if (curNode == null || !ContainsProvider("catalog") || !_catalogSettings.Value.ShowCategoryProductNumber) { return; } try { using (Services.Chronometer.Step($"DatabaseMenu.ResolveElementsCount() for {curNode.Value.Text.NaIfEmpty()}")) { // Perf: only resolve counts for categories in the current path. while (curNode != null) { if (curNode.Children.Any(x => !x.Value.ElementsCount.HasValue)) { lock (s_lock) { if (curNode.Children.Any(x => !x.Value.ElementsCount.HasValue)) { var nodes = deep ? curNode.SelectNodes(x => true, false) : curNode.Children.AsEnumerable(); nodes = nodes.Where(x => x.Value.EntityId != 0); foreach (var node in nodes) { var isCategory = node.Value.EntityName.IsCaseInsensitiveEqual(nameof(Category)); var isManufacturer = node.Value.EntityName.IsCaseInsensitiveEqual(nameof(Manufacturer)); if (isCategory || isManufacturer) { var entityIds = new HashSet <int>(); if (isCategory && _catalogSettings.Value.ShowCategoryProductNumberIncludingSubcategories) { // Include sub-categories. node.Traverse(x => { entityIds.Add(x.Value.EntityId); }, true); } else { entityIds.Add(node.Value.EntityId); } var context = new CatalogSearchQuery() .VisibleOnly() .WithVisibility(ProductVisibility.Full) .HasStoreId(Services.StoreContext.CurrentStoreIdIfMultiStoreMode) .BuildFacetMap(false) .BuildHits(false); if (isCategory) { context = context.WithCategoryIds(null, entityIds.ToArray()); } else { context = context.WithManufacturerIds(null, entityIds.ToArray()); } if (!_searchSettings.Value.IncludeNotAvailable) { context = context.AvailableOnly(true); } node.Value.ElementsCount = _catalogSearchService.Value.Search(context).TotalHitsCount; } } } } } curNode = curNode.Parent; } } } catch (Exception ex) { _logger.Error(ex); } }