Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

changes to the services #826

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 27 additions & 71 deletions src/Smartstore.Web/Controllers/SearchController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class SearchController : PublicController
private readonly CatalogSettings _catalogSettings;
private readonly Lazy<IProductService> _productService;
private readonly ProductUrlHelper _productUrlHelper;
//private SearchResultModel _searchResultModel;

public SearchController(
CatalogHelper catalogHelper,
Expand All @@ -29,7 +30,9 @@ public SearchController(
SearchSettings searchSettings,
CatalogSettings catalogSettings,
Lazy<IProductService> productService,
ProductUrlHelper productUrlHelper)
ProductUrlHelper productUrlHelper
//SearchResultModel search
)
{
_catalogHelper = catalogHelper;
_catalogSearchService = catalogSearchService;
Expand All @@ -39,6 +42,15 @@ public SearchController(
_catalogSettings = catalogSettings;
_productService = productService;
_productUrlHelper = productUrlHelper;

//if(search == null)
//{
//}
//else
//{
// _searchResultModel = search;
//}
//_searchResultModel = new SearchResultModel();
}

[HttpPost]
Expand Down Expand Up @@ -98,90 +110,34 @@ await _localizedEntityService.PrefetchLocalizedPropertiesAsync(
[LocalizedRoute("/search", Name = "Search")]
public async Task<IActionResult> Search(CatalogSearchQuery query)
{
CatalogSearchResult result = null;
var model = new SearchResultModel(query);
var term = query?.DefaultTerm;

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

var customer = Services.WorkContext.CurrentCustomer;
if (!customer.IsSystemAccount)
{
customer.GenericAttributes.LastContinueShoppingPage = HttpContext.Request.RawUrl();
}

try
if (_searchSettings.SearchProductByIdentificationNumber)
{
if (_searchSettings.SearchProductByIdentificationNumber)
var (product, attributeCombination) = await _productService.Value.GetProductByCodeAsync(term);
if (product != null)
{
var (product, attributeCombination) = await _productService.Value.GetProductByCodeAsync(term);
if (product != null)
{
if (attributeCombination != null)
{
return Redirect(await _productUrlHelper.GetProductPathAsync(
product.Id,
await product.GetActiveSlugAsync(),
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);
}
return View(await GetSearchResultModel(query));
}

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

query.DefaultTerm = oldSuggestions[0];
result = await _catalogSearchService.SearchAsync(query);

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

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

var productSummaryViewMode = query.CustomData.Get("ViewMode") is string viewMode && viewMode.EqualsNoCase("list")
? ProductSummaryViewMode.List
: ProductSummaryViewMode.Grid;

var mappingSettings = _catalogHelper.GetBestFitProductSummaryMappingSettings(productSummaryViewMode);
var summaryModel = await _catalogHelper.MapProductSummaryModelAsync(result, mappingSettings);

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

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

return View(model);
public async Task<SearchResultModel> GetSearchResultModel(CatalogSearchQuery query)
{
CatalogSearchResult result = null;
var model = new SearchResultModel(query);

var service = new SearchControllerService(_catalogSearchService, _searchSettings, _catalogSettings, _catalogHelper);
return await service.GetSearchResultService(model, result, query);
}
}
}
99 changes: 99 additions & 0 deletions src/Smartstore.Web/Controllers/SearchControllerService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
using Smartstore.Core.Catalog;
using Smartstore.Core.Catalog.Search;
using Smartstore.Web.Models.Catalog;
using Smartstore.Web.Models.Search;

namespace Smartstore.Web.Controllers
{
public class SearchControllerService: PublicController
{
private readonly CatalogHelper _catalogHelper;
private readonly SearchSettings _searchSettings;
private readonly ICatalogSearchService _catalogSearchService;
private readonly CatalogSettings _catalogSettings;


public SearchControllerService(ICatalogSearchService catalogSearchService,
SearchSettings searchSettings,
CatalogSettings catalogSettings,
CatalogHelper catalogHelper)
{
_catalogSearchService = catalogSearchService;
_searchSettings = searchSettings;
_catalogSettings = catalogSettings;
_catalogHelper = catalogHelper;
}
public async Task<SearchResultModel> GetSearchResultService(SearchResultModel model, CatalogSearchResult result, CatalogSearchQuery query)
{
var term = query?.DefaultTerm;

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

CustomerCheck();

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

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

query.DefaultTerm = oldSuggestions[0];
result = await _catalogSearchService.SearchAsync(query);

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

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

var productSummaryViewMode = query.CustomData.Get("ViewMode") is string viewMode && viewMode.EqualsNoCase("list")
? ProductSummaryViewMode.List
: ProductSummaryViewMode.Grid;

var mappingSettings = _catalogHelper.GetBestFitProductSummaryMappingSettings(productSummaryViewMode);
var summaryModel = await _catalogHelper.MapProductSummaryModelAsync(result, mappingSettings);

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

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

public void CustomerCheck()
{
var customer = Services.WorkContext.CurrentCustomer;
if (!customer.IsSystemAccount)
{
customer.GenericAttributes.LastContinueShoppingPage = HttpContext.Request.RawUrl();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using NUnit.Framework;
using Smartstore.Core.Catalog.Search;
using Smartstore.Test.Common;
using Smartstore.Web.Controllers;
using Smartstore.Web.Models.Search;
using Microsoft.AspNetCore.Mvc;
using Smartstore.Web.Models.Catalog;
using Smartstore.Collections;
using Moq;
using Smartstore.Core.Catalog.Products;
using Smartstore.Core.Search.Facets;
using Smartstore.Core.Search;

namespace Smartstore.Web.Tests.Common.Controllers;

[TestFixture]
public class SearchControllerTests
{
[Test]
public async Task Term_Not_Found()
{
SearchSettings settings = new SearchSettings();
settings.InstantSearchTermMinLength = 2;

SearchController controller = new(null, null, null, null, settings, null, null, null);
CatalogSearchQuery query = new CatalogSearchQuery();
query.DefaultTerm = "a";
var actual = await controller.GetSearchResultModel(query);

SearchResultModel expected_result = new SearchResultModel(query);
expected_result.SearchResult = new CatalogSearchResult(query);
expected_result.TopProducts = ProductSummaryModel.Empty;
expected_result.Error = "Search.SearchTermMinimumLengthIsNCharacters";

//need to mock db for this assert
Assert.AreEqual(expected_result.SearchResult.TotalHitsCount, actual.SearchResult.TotalHitsCount);
Assert.AreEqual(expected_result.TopProducts, actual.TopProducts);
Assert.AreEqual(expected_result.Error, actual.Error);
}

[Test]
public async Task Search_Item()
{
SearchSettings settings = new SearchSettings();
settings.InstantSearchTermMinLength = 2;
CatalogSearchQuery query = new CatalogSearchQuery();
query.DefaultTerm = "baseball";

var catalogSerchResult = new CatalogSearchResult(null, query, null, 1, null, null, null);

var searchServiceMock = new Mock<ICatalogSearchService>();
searchServiceMock.Setup(x => x.SearchAsync(query, false)).ReturnsAsync(catalogSerchResult);
var searchServiceMockObject = searchServiceMock.Object;

SearchController controller = new(null, null, null, null, settings, null, null, null);
var actual = await controller.GetSearchResultModel(query);

//need to mock db for this assert
Assert.AreEqual(1, actual.TopProducts.Items.Count);
}
}