From a8dc058cb5571538d1bc0b3f32314120ac2560a0 Mon Sep 17 00:00:00 2001 From: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com> Date: Wed, 29 Nov 2023 14:10:25 +0100 Subject: [PATCH] V13: Delivery API composite id handler (#15305) * Implement DeliveryApiCompositeIdHandler * Replace duplicate decomposing with Handler instead * Add obsolete messages * Make Id integer instead of string * Move from examine to core --------- Co-authored-by: Zeegaan --- .../DeliveryApiCompositeIdHandler.cs | 21 +++++++++++++ .../DeliveryApiIndexCompositeIdModel.cs | 8 +++++ .../IDeliveryApiCompositeIdHandler.cs | 8 +++++ .../DeliveryApiContentIndex.cs | 31 ++++++++++++------- .../UmbracoBuilder.Examine.cs | 2 ++ ...ApiContentIndexHandleContentTypeChanges.cs | 28 ++++++++++++++--- .../DeliveryApiContentIndexUtilites.cs | 8 ----- .../DeliveryApiContentIndexValueSetBuilder.cs | 28 ++++++++++++++++- 8 files changed, 109 insertions(+), 25 deletions(-) create mode 100644 src/Umbraco.Core/DeliveryApi/DeliveryApiCompositeIdHandler.cs create mode 100644 src/Umbraco.Core/DeliveryApi/DeliveryApiIndexCompositeIdModel.cs create mode 100644 src/Umbraco.Core/DeliveryApi/IDeliveryApiCompositeIdHandler.cs delete mode 100644 src/Umbraco.Infrastructure/Examine/DeliveryApiContentIndexUtilites.cs diff --git a/src/Umbraco.Core/DeliveryApi/DeliveryApiCompositeIdHandler.cs b/src/Umbraco.Core/DeliveryApi/DeliveryApiCompositeIdHandler.cs new file mode 100644 index 0000000000..a3c1f0fceb --- /dev/null +++ b/src/Umbraco.Core/DeliveryApi/DeliveryApiCompositeIdHandler.cs @@ -0,0 +1,21 @@ +namespace Umbraco.Cms.Core.DeliveryApi; + +public class DeliveryApiCompositeIdHandler : IDeliveryApiCompositeIdHandler +{ + public string IndexId(int id, string culture) => $"{id}|{culture}"; + + public DeliveryApiIndexCompositeIdModel Decompose(string indexId) + { + var parts = indexId.Split(Constants.CharArrays.VerticalTab); + if (parts.Length == 2 && int.TryParse(parts[0], out var id)) + { + return new DeliveryApiIndexCompositeIdModel + { + Id = id, + Culture = parts[1], + }; + } + + return new DeliveryApiIndexCompositeIdModel(); + } +} diff --git a/src/Umbraco.Core/DeliveryApi/DeliveryApiIndexCompositeIdModel.cs b/src/Umbraco.Core/DeliveryApi/DeliveryApiIndexCompositeIdModel.cs new file mode 100644 index 0000000000..d3b876b5aa --- /dev/null +++ b/src/Umbraco.Core/DeliveryApi/DeliveryApiIndexCompositeIdModel.cs @@ -0,0 +1,8 @@ +namespace Umbraco.Cms.Core.DeliveryApi; + +public class DeliveryApiIndexCompositeIdModel +{ + public int? Id { get; set; } + + public string? Culture { get; set; } +} diff --git a/src/Umbraco.Core/DeliveryApi/IDeliveryApiCompositeIdHandler.cs b/src/Umbraco.Core/DeliveryApi/IDeliveryApiCompositeIdHandler.cs new file mode 100644 index 0000000000..a472d0f9ff --- /dev/null +++ b/src/Umbraco.Core/DeliveryApi/IDeliveryApiCompositeIdHandler.cs @@ -0,0 +1,8 @@ +namespace Umbraco.Cms.Core.DeliveryApi; + +public interface IDeliveryApiCompositeIdHandler +{ + string IndexId(int id, string culture); + + DeliveryApiIndexCompositeIdModel Decompose(string indexId); +} diff --git a/src/Umbraco.Examine.Lucene/DeliveryApiContentIndex.cs b/src/Umbraco.Examine.Lucene/DeliveryApiContentIndex.cs index c70c9d4da0..a3508a3fed 100644 --- a/src/Umbraco.Examine.Lucene/DeliveryApiContentIndex.cs +++ b/src/Umbraco.Examine.Lucene/DeliveryApiContentIndex.cs @@ -1,8 +1,11 @@ using Examine; using Examine.Lucene; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Umbraco.Cms.Core; +using Umbraco.Cms.Core.DeliveryApi; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Hosting; using Umbraco.Cms.Core.Services; using Umbraco.Extensions; @@ -11,16 +14,30 @@ namespace Umbraco.Cms.Infrastructure.Examine; public class DeliveryApiContentIndex : UmbracoExamineIndex { + private readonly IDeliveryApiCompositeIdHandler _deliveryApiCompositeIdHandler; private readonly ILogger _logger; + [Obsolete("Use the constructor that takes an IDeliveryApiCompositeIdHandler instead, scheduled for removal in v15")] public DeliveryApiContentIndex( ILoggerFactory loggerFactory, string name, IOptionsMonitor indexOptions, IHostingEnvironment hostingEnvironment, IRuntimeState runtimeState) + : this(loggerFactory, name, indexOptions, hostingEnvironment, runtimeState, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public DeliveryApiContentIndex( + ILoggerFactory loggerFactory, + string name, + IOptionsMonitor indexOptions, + IHostingEnvironment hostingEnvironment, + IRuntimeState runtimeState, + IDeliveryApiCompositeIdHandler deliveryApiCompositeIdHandler) : base(loggerFactory, name, indexOptions, hostingEnvironment, runtimeState) { + _deliveryApiCompositeIdHandler = deliveryApiCompositeIdHandler; PublishedValuesOnly = false; EnableDefaultEventHandler = false; @@ -108,18 +125,8 @@ public class DeliveryApiContentIndex : UmbracoExamineIndex private (string? ContentId, string? Culture) ParseItemId(string id) { - if (int.TryParse(id, out _)) - { - return (id, null); - } - - var parts = id.Split(Constants.CharArrays.VerticalTab); - if (parts.Length == 2 && int.TryParse(parts[0], out _)) - { - return (parts[0], parts[1]); - } - - return (null, null); + DeliveryApiIndexCompositeIdModel compositeIdModel = _deliveryApiCompositeIdHandler.Decompose(id); + return (compositeIdModel.Id.ToString() ?? id, compositeIdModel.Culture); } protected override void OnTransformingIndexValues(IndexingItemEventArgs e) diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Examine.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Examine.cs index 5139cba48f..19aa103123 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Examine.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Examine.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Core.DeliveryApi; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Notifications; @@ -57,6 +58,7 @@ public static partial class UmbracoBuilderExtensions builder.Services.AddUnique(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); + builder.Services.AddUnique(); builder.AddNotificationHandler(); builder.AddNotificationHandler(); diff --git a/src/Umbraco.Infrastructure/Examine/Deferred/DeliveryApiContentIndexHandleContentTypeChanges.cs b/src/Umbraco.Infrastructure/Examine/Deferred/DeliveryApiContentIndexHandleContentTypeChanges.cs index 32dc801dd3..0cdfc10db6 100644 --- a/src/Umbraco.Infrastructure/Examine/Deferred/DeliveryApiContentIndexHandleContentTypeChanges.cs +++ b/src/Umbraco.Infrastructure/Examine/Deferred/DeliveryApiContentIndexHandleContentTypeChanges.cs @@ -1,6 +1,9 @@ using Examine; using Examine.Search; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core; +using Umbraco.Cms.Core.DeliveryApi; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Services.Changes; @@ -18,19 +21,33 @@ internal sealed class DeliveryApiContentIndexHandleContentTypeChanges : Delivery private readonly IDeliveryApiContentIndexValueSetBuilder _deliveryApiContentIndexValueSetBuilder; private readonly IContentService _contentService; private readonly IBackgroundTaskQueue _backgroundTaskQueue; + private readonly IDeliveryApiCompositeIdHandler _deliveryApiCompositeIdHandler; + [Obsolete("Use the constructor that takes an IDeliveryApiCompositeIdHandler instead, scheduled for removal in v15")] public DeliveryApiContentIndexHandleContentTypeChanges( IList> changes, DeliveryApiIndexingHandler deliveryApiIndexingHandler, IDeliveryApiContentIndexValueSetBuilder deliveryApiContentIndexValueSetBuilder, IContentService contentService, IBackgroundTaskQueue backgroundTaskQueue) + : this(changes, deliveryApiIndexingHandler, deliveryApiContentIndexValueSetBuilder, contentService, backgroundTaskQueue, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public DeliveryApiContentIndexHandleContentTypeChanges( + IList> changes, + DeliveryApiIndexingHandler deliveryApiIndexingHandler, + IDeliveryApiContentIndexValueSetBuilder deliveryApiContentIndexValueSetBuilder, + IContentService contentService, + IBackgroundTaskQueue backgroundTaskQueue, + IDeliveryApiCompositeIdHandler deliveryApiCompositeIdHandler) { _changes = changes; _deliveryApiIndexingHandler = deliveryApiIndexingHandler; _deliveryApiContentIndexValueSetBuilder = deliveryApiContentIndexValueSetBuilder; _contentService = contentService; _backgroundTaskQueue = backgroundTaskQueue; + _deliveryApiCompositeIdHandler = deliveryApiCompositeIdHandler; } public void Execute() => _backgroundTaskQueue.QueueBackgroundWorkItem(_ => @@ -79,10 +96,13 @@ internal sealed class DeliveryApiContentIndexHandleContentTypeChanges : Delivery var indexIdsByContentIds = indexIds .Select(id => { - var parts = id.Split(Constants.CharArrays.VerticalTab); - return parts.Length == 2 && int.TryParse(parts[0], out var contentId) - ? (ContentId: contentId, IndexId: id) - : throw new InvalidOperationException($"Delivery API identifier should be composite of ID and culture, got: {id}"); + DeliveryApiIndexCompositeIdModel compositeIdModel = _deliveryApiCompositeIdHandler.Decompose(id); + if (compositeIdModel.Id is null) + { + throw new InvalidOperationException($"Delivery API identifier should be composite of ID and culture, got: {id}"); + } + + return (ContentId: compositeIdModel.Id.Value, IndexId: compositeIdModel.Culture!); }) .GroupBy(tuple => tuple.ContentId) .ToDictionary( diff --git a/src/Umbraco.Infrastructure/Examine/DeliveryApiContentIndexUtilites.cs b/src/Umbraco.Infrastructure/Examine/DeliveryApiContentIndexUtilites.cs deleted file mode 100644 index 2bfd3d6f80..0000000000 --- a/src/Umbraco.Infrastructure/Examine/DeliveryApiContentIndexUtilites.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Umbraco.Cms.Core.Models; - -namespace Umbraco.Cms.Infrastructure.Examine; - -internal static class DeliveryApiContentIndexUtilites -{ - public static string IndexId(IContent content, string culture) => $"{content.Id}|{culture}"; -} diff --git a/src/Umbraco.Infrastructure/Examine/DeliveryApiContentIndexValueSetBuilder.cs b/src/Umbraco.Infrastructure/Examine/DeliveryApiContentIndexValueSetBuilder.cs index abf19b6bfe..e8226d994c 100644 --- a/src/Umbraco.Infrastructure/Examine/DeliveryApiContentIndexValueSetBuilder.cs +++ b/src/Umbraco.Infrastructure/Examine/DeliveryApiContentIndexValueSetBuilder.cs @@ -1,9 +1,11 @@ using Examine; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.DeliveryApi; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services; using Umbraco.Extensions; @@ -18,8 +20,10 @@ internal sealed class DeliveryApiContentIndexValueSetBuilder : IDeliveryApiConte private readonly ILogger _logger; private readonly IDeliveryApiContentIndexFieldDefinitionBuilder _deliveryApiContentIndexFieldDefinitionBuilder; private readonly IMemberService _memberService; + private readonly IDeliveryApiCompositeIdHandler _deliveryApiCompositeIdHandler; private DeliveryApiSettings _deliveryApiSettings; + [Obsolete("Please use ctor that takes an IDeliveryApiCompositeIdHandler. Scheduled for removal in v15")] public DeliveryApiContentIndexValueSetBuilder( ContentIndexHandlerCollection contentIndexHandlerCollection, IContentService contentService, @@ -28,12 +32,34 @@ internal sealed class DeliveryApiContentIndexValueSetBuilder : IDeliveryApiConte IDeliveryApiContentIndexFieldDefinitionBuilder deliveryApiContentIndexFieldDefinitionBuilder, IOptionsMonitor deliveryApiSettings, IMemberService memberService) + : this( + contentIndexHandlerCollection, + contentService, + publicAccessService, + logger, + deliveryApiContentIndexFieldDefinitionBuilder, + deliveryApiSettings, + memberService, + StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public DeliveryApiContentIndexValueSetBuilder( + ContentIndexHandlerCollection contentIndexHandlerCollection, + IContentService contentService, + IPublicAccessService publicAccessService, + ILogger logger, + IDeliveryApiContentIndexFieldDefinitionBuilder deliveryApiContentIndexFieldDefinitionBuilder, + IOptionsMonitor deliveryApiSettings, + IMemberService memberService, + IDeliveryApiCompositeIdHandler deliveryApiCompositeIdHandler) { _contentIndexHandlerCollection = contentIndexHandlerCollection; _publicAccessService = publicAccessService; _logger = logger; _deliveryApiContentIndexFieldDefinitionBuilder = deliveryApiContentIndexFieldDefinitionBuilder; _memberService = memberService; + _deliveryApiCompositeIdHandler = deliveryApiCompositeIdHandler; _contentService = contentService; _deliveryApiSettings = deliveryApiSettings.CurrentValue; deliveryApiSettings.OnChange(settings => _deliveryApiSettings = settings); @@ -73,7 +99,7 @@ internal sealed class DeliveryApiContentIndexValueSetBuilder : IDeliveryApiConte AddContentIndexHandlerFields(content, culture, fieldDefinitions, indexValues); - yield return new ValueSet(DeliveryApiContentIndexUtilites.IndexId(content, indexCulture), IndexTypes.Content, content.ContentType.Alias, indexValues); + yield return new ValueSet(_deliveryApiCompositeIdHandler.IndexId(content.Id, indexCulture), IndexTypes.Content, content.ContentType.Alias, indexValues); } } }