diff --git a/src/Umbraco.Cms.Api.Delivery/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Cms.Api.Delivery/DependencyInjection/UmbracoBuilderExtensions.cs index 9f56f591ce..5ecc856f3b 100644 --- a/src/Umbraco.Cms.Api.Delivery/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Cms.Api.Delivery/DependencyInjection/UmbracoBuilderExtensions.cs @@ -15,6 +15,7 @@ using Umbraco.Cms.Api.Delivery.Rendering; using Umbraco.Cms.Api.Delivery.Routing; using Umbraco.Cms.Api.Delivery.Security; using Umbraco.Cms.Api.Delivery.Services; +using Umbraco.Cms.Api.Delivery.Services.QueryBuilders; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.DeliveryApi; @@ -55,6 +56,7 @@ public static class UmbracoBuilderExtensions builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); + builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddTransient(); builder.Services.AddTransient(); diff --git a/src/Umbraco.Cms.Api.Delivery/Services/ApiContentQueryProvider.cs b/src/Umbraco.Cms.Api.Delivery/Services/ApiContentQueryProvider.cs index 5b191b5262..cafb27ad71 100644 --- a/src/Umbraco.Cms.Api.Delivery/Services/ApiContentQueryProvider.cs +++ b/src/Umbraco.Cms.Api.Delivery/Services/ApiContentQueryProvider.cs @@ -1,4 +1,4 @@ -using Examine; +using Examine; using Examine.Search; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -27,6 +27,7 @@ internal sealed class ApiContentQueryProvider : IApiContentQueryProvider public ApiContentQueryProvider( IExamineManager examineManager, ContentIndexHandlerCollection indexHandlers, + IApiContentQueryFactory apiContentQueryFactory, IOptions deliveryApiSettings, ILogger logger) { @@ -41,7 +42,7 @@ internal sealed class ApiContentQueryProvider : IApiContentQueryProvider // for the time being we're going to keep these as internal implementation details. // perhaps later on it will make sense to expose them through the DI. - _selectorBuilder = new ApiContentQuerySelectorBuilder(deliveryApiSettings.Value); + _selectorBuilder = new ApiContentQuerySelectorBuilder(deliveryApiSettings.Value, apiContentQueryFactory); _filterBuilder = new ApiContentQueryFilterBuilder(fieldTypes, _logger); _sortBuilder = new ApiContentQuerySortBuilder(fieldTypes, _logger); diff --git a/src/Umbraco.Cms.Api.Delivery/Services/QueryBuilders/ApiContentQueryFactory.cs b/src/Umbraco.Cms.Api.Delivery/Services/QueryBuilders/ApiContentQueryFactory.cs new file mode 100644 index 0000000000..6add9861ab --- /dev/null +++ b/src/Umbraco.Cms.Api.Delivery/Services/QueryBuilders/ApiContentQueryFactory.cs @@ -0,0 +1,26 @@ +using Examine; +using Examine.Lucene.Providers; +using Examine.Lucene.Search; +using Examine.Search; +using Umbraco.Cms.Infrastructure.Examine; + +namespace Umbraco.Cms.Api.Delivery.Services.QueryBuilders +{ + internal sealed class ApiContentQueryFactory : IApiContentQueryFactory + { + /// + public IQuery CreateApiContentQuery(IIndex index) + { + // Needed for enabling leading wildcards searches + BaseLuceneSearcher searcher = index.Searcher as BaseLuceneSearcher ?? throw new InvalidOperationException($"Index searcher must be of type {nameof(BaseLuceneSearcher)}."); + + IQuery query = searcher.CreateQuery( + IndexTypes.Content, + BooleanOperation.And, + searcher.LuceneAnalyzer, + new LuceneSearchOptions { AllowLeadingWildcard = true }); + + return query; + } + } +} diff --git a/src/Umbraco.Cms.Api.Delivery/Services/QueryBuilders/ApiContentQuerySelectorBuilder.cs b/src/Umbraco.Cms.Api.Delivery/Services/QueryBuilders/ApiContentQuerySelectorBuilder.cs index c39f6f3f51..3d3c1ba225 100644 --- a/src/Umbraco.Cms.Api.Delivery/Services/QueryBuilders/ApiContentQuerySelectorBuilder.cs +++ b/src/Umbraco.Cms.Api.Delivery/Services/QueryBuilders/ApiContentQuerySelectorBuilder.cs @@ -1,6 +1,4 @@ using Examine; -using Examine.Lucene.Providers; -using Examine.Lucene.Search; using Examine.Search; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.DeliveryApi; @@ -13,11 +11,15 @@ namespace Umbraco.Cms.Api.Delivery.Services.QueryBuilders; internal sealed class ApiContentQuerySelectorBuilder { private readonly DeliveryApiSettings _deliveryApiSettings; + private readonly IApiContentQueryFactory _queryFactory; private readonly string _fallbackGuidValue; - public ApiContentQuerySelectorBuilder(DeliveryApiSettings deliveryApiSettings) + public ApiContentQuerySelectorBuilder( + DeliveryApiSettings deliveryApiSettings, + IApiContentQueryFactory queryFactory) { _deliveryApiSettings = deliveryApiSettings; + _queryFactory = queryFactory; // A fallback value is needed for Examine queries in case we don't have a value - we can't pass null or empty string // It is set to a random guid since this would be highly unlikely to yield any results @@ -26,14 +28,7 @@ internal sealed class ApiContentQuerySelectorBuilder public IBooleanOperation Build(SelectorOption selectorOption, IIndex index, string culture, ProtectedAccess protectedAccess, bool preview) { - // Needed for enabling leading wildcards searches - BaseLuceneSearcher searcher = index.Searcher as BaseLuceneSearcher ?? throw new InvalidOperationException($"Index searcher must be of type {nameof(BaseLuceneSearcher)}."); - - IQuery query = searcher.CreateQuery( - IndexTypes.Content, - BooleanOperation.And, - searcher.LuceneAnalyzer, - new LuceneSearchOptions { AllowLeadingWildcard = true }); + IQuery query = _queryFactory.CreateApiContentQuery(index); IBooleanOperation selectorOperation = selectorOption.Values.Length == 1 ? query.Field(selectorOption.FieldName, selectorOption.Values.First()) diff --git a/src/Umbraco.Cms.Api.Delivery/Services/QueryBuilders/IApiContentQueryFactory.cs b/src/Umbraco.Cms.Api.Delivery/Services/QueryBuilders/IApiContentQueryFactory.cs new file mode 100644 index 0000000000..3ff51afed8 --- /dev/null +++ b/src/Umbraco.Cms.Api.Delivery/Services/QueryBuilders/IApiContentQueryFactory.cs @@ -0,0 +1,18 @@ +using Examine; +using Examine.Search; + +namespace Umbraco.Cms.Api.Delivery.Services.QueryBuilders +{ + /// + /// Used to create an instance for content items for the content delivery api. + /// + public interface IApiContentQueryFactory + { + /// + /// Creates an for content items for the content delivery api. + /// + /// The . + /// An instance. + IQuery CreateApiContentQuery(IIndex index); + } +}