Skip to content

Instantly share code, notes, and snippets.

@karlstal
Created December 1, 2023 12:55
Show Gist options
  • Save karlstal/7f8d17e9e41825ce8165c6f285598a1c to your computer and use it in GitHub Desktop.
Save karlstal/7f8d17e9e41825ce8165c6f285598a1c to your computer and use it in GitHub Desktop.
A Commerce Search Provider that filter on CatalogContentBase instead of EntryContentBase which allows for hits on node content in catalog ui search.
using EPiServer.Find;
using EPiServer.Find.Cms;
using EPiServer.Find.Cms.SearchProviders;
using EPiServer.Find.Commerce;
using EPiServer.Find.Framework;
using EPiServer.Find.Framework.UI.Localization;
using EPiServer.Find.Helpers.Text;
using EPiServer.Shell;
using EPiServer.Shell.Search;
namespace MySite
{
[SearchProvider]
// Changed first parameter so it accepts CatalogContentBase instead of only EntryContentBase.
public class BetterCommerceSearchProvider : EnterpriseContentSearchProviderBase<CatalogContentBase, ContentType>
{
private static readonly string SearchArea = "Commerce/Catalog";
public BetterCommerceSearchProvider(LocalizationService localizationService,
ISiteDefinitionResolver siteDefinitionResolver,
IContentTypeRepository contentTypeRepository,
UIDescriptorRegistry uiDescriptorRegistry,
EditUrlResolver editUrlResolver,
ServiceAccessor<SiteDefinition> currentSiteDefinition,
IContentLanguageAccessor languageResolver,
IUrlResolver urlResolver,
ITemplateResolver templateResolver,
IContentRepository contentRepository)
: base(localizationService, siteDefinitionResolver, contentTypeRepository, uiDescriptorRegistry, editUrlResolver, currentSiteDefinition, languageResolver, urlResolver, templateResolver, contentRepository)
{
// set the EditPath function to return the Commerce edit Url instead of CMS one
EditPath = GetEditPath;
}
// Changed first parameter so it accepts CatalogContentBase instead of only EntryContentBase.
private string GetEditPath(CatalogContentBase entryContent, ContentReference contentLink, string languageName)
{
var catalogPath = Paths.ToResource("Commerce", "Catalog");
if (catalogPath == "/")
{
catalogPath = Paths.ToResource("CMS", null);
}
if (!string.IsNullOrWhiteSpace(languageName))
{
return string.Format("{0}?language={1}#context={2}", catalogPath, languageName, entryContent.GetUri());
}
return string.Format("{0}#context={1}", catalogPath, entryContent.GetUri());
}
public override string Area
{
get { return SearchArea; }
}
public override string Category
{
get { return Text.Translate("/commerce/searchprovider/product/name"); }
}
protected override string IconCssClass => FindContentSearchProviderConstants.PageIconCssClass;
protected override ITypeSearch<IContentData> GetFieldQuery(string searchQuery, int maxResults)
{
// Did some general improvements here, since the base
var findQuery = SearchClient.Instance.Search<CatalogContentBase>();
if (searchQuery.IsNotNullOrEmpty())
{
var normalizedQuery = EscapeForQuery(searchQuery);
findQuery = findQuery.For(searchQuery)
.InField(x => x.SearchTitle())
.InField(x => x.SearchText())
/* You should install the Find Toolbox
(https://github.com/episerver/EPiServer.Labs.Find.Toolbox/tree/master#fuzzymatch-and-wildcardmatch)
and add: */
// .WildcardMatch()
.BoostMatching(x => ((EntryContentBase)x).EscapedQueryableCode().Match(normalizedQuery), 2);
}
return findQuery.Take(maxResults);
}
private string EscapeForQuery(string input)
{
if (input == null)
{
return null;
}
var buffer = new StringBuilder();
foreach (var c in input)
{
// 0-9: [0x30, 0x39], A-Z: [0x41, 0x5A], a-z: [0x61, 0x7A]
if (c > 'z' || c < '0' || (c > '9' && c < 'A') || (c > 'Z' && c < 'a'))
{
// Non-ascii or non-alphanumeric. Write unicode position in hex instead.
buffer.AppendFormat("{0:X}", (int)c);
}
else
{
buffer.Append(c);
}
}
return buffer.ToString();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment