Skip to content

Commit

Permalink
Merge pull request #3 from nixtus/feat-autocomplete
Browse files Browse the repository at this point in the history
feat: use lucene for auto complete searches
  • Loading branch information
mewajda authored Aug 26, 2020
2 parents 793ff91 + a462626 commit 02515a0
Show file tree
Hide file tree
Showing 9 changed files with 176 additions and 130 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using Microsoft.AspNetCore.Mvc;
using Nixtus.Plugin.Widgets.Lucene.Services;
using Nop.Core;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Media;
using Nop.Services.Catalog;
using Nop.Web.Controllers;
using Nop.Web.Factories;
using System.Linq;

namespace Nixtus.Plugin.Widgets.Lucene.Controllers
{
public class LuceneCatalogController : BasePublicController
{
private readonly LuceneSettings _luceneSettings;
private readonly CatalogSettings _catalogSettings;
private readonly IProductService _productService;
private readonly IStoreContext _storeContext;
private readonly IWorkContext _workContext;
private readonly IProductModelFactory _productModelFactory;
private readonly MediaSettings _mediaSettings;
private readonly ILuceneService _luceneService;

public LuceneCatalogController(LuceneSettings luceneSettings, CatalogSettings catalogSettings,
IProductService productService,
IStoreContext storeContext,
IWorkContext workContext,
IProductModelFactory productModelFactory,
MediaSettings mediaSettings, ILuceneService luceneService)
{
_luceneSettings = luceneSettings;
_catalogSettings = catalogSettings;
_productService = productService;
_storeContext = storeContext;
_workContext = workContext;
_productModelFactory = productModelFactory;
_mediaSettings = mediaSettings;
_luceneService = luceneService;
}

public IActionResult SearchTermAutoComplete(string term)
{
if (string.IsNullOrWhiteSpace(term) || term.Length < _catalogSettings.ProductSearchTermMinimumLength)
return Content("");

//products
var productNumber = _catalogSettings.ProductSearchAutoCompleteNumberOfProducts > 0 ?
_catalogSettings.ProductSearchAutoCompleteNumberOfProducts : 10;

IPagedList<Product> products = null;

// use lucene search if enabled
if (_luceneSettings.AutoCompleteSearchEnabled)
{
_luceneService.GetLuceneDirectory();

var luceneProducts = _luceneService.Search(term);

products = new PagedList<Product>(luceneProducts.AsQueryable(), 0, productNumber);
}
else
{
products = _productService.SearchProducts(
storeId: _storeContext.CurrentStore.Id,
keywords: term,
languageId: _workContext.WorkingLanguage.Id,
visibleIndividuallyOnly: true,
pageSize: productNumber);
}

var showLinkToResultSearch = _catalogSettings.ShowLinkToAllResultInSearchAutoComplete && (products.TotalCount > productNumber);

var models = _productModelFactory.PrepareProductOverviewModels(products, false, _catalogSettings.ShowProductImagesInSearchAutoComplete, _mediaSettings.AutoCompleteSearchThumbPictureSize).ToList();
var result = (from p in models
select new
{
label = p.Name,
producturl = Url.RouteUrl("Product", new { SeName = p.SeName }),
productpictureurl = p.DefaultPictureModel.ImageUrl,
showlinktoresultsearch = showLinkToResultSearch
})
.ToList();
return Json(result);
}
}
}
139 changes: 21 additions & 118 deletions Nixtus.Plugin.Widgets.Lucene/Controllers/LuceneController.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,8 @@
using Microsoft.AspNetCore.Mvc;
using Nop.Core;
using Nop.Core.Domain.Blogs;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Forums;
using Nop.Core.Domain.Media;
using Nop.Core.Domain.Vendors;
using Nixtus.Plugin.Widgets.Lucene.Models;
using Nixtus.Plugin.Widgets.Lucene.Services;
using Nop.Services.Catalog;
using Nop.Services.Common;
using Nop.Core;
using Nop.Services.Configuration;
using Nop.Services.Directory;
using Nop.Services.Events;
using Nop.Services.Localization;
using Nop.Services.Logging;
using Nop.Services.Media;
using Nop.Services.Security;
using Nop.Services.Stores;
using Nop.Services.Tax;
using Nop.Services.Vendors;
using Nop.Web.Framework;
using Nop.Web.Framework.Controllers;
using Nop.Web.Framework.Mvc.Filters;
Expand All @@ -29,109 +13,20 @@ public class LuceneController : BasePluginController
{
#region Fields

private readonly ICategoryService _categoryService;
private readonly IManufacturerService _manufacturerService;
private readonly IProductService _productService;
private readonly IVendorService _vendorService;
private readonly ICategoryTemplateService _categoryTemplateService;
private readonly IManufacturerTemplateService _manufacturerTemplateService;
private readonly IWorkContext _workContext;
private readonly IStoreContext _storeContext;
private readonly ITaxService _taxService;
private readonly ICurrencyService _currencyService;
private readonly IPictureService _pictureService;
private readonly ILocalizationService _localizationService;
private readonly IPriceCalculationService _priceCalculationService;
private readonly IPriceFormatter _priceFormatter;
private readonly IWebHelper _webHelper;
private readonly ISpecificationAttributeService _specificationAttributeService;
private readonly IProductTagService _productTagService;
private readonly IGenericAttributeService _genericAttributeService;
private readonly IAclService _aclService;
private readonly IStoreMappingService _storeMappingService;
private readonly IPermissionService _permissionService;
private readonly ICustomerActivityService _customerActivityService;
private readonly IEventPublisher _eventPublisher;
private readonly ISearchTermService _searchTermService;
private readonly MediaSettings _mediaSettings;
private readonly CatalogSettings _catalogSettings;
private readonly VendorSettings _vendorSettings;
private readonly BlogSettings _blogSettings;
private readonly ForumSettings _forumSettings;
private readonly ISettingService _settingService;
private readonly IStoreService _storeService;
private readonly ILuceneService _luceneService;
private readonly LuceneSettings _luceneSettings;
private readonly IStoreContext _storeContext;
#endregion

#region Constructors

public LuceneController(ICategoryService categoryService,
IManufacturerService manufacturerService,
IProductService productService,
IVendorService vendorService,
ICategoryTemplateService categoryTemplateService,
IManufacturerTemplateService manufacturerTemplateService,
IWorkContext workContext,
IStoreContext storeContext,
ITaxService taxService,
ICurrencyService currencyService,
IPictureService pictureService,
ILocalizationService localizationService,
IPriceCalculationService priceCalculationService,
IPriceFormatter priceFormatter,
IWebHelper webHelper,
ISpecificationAttributeService specificationAttributeService,
IProductTagService productTagService,
IGenericAttributeService genericAttributeService,
IAclService aclService,
IStoreMappingService storeMappingService,
IPermissionService permissionService,
ICustomerActivityService customerActivityService,
IEventPublisher eventPublisher,
ISearchTermService searchTermService,
MediaSettings mediaSettings,
CatalogSettings catalogSettings,
VendorSettings vendorSettings,
BlogSettings blogSettings,
ForumSettings forumSettings,
ISettingService settingService,
IStoreService storeService,
ILuceneService luceneService, LuceneSettings luceneSettings)
#region Constructors

public LuceneController(ISettingService settingService,
ILuceneService luceneService,
IStoreContext storeContext)
{
this._categoryService = categoryService;
this._manufacturerService = manufacturerService;
this._productService = productService;
this._vendorService = vendorService;
this._categoryTemplateService = categoryTemplateService;
this._manufacturerTemplateService = manufacturerTemplateService;
this._workContext = workContext;
this._storeContext = storeContext;
this._taxService = taxService;
this._currencyService = currencyService;
this._pictureService = pictureService;
this._localizationService = localizationService;
this._priceCalculationService = priceCalculationService;
this._priceFormatter = priceFormatter;
this._webHelper = webHelper;
this._specificationAttributeService = specificationAttributeService;
this._productTagService = productTagService;
this._genericAttributeService = genericAttributeService;
this._aclService = aclService;
this._storeMappingService = storeMappingService;
this._permissionService = permissionService;
this._customerActivityService = customerActivityService;
this._eventPublisher = eventPublisher;
this._searchTermService = searchTermService;
this._mediaSettings = mediaSettings;
this._catalogSettings = catalogSettings;
this._vendorSettings = vendorSettings;
this._blogSettings = blogSettings;
this._forumSettings = forumSettings;
_settingService = settingService;
_storeService = storeService;
_luceneService = luceneService;
_luceneSettings = luceneSettings;
_storeContext = storeContext;
}

#endregion
Expand All @@ -146,13 +41,15 @@ public ActionResult Configure()

var model = new ConfigurationModel();
model.Enabled = luceneSettings.Enabled;
model.AutoCompleteSearchEnabled = luceneSettings.AutoCompleteSearchEnabled;

model.ActiveStoreScopeConfiguration = storeScope;
if (storeScope > 0)
{
model.Enabled_OverrideForStore = _settingService.SettingExists(luceneSettings, x => x.Enabled, storeScope);
model.AutoCompleteSearchEnabled_OverrideForStore = _settingService.SettingExists(luceneSettings, x => x.AutoCompleteSearchEnabled, storeScope);
}

return View("~/Plugins/Nixtus.Misc.Lucene/Views/Configure.cshtml", model);
}

Expand All @@ -164,18 +61,24 @@ public ActionResult Configure(ConfigurationModel model)
{
if (!ModelState.IsValid)
return Configure();

//load settings for a chosen store scope
var storeScope = _storeContext.ActiveStoreScopeConfiguration;
var luceneSettings = _settingService.LoadSetting<LuceneSettings>(storeScope);

luceneSettings.Enabled = model.Enabled;
luceneSettings.AutoCompleteSearchEnabled = model.AutoCompleteSearchEnabled;

if (model.Enabled_OverrideForStore || storeScope == 0)
_settingService.SaveSetting(luceneSettings, x => x.Enabled, storeScope, false);
else if (storeScope > 0)
_settingService.DeleteSetting(luceneSettings, x => x.Enabled, storeScope);

if (model.AutoCompleteSearchEnabled_OverrideForStore || storeScope == 0)
_settingService.SaveSetting(luceneSettings, x => x.AutoCompleteSearchEnabled, storeScope, false);
else if (storeScope > 0)
_settingService.DeleteSetting(luceneSettings, x => x.AutoCompleteSearchEnabled, storeScope);

//now clear settings cache
_settingService.ClearCache();

Expand All @@ -190,9 +93,9 @@ public ActionResult RebuildIndex()
_luceneService.BuildIndex();

return Json(new
{
success = "0"
});
{
success = "0"
});
}
}
}
35 changes: 35 additions & 0 deletions Nixtus.Plugin.Widgets.Lucene/Infrastructure/RouterProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Nop.Core.Domain.Localization;
using Nop.Data;
using Nop.Services.Localization;
using Nop.Web.Framework.Mvc.Routing;
using System.Linq;

namespace Nixtus.Plugin.Widgets.Lucene.Infrastructure
{
public class RouterProvider : IRouteProvider
{
public int Priority => 1;

public void RegisterRoutes(IEndpointRouteBuilder endpointRouteBuilder)
{
var pattern = string.Empty;
if (DataSettingsManager.DatabaseIsInstalled)
{
var localizationSettings = endpointRouteBuilder.ServiceProvider.GetRequiredService<LocalizationSettings>();
if (localizationSettings.SeoFriendlyUrlsForLanguagesEnabled)
{
var langservice = endpointRouteBuilder.ServiceProvider.GetRequiredService<ILanguageService>();
var languages = langservice.GetAllLanguages().ToList();
pattern = "{language:lang=" + languages.FirstOrDefault().UniqueSeoCode + "}/";
}
}

// override autocomplete search
endpointRouteBuilder.MapControllerRoute("ProductSearchAutoComplete", $"{pattern}catalog/searchtermautocomplete",
new { controller = "LuceneCatalog", action = "SearchTermAutoComplete" });
}
}
}
22 changes: 17 additions & 5 deletions Nixtus.Plugin.Widgets.Lucene/LucenePlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Nop.Services.Configuration;
using Nop.Services.Localization;
using Nop.Services.Plugins;
using System.Collections.Generic;

namespace Nixtus.Plugin.Widgets.Lucene
{
Expand Down Expand Up @@ -31,14 +32,20 @@ public override void Install()
{
var settings = new LuceneSettings
{
Enabled = true
Enabled = true,
AutoCompleteSearchEnabled = true
};

_settingService.SaveSetting(settings);

//locales
_localizationService.AddOrUpdatePluginLocaleResource("Plugins.Misc.Lucene.Fields.Enabled", "Enabled Lucene search");
_localizationService.AddOrUpdatePluginLocaleResource("Plugins.Misc.Lucene.Fields.Enabled.Hint", "Turn on the Lucene Full-Text search funtionality");
_localizationService.AddPluginLocaleResource(new Dictionary<string, string>
{
{ "Plugins.Misc.Lucene.Fields.Enabled", "Enable Lucene search" },
{ "Plugins.Misc.Lucene.Fields.Enabled.Hint", "Turn on the Lucene Full-Text search funtionality" },
{ "Plugins.Misc.Lucene.Fields.AutoCompleteSearchEnabled", "Enable auto complete search" },
{ "Plugins.Misc.Lucene.Fields.AutoCompleteSearchEnabled.Hint", "Turn on the Lucene Full-Text search funtionality for auto complete" }
});

base.Install();
}
Expand All @@ -48,8 +55,13 @@ public override void Uninstall()
_settingService.DeleteSetting<LuceneSettings>();

//locales
_localizationService.DeletePluginLocaleResource("Plugins.Misc.Lucene.Fields.Enabled");
_localizationService.DeletePluginLocaleResource("Plugins.Misc.Lucene.Fields.Enabled.Hint");
_localizationService.DeletePluginLocaleResources(new List<string>
{
"Plugins.Misc.Lucene.Fields.Enabled",
"Plugins.Misc.Lucene.Fields.Enabled.Hint",
"Plugins.Misc.Lucene.Fields.AutoCompleteSearchEnabled",
"Plugins.Misc.Lucene.Fields.AutoCompleteSearchEnabled.Hint"
});

base.Uninstall();
}
Expand Down
2 changes: 2 additions & 0 deletions Nixtus.Plugin.Widgets.Lucene/LuceneSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@ namespace Nixtus.Plugin.Widgets.Lucene
public class LuceneSettings : ISettings
{
public bool Enabled { get; set; }

public bool AutoCompleteSearchEnabled { get; set; }
}
}
4 changes: 4 additions & 0 deletions Nixtus.Plugin.Widgets.Lucene/Models/ConfigurationModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,9 @@ public class ConfigurationModel
[NopResourceDisplayName("Plugins.Misc.Lucene.Fields.Enabled")]
public bool Enabled { get; set; }
public bool Enabled_OverrideForStore { get; set; }

[NopResourceDisplayName("Plugins.Misc.Lucene.Fields.AutoCompleteSearchEnabled")]
public bool AutoCompleteSearchEnabled { get; set; }
public bool AutoCompleteSearchEnabled_OverrideForStore { get; set; }
}
}
Loading

0 comments on commit 02515a0

Please sign in to comment.