public async Task <IActionResult> Search(CatalogSearchQuery query)
        {
            var model = new SearchResultModel(query);
            CatalogSearchResult result = null;

            if (query.Term == null || query.Term.Length < _searchSettings.InstantSearchTermMinLength)
            {
                model.SearchResult = new CatalogSearchResult(query);
                model.Error        = T("Search.SearchTermMinimumLengthIsNCharacters", _searchSettings.InstantSearchTermMinLength);
                return(View(model));
            }

            Services.WorkContext.CurrentCustomer.GenericAttributes.LastContinueShoppingPage = Services.WebHelper.GetCurrentPageUrl(false);

            try
            {
                if (_searchSettings.SearchProductByIdentificationNumber)
                {
                    var(product, attributeCombination) = await _productService.Value.GetProductByIdentificationNumberAsync(query.Term);

                    if (product != null)
                    {
                        if (attributeCombination != null)
                        {
                            return(Redirect(await _productUrlHelper.GetProductUrlAsync(product.Id, await product.GetActiveSlugAsync(), attributeCombination.AttributeSelection)));
                        }

                        return(RedirectToRoute("Product", new { SeName = await product.GetActiveSlugAsync() }));
                    }
                }

                result = await _catalogSearchService.SearchAsync(query);
            }
            catch (Exception ex)
            {
                model.Error = ex.ToString();
                result      = new CatalogSearchResult(query);
            }

            if (result.TotalHitsCount == 0 && result.SpellCheckerSuggestions.Any())
            {
                // No matches, but spell checker made a suggestion.
                // We implicitly search again with the first suggested term.
                var oldSuggestions = result.SpellCheckerSuggestions;
                var oldTerm        = query.Term;
                query.Term = oldSuggestions[0];

                result = await _catalogSearchService.SearchAsync(query);

                if (result.TotalHitsCount > 0)
                {
                    model.AttemptedTerm = oldTerm;
                    // Restore the original suggestions.
                    result.SpellCheckerSuggestions = oldSuggestions.Where(x => x != query.Term).ToArray();
                }
                else
                {
                    query.Term = oldTerm;
                }
            }

            model.SearchResult       = result;
            model.Term               = query.Term;
            model.TotalProductsCount = result.TotalHitsCount;

            var mappingSettings = _catalogHelper.GetBestFitProductSummaryMappingSettings(_catalogHelper.GetSearchQueryViewMode(query));
            var summaryModel    = await _catalogHelper.MapProductSummaryModelAsync(await result.GetHitsAsync(), mappingSettings);

            // Prepare paging/sorting/mode stuff.
            _catalogHelper.MapListActions(summaryModel, null, _catalogSettings.DefaultPageSizeOptions);

            // Add product hits.
            model.TopProducts = summaryModel;

            return(View(model));
        }
Beispiel #2
0
        public async Task <IActionResult> Manufacturer(int manufacturerId, CatalogSearchQuery query)
        {
            var manufacturer = await _db.Manufacturers.FindByIdAsync(manufacturerId, false);

            if (manufacturer == null || manufacturer.Deleted)
            {
                return(NotFound());
            }

            // Check whether the current user has a "Manage catalog" permission.
            // It allows him to preview a manufacturer before publishing.
            if (!manufacturer.Published && !await Services.Permissions.AuthorizeAsync(Permissions.Catalog.Manufacturer.Read))
            {
                return(NotFound());
            }

            // ACL (access control list).
            if (!await _aclService.AuthorizeAsync(manufacturer))
            {
                return(NotFound());
            }

            // Store mapping.
            if (!await _storeMappingService.AuthorizeAsync(manufacturer))
            {
                return(NotFound());
            }

            var customer = Services.WorkContext.CurrentCustomer;
            var storeId  = Services.StoreContext.CurrentStore.Id;

            // 'Continue shopping' URL.
            if (!customer.IsSystemAccount)
            {
                customer.GenericAttributes.LastContinueShoppingPage = Services.WebHelper.GetCurrentPageUrl(false);
            }

            var model = await _helper.PrepareBrandModelAsync(manufacturer);

            if (_seoSettings.CanonicalUrlsEnabled)
            {
                model.CanonicalUrl = _urlHelper.Value.RouteUrl("Manufacturer", new { model.SeName }, Request.Scheme);
            }

            if (query.IsSubPage && !_catalogSettings.ShowDescriptionInSubPages)
            {
                model.Description.ChangeValue(string.Empty);
                model.BottomDescription.ChangeValue(string.Empty);
            }

            model.Image = await _helper.PrepareBrandImageModelAsync(manufacturer, model.Name);

            // Featured products.
            var hideFeaturedProducts = _catalogSettings.IgnoreFeaturedProducts || (query.IsSubPage && !_catalogSettings.IncludeFeaturedProductsInSubPages);

            if (!hideFeaturedProducts)
            {
                CatalogSearchResult featuredProductsResult = null;

                var cacheKey = ModelCacheInvalidator.MANUFACTURER_HAS_FEATURED_PRODUCTS_KEY.FormatInvariant(manufacturerId, string.Join(",", customer.GetRoleIds()), storeId);
                var hasFeaturedProductsCache = await Services.Cache.GetAsync <bool?>(cacheKey);

                var featuredProductsQuery = new CatalogSearchQuery()
                                            .VisibleOnly(customer)
                                            .WithVisibility(ProductVisibility.Full)
                                            .WithManufacturerIds(true, manufacturerId)
                                            .HasStoreId(storeId)
                                            .WithLanguage(Services.WorkContext.WorkingLanguage)
                                            .WithCurrency(Services.WorkContext.WorkingCurrency);

                if (!hasFeaturedProductsCache.HasValue)
                {
                    featuredProductsResult = await _catalogSearchService.SearchAsync(featuredProductsQuery);

                    hasFeaturedProductsCache = featuredProductsResult.TotalHitsCount > 0;
                    await Services.Cache.PutAsync(cacheKey, hasFeaturedProductsCache);
                }

                if (hasFeaturedProductsCache.Value && featuredProductsResult == null)
                {
                    featuredProductsResult = await _catalogSearchService.SearchAsync(featuredProductsQuery);
                }

                if (featuredProductsResult != null)
                {
                    // TODO: (mc) determine settings properly
                    var featuredProductsmappingSettings = _helper.GetBestFitProductSummaryMappingSettings(ProductSummaryViewMode.Grid);
                    model.FeaturedProducts = await _helper.MapProductSummaryModelAsync(await featuredProductsResult.GetHitsAsync(), featuredProductsmappingSettings);
                }
            }

            // Products
            query.WithManufacturerIds(_catalogSettings.IncludeFeaturedProductsInNormalLists ? null : false, manufacturerId);

            var searchResult = await _catalogSearchService.SearchAsync(query);

            model.SearchResult = searchResult;

            var viewMode        = _helper.GetSearchQueryViewMode(query);
            var mappingSettings = _helper.GetBestFitProductSummaryMappingSettings(viewMode);

            model.Products = await _helper.MapProductSummaryModelAsync(await searchResult.GetHitsAsync(), mappingSettings);

            // Prepare paging/sorting/mode stuff
            _helper.MapListActions(model.Products, manufacturer, _catalogSettings.DefaultPageSizeOptions);

            // Template.
            var templateCacheKey = string.Format(ModelCacheInvalidator.MANUFACTURER_TEMPLATE_MODEL_KEY, manufacturer.ManufacturerTemplateId);
            var templateViewPath = await Services.Cache.GetAsync(templateCacheKey, async() =>
            {
                var template = await _db.ManufacturerTemplates.FindByIdAsync(manufacturer.ManufacturerTemplateId, false)
                               ?? await _db.ManufacturerTemplates.FirstOrDefaultAsync();

                return(template.ViewPath);
            });

            // Activity log.
            Services.ActivityLogger.LogActivity("PublicStore.ViewManufacturer", T("ActivityLog.PublicStore.ViewManufacturer"), manufacturer.Name);

            Services.DisplayControl.Announce(manufacturer);

            return(View(templateViewPath, model));
        }
Beispiel #3
0
        public async Task <IActionResult> Category(int categoryId, CatalogSearchQuery query)
        {
            var category = await _db.Categories
                           .Include(x => x.MediaFile)
                           .FindByIdAsync(categoryId, false);

            if (category == null || category.Deleted)
            {
                return(NotFound());
            }

            // Check whether the current user has a "Manage catalog" permission.
            // It allows him to preview a category before publishing.
            if (!category.Published && !await Services.Permissions.AuthorizeAsync(Permissions.Catalog.Category.Read))
            {
                return(NotFound());
            }

            // ACL (access control list).
            if (!await _aclService.AuthorizeAsync(category))
            {
                return(NotFound());
            }

            // Store mapping.
            if (!await _storeMappingService.AuthorizeAsync(category))
            {
                return(NotFound());
            }

            var customer = Services.WorkContext.CurrentCustomer;
            var storeId  = Services.StoreContext.CurrentStore.Id;

            // 'Continue shopping' URL.
            if (!customer.IsSystemAccount)
            {
                customer.GenericAttributes.LastContinueShoppingPage = Services.WebHelper.GetCurrentPageUrl(false);
            }

            var model = await _helper.PrepareCategoryModelAsync(category);

            if (_seoSettings.CanonicalUrlsEnabled)
            {
                model.CanonicalUrl = _urlHelper.Value.RouteUrl("Category", new { model.SeName }, Request.Scheme);
            }

            if (query.IsSubPage && !_catalogSettings.ShowDescriptionInSubPages)
            {
                model.Description.ChangeValue(string.Empty);
                model.BottomDescription.ChangeValue(string.Empty);
            }

            model.Image = await _helper.PrepareCategoryImageModelAsync(category, model.Name);

            // Category breadcrumb.
            if (_catalogSettings.CategoryBreadcrumbEnabled)
            {
                await _helper.GetBreadcrumbAsync(_breadcrumb, ControllerContext);
            }

            // Products.
            var catIds = new int[] { categoryId };

            if (_catalogSettings.ShowProductsFromSubcategories)
            {
                // Include subcategories.
                catIds = catIds.Concat(await _helper.GetChildCategoryIdsAsync(categoryId)).ToArray();
            }

            query.WithCategoryIds(_catalogSettings.IncludeFeaturedProductsInNormalLists ? null : false, catIds);

            var searchResult = await _catalogSearchService.SearchAsync(query);

            model.SearchResult = searchResult;

            var viewMode        = _helper.GetSearchQueryViewMode(query);
            var mappingSettings = _helper.GetBestFitProductSummaryMappingSettings(viewMode);

            model.Products = await _helper.MapProductSummaryModelAsync(await searchResult.GetHitsAsync(), mappingSettings);

            model.SubCategoryDisplayType = _catalogSettings.SubCategoryDisplayType;

            var pictureSize  = _mediaSettings.CategoryThumbPictureSize;
            var fallbackType = _catalogSettings.HideCategoryDefaultPictures ? FallbackPictureType.NoFallback : FallbackPictureType.Entity;

            var hideSubCategories = _catalogSettings.SubCategoryDisplayType == SubCategoryDisplayType.Hide ||
                                    (_catalogSettings.SubCategoryDisplayType == SubCategoryDisplayType.AboveProductList && query.IsSubPage && !_catalogSettings.ShowSubCategoriesInSubPages);
            var hideFeaturedProducts = _catalogSettings.IgnoreFeaturedProducts || (query.IsSubPage && !_catalogSettings.IncludeFeaturedProductsInSubPages);

            // Subcategories.
            if (!hideSubCategories)
            {
                var subCategories = await _categoryService.GetCategoriesByParentCategoryIdAsync(categoryId);

                model.SubCategories = await _helper.MapCategorySummaryModelAsync(subCategories, pictureSize);
            }

            // Featured Products.
            if (!hideFeaturedProducts)
            {
                CatalogSearchResult featuredProductsResult = null;

                string cacheKey = ModelCacheInvalidator.CATEGORY_HAS_FEATURED_PRODUCTS_KEY.FormatInvariant(categoryId, string.Join(",", customer.GetRoleIds()), storeId);
                var    hasFeaturedProductsCache = await Services.Cache.GetAsync <bool?>(cacheKey);

                var featuredProductsQuery = new CatalogSearchQuery()
                                            .VisibleOnly(customer)
                                            .WithVisibility(ProductVisibility.Full)
                                            .WithCategoryIds(true, categoryId)
                                            .HasStoreId(storeId)
                                            .WithLanguage(Services.WorkContext.WorkingLanguage)
                                            .WithCurrency(Services.WorkContext.WorkingCurrency);

                if (!hasFeaturedProductsCache.HasValue)
                {
                    featuredProductsResult = await _catalogSearchService.SearchAsync(featuredProductsQuery);

                    hasFeaturedProductsCache = featuredProductsResult.TotalHitsCount > 0;
                    await Services.Cache.PutAsync(cacheKey, hasFeaturedProductsCache);
                }

                if (hasFeaturedProductsCache.Value && featuredProductsResult == null)
                {
                    featuredProductsResult = await _catalogSearchService.SearchAsync(featuredProductsQuery);
                }

                if (featuredProductsResult != null)
                {
                    var featuredProductsMappingSettings = _helper.GetBestFitProductSummaryMappingSettings(ProductSummaryViewMode.Grid);
                    model.FeaturedProducts = await _helper.MapProductSummaryModelAsync(await featuredProductsResult.GetHitsAsync(), featuredProductsMappingSettings);
                }
            }

            // Prepare paging/sorting/mode stuff.
            _helper.MapListActions(model.Products, category, _catalogSettings.DefaultPageSizeOptions);

            // Template.
            var templateCacheKey = string.Format(ModelCacheInvalidator.CATEGORY_TEMPLATE_MODEL_KEY, category.CategoryTemplateId);
            var templateViewPath = await Services.Cache.GetAsync(templateCacheKey, async() =>
            {
                var template = await _db.CategoryTemplates.FindByIdAsync(category.CategoryTemplateId, false)
                               ?? await _db.CategoryTemplates.FirstOrDefaultAsync();

                return(template.ViewPath);
            });

            // Activity log.
            Services.ActivityLogger.LogActivity("PublicStore.ViewCategory", T("ActivityLog.PublicStore.ViewCategory"), category.Name);

            Services.DisplayControl.Announce(category);

            return(View(templateViewPath, model));
        }
 public virtual async Task <ProductSummaryModel> MapProductSummaryModelAsync(CatalogSearchResult sourceResult, ProductSummaryMappingSettings settings)
 {
     return(await MapProductSummaryModelAsync(await sourceResult.GetHitsAsync(), sourceResult, settings));
 }