diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Document/GetPublicAccessDocumentController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Document/GetPublicAccessDocumentController.cs index dcb27ac42a..cdcdc1c85c 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Document/GetPublicAccessDocumentController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Document/GetPublicAccessDocumentController.cs @@ -49,7 +49,7 @@ public class GetPublicAccessDocumentController : DocumentControllerBase } Attempt accessAttempt = - await _publicAccessService.GetEntryByContentKeyAsync(id); + await _publicAccessService.GetEntryByContentKeyWithoutAncestorsAsync(id); if (accessAttempt.Success is false || accessAttempt.Result is null) { diff --git a/src/Umbraco.Core/DeliveryApi/ApiContentRouteBuilder.cs b/src/Umbraco.Core/DeliveryApi/ApiContentRouteBuilder.cs index 306cf7f3ee..221a1a1af5 100644 --- a/src/Umbraco.Core/DeliveryApi/ApiContentRouteBuilder.cs +++ b/src/Umbraco.Core/DeliveryApi/ApiContentRouteBuilder.cs @@ -1,5 +1,7 @@ -using Microsoft.Extensions.Options; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Configuration.Models; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Models.DeliveryApi; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.PublishedCache; @@ -16,6 +18,7 @@ public sealed class ApiContentRouteBuilder : IApiContentRouteBuilder private readonly IRequestPreviewService _requestPreviewService; private readonly IPublishedContentCache _contentCache; private readonly IDocumentNavigationQueryService _navigationQueryService; + private readonly IPublishStatusQueryService _publishStatusQueryService; private RequestHandlerSettings _requestSettings; public ApiContentRouteBuilder( @@ -25,18 +28,41 @@ public sealed class ApiContentRouteBuilder : IApiContentRouteBuilder IRequestPreviewService requestPreviewService, IOptionsMonitor requestSettings, IPublishedContentCache contentCache, - IDocumentNavigationQueryService navigationQueryService) + IDocumentNavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService) { _apiContentPathProvider = apiContentPathProvider; _variationContextAccessor = variationContextAccessor; _requestPreviewService = requestPreviewService; _contentCache = contentCache; _navigationQueryService = navigationQueryService; + _publishStatusQueryService = publishStatusQueryService; _globalSettings = globalSettings.Value; _requestSettings = requestSettings.CurrentValue; requestSettings.OnChange(settings => _requestSettings = settings); } + [Obsolete("Use constructor that takes an IPublishStatusQueryService instead, scheduled for removal in v17")] + public ApiContentRouteBuilder( + IApiContentPathProvider apiContentPathProvider, + IOptions globalSettings, + IVariationContextAccessor variationContextAccessor, + IRequestPreviewService requestPreviewService, + IOptionsMonitor requestSettings, + IPublishedContentCache contentCache, + IDocumentNavigationQueryService navigationQueryService) + : this( + apiContentPathProvider, + globalSettings, + variationContextAccessor, + requestPreviewService, + requestSettings, + contentCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService()) + { + } + public IApiContentRoute? Build(IPublishedContent content, string? culture = null) { if (content.ItemType != PublishedItemType.Content) @@ -105,7 +131,7 @@ public sealed class ApiContentRouteBuilder : IApiContentRouteBuilder { if (isPreview is false) { - return content.Root(_contentCache, _navigationQueryService); + return content.Root(_variationContextAccessor, _contentCache, _navigationQueryService, _publishStatusQueryService); } _navigationQueryService.TryGetRootKeys(out IEnumerable rootKeys); @@ -114,6 +140,6 @@ public sealed class ApiContentRouteBuilder : IApiContentRouteBuilder // in very edge case scenarios during preview, content.Root() does not map to the root. // we'll code our way around it for the time being. return rootContent.FirstOrDefault(root => root.IsAncestorOrSelf(content)) - ?? content.Root(_contentCache, _navigationQueryService); + ?? content.Root(_variationContextAccessor, _contentCache, _navigationQueryService, _publishStatusQueryService); } } diff --git a/src/Umbraco.Core/Extensions/PublishedContentExtensions.cs b/src/Umbraco.Core/Extensions/PublishedContentExtensions.cs index f2718eb87d..adfdbb6076 100644 --- a/src/Umbraco.Core/Extensions/PublishedContentExtensions.cs +++ b/src/Umbraco.Core/Extensions/PublishedContentExtensions.cs @@ -2,7 +2,6 @@ // See LICENSE for more details. using System.Data; -using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.DependencyInjection; @@ -522,15 +521,70 @@ public static class PublishedContentExtensions /// Gets the ancestors of the content. /// /// The content. + /// /// The content cache. /// The query service for the in-memory navigation structure. + /// /// The ancestors of the content, in down-top order. /// Does not consider the content itself. public static IEnumerable Ancestors( this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, - INavigationQueryService navigationQueryService) => - content.AncestorsOrSelf(publishedCache, navigationQueryService, false, null); + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService) => + content.AncestorsOrSelf( + variationContextAccessor, + publishedCache, + navigationQueryService, + publishStatusQueryService, + false, + null); + + /// + /// Gets the ancestors of the content. + /// + /// The content. + /// The content cache. + /// The query service for the in-memory navigation structure. + /// The ancestors of the content, in down-top order. + /// Does not consider the content itself. + [Obsolete("Use the overload with IVariationContextAccessor and IPublishStatusQueryService, scheduled for removal in v17")] + public static IEnumerable Ancestors( + this IPublishedContent content, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService) => Ancestors( + content, + StaticServiceProvider.Instance.GetRequiredService(), + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService()); + + /// + /// Gets the ancestors of the content, at a level lesser or equal to a specified level. + /// + /// The content. + /// + /// The content cache. + /// The query service for the in-memory navigation structure. + /// + /// The level. + /// The ancestors of the content, at a level lesser or equal to the specified level, in down-top order. + /// Does not consider the content itself. Only content that are "high enough" in the tree are returned. + public static IEnumerable Ancestors( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + int maxLevel) => + content.AncestorsOrSelf( + variationContextAccessor, + publishedCache, + navigationQueryService, + publishStatusQueryService, + false, + n => n.Level <= maxLevel); /// /// Gets the ancestors of the content, at a level lesser or equal to a specified level. @@ -541,12 +595,50 @@ public static class PublishedContentExtensions /// The level. /// The ancestors of the content, at a level lesser or equal to the specified level, in down-top order. /// Does not consider the content itself. Only content that are "high enough" in the tree are returned. + [Obsolete("Use the overload with IVariationContextAccessor and IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable Ancestors( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int maxLevel) => - content.AncestorsOrSelf(publishedCache, navigationQueryService, false, n => n.Level <= maxLevel); + Ancestors( + content, + StaticServiceProvider.Instance.GetRequiredService(), + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + maxLevel); + + + /// + /// Gets the ancestors of the content, of a specified content type. + /// + /// The content. + /// + /// The content cache. + /// The query service for the in-memory navigation structure. + /// + /// The content type. + /// The ancestors of the content, of the specified content type, in down-top order. + /// Does not consider the content itself. Returns all ancestors, of the specified content type. + public static IEnumerable Ancestors( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + string contentTypeAlias) + { + ArgumentNullException.ThrowIfNull(content); + + return content.EnumerateAncestorsOrSelfInternal( + variationContextAccessor, + publishedCache, + navigationQueryService, + publishStatusQueryService, + false, + contentTypeAlias); + } /// /// Gets the ancestors of the content, of a specified content type. @@ -557,16 +649,39 @@ public static class PublishedContentExtensions /// The content type. /// The ancestors of the content, of the specified content type, in down-top order. /// Does not consider the content itself. Returns all ancestors, of the specified content type. + [Obsolete("Use the overload with IVariationContextAccessor and IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable Ancestors( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, - string contentTypeAlias) - { - ArgumentNullException.ThrowIfNull(content); + string contentTypeAlias) => + Ancestors( + content, + StaticServiceProvider.Instance.GetRequiredService(), + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + contentTypeAlias); - return content.EnumerateAncestorsOrSelfInternal(publishedCache, navigationQueryService, false, contentTypeAlias); - } + /// + /// Gets the ancestors of the content, of a specified content type. + /// + /// The content type. + /// The content. + /// + /// The content cache. + /// The query service for the in-memory navigation structure. + /// + /// The ancestors of the content, of the specified content type, in down-top order. + /// Does not consider the content itself. Returns all ancestors, of the specified content type. + public static IEnumerable Ancestors( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService) + where T : class, IPublishedContent => + content.Ancestors(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService).OfType(); /// /// Gets the ancestors of the content, of a specified content type. @@ -577,12 +692,47 @@ public static class PublishedContentExtensions /// The query service for the in-memory navigation structure. /// The ancestors of the content, of the specified content type, in down-top order. /// Does not consider the content itself. Returns all ancestors, of the specified content type. + [Obsolete("Use the overload with IVariationContextAccessor and IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable Ancestors( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService) where T : class, IPublishedContent => - content.EnumerateAncestorsOrSelfInternal(publishedCache, navigationQueryService, false); + Ancestors( + content, + StaticServiceProvider.Instance.GetRequiredService(), + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService()); + + /// + /// Gets the ancestors of the content, at a level lesser or equal to a specified level, and of a specified content + /// type. + /// + /// The content type. + /// The content. + /// + /// The content cache. + /// The query service for the in-memory navigation structure. + /// + /// The level. + /// + /// The ancestors of the content, at a level lesser or equal to the specified level, and of the specified + /// content type, in down-top order. + /// + /// + /// Does not consider the content itself. Only content that are "high enough" in the trees, and of the + /// specified content type, are returned. + /// + public static IEnumerable Ancestors( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + int maxLevel) + where T : class, IPublishedContent => + content.Ancestors(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, maxLevel).OfType(); /// /// Gets the ancestors of the content, at a level lesser or equal to a specified level, and of a specified content @@ -601,14 +751,43 @@ public static class PublishedContentExtensions /// Does not consider the content itself. Only content that are "high enough" in the trees, and of the /// specified content type, are returned. /// + [Obsolete("Use the overload with IVariationContextAccessor and IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable Ancestors( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int maxLevel) - where T : class, IPublishedContent => content - .EnumerateAncestorsOrSelfInternal(publishedCache, navigationQueryService, false) - .Where(n => n.Level <= maxLevel); + where T : class, IPublishedContent => + Ancestors( + content, + StaticServiceProvider.Instance.GetRequiredService(), + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + maxLevel); + + /// + /// Gets the content and its ancestors. + /// + /// The content. + /// + /// The content cache. + /// The query service for the in-memory navigation structure. + /// + /// The content and its ancestors, in down-top order. + public static IEnumerable AncestorsOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService) => + content.AncestorsOrSelf( + variationContextAccessor, + publishedCache, + navigationQueryService, + publishStatusQueryService, + true, + null); /// /// Gets the content and its ancestors. @@ -617,11 +796,49 @@ public static class PublishedContentExtensions /// The content cache. /// The query service for the in-memory navigation structure. /// The content and its ancestors, in down-top order. + [Obsolete("Use the overload with IVariationContextAccessor and IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable AncestorsOrSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService) => - content.AncestorsOrSelf(publishedCache, navigationQueryService, true, null); + AncestorsOrSelf( + content, + StaticServiceProvider.Instance.GetRequiredService(), + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService()); + + /// + /// Gets the content and its ancestors, at a level lesser or equal to a specified level. + /// + /// The content. + /// + /// The content cache. + /// The query service for the in-memory navigation structure. + /// + /// The level. + /// + /// The content and its ancestors, at a level lesser or equal to the specified level, + /// in down-top order. + /// + /// + /// Only content that are "high enough" in the tree are returned. So it may or may not begin + /// with the content itself, depending on its level. + /// + public static IEnumerable AncestorsOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + int maxLevel) => + content.AncestorsOrSelf( + variationContextAccessor, + publishedCache, + navigationQueryService, + publishStatusQueryService, + true, + n => n.Level <= maxLevel); /// /// Gets the content and its ancestors, at a level lesser or equal to a specified level. @@ -638,12 +855,49 @@ public static class PublishedContentExtensions /// Only content that are "high enough" in the tree are returned. So it may or may not begin /// with the content itself, depending on its level. /// + [Obsolete("Use the overload with IVariationContextAccessor and IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable AncestorsOrSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int maxLevel) => - content.AncestorsOrSelf(publishedCache, navigationQueryService, true, n => n.Level <= maxLevel); + AncestorsOrSelf( + content, + StaticServiceProvider.Instance.GetRequiredService(), + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + maxLevel); + + /// + /// Gets the content and its ancestors, of a specified content type. + /// + /// The content. + /// + /// The content cache. + /// The query service for the in-memory navigation structure. + /// + /// The content type. + /// The content and its ancestors, of the specified content type, in down-top order. + /// May or may not begin with the content itself, depending on its content type. + public static IEnumerable AncestorsOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + string contentTypeAlias) + { + ArgumentNullException.ThrowIfNull(content); + + return content.EnumerateAncestorsOrSelfInternal( + variationContextAccessor, + publishedCache, + navigationQueryService, + publishStatusQueryService, + true, + contentTypeAlias); + } /// /// Gets the content and its ancestors, of a specified content type. @@ -654,16 +908,39 @@ public static class PublishedContentExtensions /// The content type. /// The content and its ancestors, of the specified content type, in down-top order. /// May or may not begin with the content itself, depending on its content type. + [Obsolete("Use the overload with IVariationContextAccessor and IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable AncestorsOrSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, - string contentTypeAlias) - { - ArgumentNullException.ThrowIfNull(content); + string contentTypeAlias) => + AncestorsOrSelf( + content, + StaticServiceProvider.Instance.GetRequiredService(), + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + contentTypeAlias); - return content.EnumerateAncestorsOrSelfInternal(publishedCache, navigationQueryService, true, contentTypeAlias); - } + /// + /// Gets the content and its ancestors, of a specified content type. + /// + /// The content type. + /// The content. + /// + /// The content cache. + /// The query service for the in-memory navigation structure. + /// + /// The content and its ancestors, of the specified content type, in down-top order. + /// May or may not begin with the content itself, depending on its content type. + public static IEnumerable AncestorsOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService) + where T : class, IPublishedContent => + content.AncestorsOrSelf(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService).OfType(); /// /// Gets the content and its ancestors, of a specified content type. @@ -674,12 +951,43 @@ public static class PublishedContentExtensions /// The query service for the in-memory navigation structure. /// The content and its ancestors, of the specified content type, in down-top order. /// May or may not begin with the content itself, depending on its content type. + [Obsolete("Use the overload with IVariationContextAccessor and IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable AncestorsOrSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService) + where T : class, IPublishedContent => AncestorsOrSelf( + content, + StaticServiceProvider.Instance.GetRequiredService(), + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService()); + + /// + /// Gets the content and its ancestor, at a lever lesser or equal to a specified level, and of a specified content + /// type. + /// + /// The content type. + /// The content. + /// + /// The content cache. + /// The query service for the in-memory navigation structure. + /// + /// The level. + /// + /// The content and its ancestors, at a level lesser or equal to the specified level, and of the specified + /// content type, in down-top order. + /// + /// May or may not begin with the content itself, depending on its level and content type. + public static IEnumerable AncestorsOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + int maxLevel) where T : class, IPublishedContent => - content.EnumerateAncestorsOrSelfInternal(publishedCache, navigationQueryService, true); + content.AncestorsOrSelf(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, maxLevel).OfType(); /// /// Gets the content and its ancestor, at a lever lesser or equal to a specified level, and of a specified content @@ -695,14 +1003,19 @@ public static class PublishedContentExtensions /// content type, in down-top order. /// /// May or may not begin with the content itself, depending on its level and content type. + [Obsolete("Use the overload with IVariationContextAccessor and IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable AncestorsOrSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int maxLevel) - where T : class, IPublishedContent => content - .EnumerateAncestorsOrSelfInternal(publishedCache, navigationQueryService, true) - .Where(n => n.Level <= maxLevel); + where T : class, IPublishedContent => AncestorsOrSelf( + content, + StaticServiceProvider.Instance.GetRequiredService(), + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + maxLevel); /// /// Gets the ancestor of the content, ie its parent. @@ -722,17 +1035,80 @@ public static class PublishedContentExtensions /// Gets the nearest ancestor of the content, at a lever lesser or equal to a specified level. /// /// The content. + /// /// The content cache. /// The query service for the in-memory navigation structure. + /// The query service for the in-memory navigation structure. /// The level. /// The nearest (in down-top order) ancestor of the content, at a level lesser or equal to the specified level. /// Does not consider the content itself. May return null. + public static IPublishedContent? Ancestor( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + int maxLevel) => + content.EnumerateAncestors( + variationContextAccessor, + publishedCache, + navigationQueryService, + publishStatusQueryService, + false).FirstOrDefault(x => x.Level <= maxLevel); + + /// + /// Gets the nearest ancestor of the content, at a lever lesser or equal to a specified level. + /// + /// The content. + /// The content cache. + /// The query service for the in-memory navigation structure. + /// The level. + /// The nearest (in down-top order) ancestor of the content, at a level lesser or equal to the specified level. + /// Does not consider the content itself. May return null. + [Obsolete("Use the overload with IVariationContextAccessor and IPublishStatusQueryService, scheduled for removal in v17")] public static IPublishedContent? Ancestor( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int maxLevel) => - content.EnumerateAncestors(publishedCache, navigationQueryService, false).FirstOrDefault(x => x.Level <= maxLevel); + Ancestor( + content, + StaticServiceProvider.Instance.GetRequiredService(), + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + maxLevel); + + /// + /// Gets the nearest ancestor of the content, of a specified content type. + /// + /// The content. + /// + /// The content cache. + /// The query service for the in-memory navigation structure. + /// + /// The content type alias. + /// The nearest (in down-top order) ancestor of the content, of the specified content type. + /// Does not consider the content itself. May return null. + public static IPublishedContent? Ancestor( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + string contentTypeAlias) + { + ArgumentNullException.ThrowIfNull(content); + + return content + .EnumerateAncestorsOrSelfInternal( + variationContextAccessor, + publishedCache, + navigationQueryService, + publishStatusQueryService, + false, + contentTypeAlias).FirstOrDefault(); + } /// /// Gets the nearest ancestor of the content, of a specified content type. @@ -743,18 +1119,39 @@ public static class PublishedContentExtensions /// The content type alias. /// The nearest (in down-top order) ancestor of the content, of the specified content type. /// Does not consider the content itself. May return null. + [Obsolete("Use the overload with IVariationContextAccessor and IPublishStatusQueryService, scheduled for removal in v17")] public static IPublishedContent? Ancestor( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, - string contentTypeAlias) - { - ArgumentNullException.ThrowIfNull(content); + string contentTypeAlias) => + Ancestor( + content, + StaticServiceProvider.Instance.GetRequiredService(), + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + contentTypeAlias); - return content - .EnumerateAncestorsOrSelfInternal(publishedCache, navigationQueryService, false, contentTypeAlias) - .FirstOrDefault(); - } + /// + /// Gets the nearest ancestor of the content, of a specified content type. + /// + /// The content type. + /// The content. + /// + /// The content cache. + /// The query service for the in-memory navigation structure. + /// + /// The nearest (in down-top order) ancestor of the content, of the specified content type. + /// Does not consider the content itself. May return null. + public static T? Ancestor( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService) + where T : class, IPublishedContent => + content.Ancestors(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService).FirstOrDefault(); /// /// Gets the nearest ancestor of the content, of a specified content type. @@ -765,12 +1162,48 @@ public static class PublishedContentExtensions /// The query service for the in-memory navigation structure. /// The nearest (in down-top order) ancestor of the content, of the specified content type. /// Does not consider the content itself. May return null. + [Obsolete("Use the overload with IVariationContextAccessor and IPublishStatusQueryService, scheduled for removal in v17")] public static T? Ancestor( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService) where T : class, IPublishedContent => - content.Ancestors(publishedCache, navigationQueryService).FirstOrDefault(); + Ancestor( + content, + StaticServiceProvider.Instance.GetRequiredService(), + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService()); + + /// + /// Gets the nearest ancestor of the content, at the specified level and of the specified content type. + /// + /// The content type. + /// The content. + /// + /// The content cache. + /// The query service for the in-memory navigation structure. + /// + /// The level. + /// The ancestor of the content, at the specified level and of the specified content type. + /// + /// Does not consider the content itself. If the ancestor at the specified level is + /// not of the specified type, returns null. + /// + public static T? Ancestor( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + int maxLevel) + where T : class, IPublishedContent => + content.Ancestors( + variationContextAccessor, + publishedCache, + navigationQueryService, + publishStatusQueryService, + maxLevel).FirstOrDefault(); /// /// Gets the nearest ancestor of the content, at the specified level and of the specified content type. @@ -785,13 +1218,20 @@ public static class PublishedContentExtensions /// Does not consider the content itself. If the ancestor at the specified level is /// not of the specified type, returns null. /// + [Obsolete("Use the overload with IVariationContextAccessor and IPublishStatusQueryService, scheduled for removal in v17")] public static T? Ancestor( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int maxLevel) where T : class, IPublishedContent => - content.Ancestors(publishedCache, navigationQueryService, maxLevel).FirstOrDefault(); + Ancestor( + content, + StaticServiceProvider.Instance.GetRequiredService(), + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + maxLevel); /// /// Gets the content or its nearest ancestor. @@ -805,17 +1245,82 @@ public static class PublishedContentExtensions /// Gets the content or its nearest ancestor, at a lever lesser or equal to a specified level. /// /// The content. + /// /// The content cache. /// The query service for the in-memory navigation structure. + /// The query service for the in-memory navigation structure. /// The level. /// The content or its nearest (in down-top order) ancestor, at a level lesser or equal to the specified level. /// May or may not return the content itself depending on its level. May return null. + public static IPublishedContent AncestorOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + int maxLevel) => + content.EnumerateAncestors( + variationContextAccessor, + publishedCache, + navigationQueryService, + publishStatusQueryService, + true) + .FirstOrDefault(x => x.Level <= maxLevel) ?? content; + + /// + /// Gets the content or its nearest ancestor, at a lever lesser or equal to a specified level. + /// + /// The content. + /// The content cache. + /// The query service for the in-memory navigation structure. + /// The level. + /// The content or its nearest (in down-top order) ancestor, at a level lesser or equal to the specified level. + /// May or may not return the content itself depending on its level. May return null. + [Obsolete("Use the overload with IVariationContextAccessor and IPublishStatusQueryService, scheduled for removal in v17")] public static IPublishedContent AncestorOrSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int maxLevel) => - content.EnumerateAncestors(publishedCache, navigationQueryService, true).FirstOrDefault(x => x.Level <= maxLevel) ?? content; + AncestorOrSelf( + content, + StaticServiceProvider.Instance.GetRequiredService(), + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + maxLevel); + + /// + /// Gets the content or its nearest ancestor, of a specified content type. + /// + /// The content. + /// + /// The content cache. + /// The query service for the in-memory navigation structure. + /// + /// The content type. + /// The content or its nearest (in down-top order) ancestor, of the specified content type. + /// May or may not return the content itself depending on its content type. May return null. + public static IPublishedContent AncestorOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + string contentTypeAlias) + { + ArgumentNullException.ThrowIfNull(content); + + return content + .EnumerateAncestorsOrSelfInternal( + variationContextAccessor, + publishedCache, + navigationQueryService, + publishStatusQueryService, + true, + contentTypeAlias) + .FirstOrDefault() ?? content; + } /// /// Gets the content or its nearest ancestor, of a specified content type. @@ -826,18 +1331,38 @@ public static class PublishedContentExtensions /// The content type. /// The content or its nearest (in down-top order) ancestor, of the specified content type. /// May or may not return the content itself depending on its content type. May return null. + [Obsolete("Use the overload with IVariationContextAccessor and IPublishStatusQueryService, scheduled for removal in v17")] public static IPublishedContent AncestorOrSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, - string contentTypeAlias) - { - ArgumentNullException.ThrowIfNull(content); + string contentTypeAlias) => AncestorOrSelf( + content, + StaticServiceProvider.Instance.GetRequiredService(), + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + contentTypeAlias); - return content - .EnumerateAncestorsOrSelfInternal(publishedCache, navigationQueryService, true, contentTypeAlias) - .FirstOrDefault() ?? content; - } + /// + /// Gets the content or its nearest ancestor, of a specified content type. + /// + /// The content type. + /// The content. + /// + /// The content cache. + /// The query service for the in-memory navigation structure. + /// + /// The content or its nearest (in down-top order) ancestor, of the specified content type. + /// May or may not return the content itself depending on its content type. May return null. + public static T? AncestorOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService) + where T : class, IPublishedContent => + content.AncestorsOrSelf(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService).FirstOrDefault(); /// /// Gets the content or its nearest ancestor, of a specified content type. @@ -848,12 +1373,46 @@ public static class PublishedContentExtensions /// The query service for the in-memory navigation structure. /// The content or its nearest (in down-top order) ancestor, of the specified content type. /// May or may not return the content itself depending on its content type. May return null. + [Obsolete("Use the overload with IVariationContextAccessor and IPublishStatusQueryService, scheduled for removal in v17")] public static T? AncestorOrSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService) where T : class, IPublishedContent => - content.AncestorsOrSelf(publishedCache, navigationQueryService).FirstOrDefault(); + AncestorOrSelf( + content, + StaticServiceProvider.Instance.GetRequiredService(), + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService()); + + /// + /// Gets the content or its nearest ancestor, at a lever lesser or equal to a specified level, and of a specified + /// content type. + /// + /// The content type. + /// The content. + /// + /// The content cache. + /// The query service for the in-memory navigation structure. + /// + /// The level. + /// + public static T? AncestorOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + int maxLevel) + where T : class, IPublishedContent => + content.AncestorsOrSelf( + variationContextAccessor, + publishedCache, + navigationQueryService, + publishStatusQueryService, + maxLevel) + .FirstOrDefault(); /// /// Gets the content or its nearest ancestor, at a lever lesser or equal to a specified level, and of a specified @@ -865,42 +1424,76 @@ public static class PublishedContentExtensions /// The query service for the in-memory navigation structure. /// The level. /// + [Obsolete("Use the overload with IVariationContextAccessor and IPublishStatusQueryService, scheduled for removal in v17")] public static T? AncestorOrSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int maxLevel) where T : class, IPublishedContent => - content.AncestorsOrSelf(publishedCache, navigationQueryService, maxLevel).FirstOrDefault(); + AncestorOrSelf( + content, + StaticServiceProvider.Instance.GetRequiredService(), + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + maxLevel); + public static IEnumerable AncestorsOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + bool orSelf, + Func? func) + { + IEnumerable ancestorsOrSelf = content.EnumerateAncestors( + variationContextAccessor, + publishedCache, + navigationQueryService, + publishStatusQueryService, + orSelf); + return func == null ? ancestorsOrSelf : ancestorsOrSelf.Where(func); + } + + [Obsolete("Use the overload with IVariationContextAccessor and IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable AncestorsOrSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, bool orSelf, - Func? func) - { - IEnumerable ancestorsOrSelf = content.EnumerateAncestors(publishedCache, navigationQueryService, orSelf); - return func == null ? ancestorsOrSelf : ancestorsOrSelf.Where(func); - } + Func? func) => + AncestorsOrSelf( + content, + StaticServiceProvider.Instance.GetRequiredService(), + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + orSelf, + func); /// /// Enumerates ancestors of the content, bottom-up. /// /// The content. + /// The content. /// The content cache. /// The query service for the in-memory navigation structure. + /// /// Indicates whether the content should be included. /// Enumerates bottom-up ie walking up the tree (parent, grand-parent, etc). internal static IEnumerable EnumerateAncestors( this IPublishedContent? content, + IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, bool orSelf) { ArgumentNullException.ThrowIfNull(content); - return content.EnumerateAncestorsOrSelfInternal(publishedCache, navigationQueryService, orSelf); + return content.EnumerateAncestorsOrSelfInternal(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, orSelf); } #endregion @@ -990,6 +1583,7 @@ public static class PublishedContentExtensions /// /// Variation context accessor. /// + /// /// /// /// The specific culture to filter for. If null is used the current culture is used. (Default is @@ -1005,9 +1599,69 @@ public static class PublishedContentExtensions IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, string docTypeAlias, string? culture = null) => parentNodes.SelectMany(x => - x.DescendantsOrSelfOfType(variationContextAccessor, publishedCache, navigationQueryService, docTypeAlias, culture)); + x.DescendantsOrSelfOfType(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, docTypeAlias, culture)); + + /// + /// Returns all DescendantsOrSelf of all content referenced + /// + /// + /// Variation context accessor. + /// + /// + /// + /// The specific culture to filter for. If null is used the current culture is used. (Default is + /// null) + /// + /// + /// + /// + /// This can be useful in order to return all nodes in an entire site by a type when combined with TypedContentAtRoot + /// + [Obsolete("Use the overload with IPublishStatusQueryService instead, scheduled for removal in v17")] + public static IEnumerable DescendantsOrSelfOfType( + this IEnumerable parentNodes, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + string docTypeAlias, + string? culture = null) => + DescendantsOrSelfOfType( + parentNodes, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + docTypeAlias, + culture); + + /// + /// Returns all DescendantsOrSelf of all content referenced + /// + /// + /// Variation context accessor. + /// + /// + /// + /// The specific culture to filter for. If null is used the current culture is used. (Default is + /// null) + /// + /// + /// + /// + /// This can be useful in order to return all nodes in an entire site by a type when combined with TypedContentAtRoot + /// + public static IEnumerable DescendantsOrSelf( + this IEnumerable parentNodes, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + string? culture = null) + where T : class, IPublishedContent => + parentNodes.SelectMany(x => x.DescendantsOrSelf(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, culture)); /// /// Returns all DescendantsOrSelf of all content referenced @@ -1024,6 +1678,7 @@ public static class PublishedContentExtensions /// /// This can be useful in order to return all nodes in an entire site by a type when combined with TypedContentAtRoot /// + [Obsolete("Use the overload with IPublishStatusQueryService instead, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IEnumerable parentNodes, IVariationContextAccessor variationContextAccessor, @@ -1031,7 +1686,13 @@ public static class PublishedContentExtensions INavigationQueryService navigationQueryService, string? culture = null) where T : class, IPublishedContent => - parentNodes.SelectMany(x => x.DescendantsOrSelf(variationContextAccessor, publishedCache, navigationQueryService, culture)); + DescendantsOrSelf( + parentNodes, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + culture); // as per XPath 1.0 specs �2.2, // - the descendant axis contains the descendants of the context node; a descendant is a child or a child of a child and so on; thus @@ -1056,9 +1717,43 @@ public static class PublishedContentExtensions IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, string? culture = null) => - content.DescendantsOrSelf(variationContextAccessor, publishedCache, navigationQueryService, false, null, culture); + content.DescendantsOrSelf(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, false, null, culture); + [Obsolete("Use the overload with IPublishStatusQuery instead, scheduled for removal in v17")] + public static IEnumerable Descendants( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + string? culture = null) => + Descendants( + content, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + culture); + + public static IEnumerable Descendants( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + int level, + string? culture = null) => + content.DescendantsOrSelf( + variationContextAccessor, + publishedCache, + navigationQueryService, + publishStatusQueryService, + false, + p => p.Level >= level, + culture); + + [Obsolete("Use the overload with IPublishStatusQuery instead, scheduled for removal in v17")] public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, @@ -1066,8 +1761,33 @@ public static class PublishedContentExtensions INavigationQueryService navigationQueryService, int level, string? culture = null) => - content.DescendantsOrSelf(variationContextAccessor, publishedCache, navigationQueryService, false, p => p.Level >= level, culture); + Descendants( + content, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + level, + culture); + public static IEnumerable DescendantsOfType( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + string contentTypeAlias, + string? culture = null) => + content.EnumerateDescendantsOrSelfInternal( + variationContextAccessor, + publishedCache, + navigationQueryService, + publishStatusQueryService, + culture, + false, + contentTypeAlias); + + [Obsolete("Use the overload with IPublishStatusQuery instead, scheduled for removal in v17")] public static IEnumerable DescendantsOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, @@ -1075,14 +1795,26 @@ public static class PublishedContentExtensions INavigationQueryService navigationQueryService, string contentTypeAlias, string? culture = null) => - content.EnumerateDescendantsOrSelfInternal( + DescendantsOfType( + content, variationContextAccessor, publishedCache, navigationQueryService, - culture, - false, - contentTypeAlias); + StaticServiceProvider.Instance.GetRequiredService(), + contentTypeAlias, + culture); + public static IEnumerable Descendants( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + string? culture = null) + where T : class, IPublishedContent => + content.Descendants(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, culture).OfType(); + + [Obsolete("Use the overload with IPublishStatusQuery instead, scheduled for removal in v17")] public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, @@ -1090,13 +1822,20 @@ public static class PublishedContentExtensions INavigationQueryService navigationQueryService, string? culture = null) where T : class, IPublishedContent => - content.EnumerateDescendantsOrSelfInternal( - variationContextAccessor, - publishedCache, - navigationQueryService, - culture, - false); + content.Descendants(variationContextAccessor, publishedCache, navigationQueryService, culture).OfType(); + public static IEnumerable Descendants( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + int level, + string? culture = null) + where T : class, IPublishedContent => + content.Descendants(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, level, culture).OfType(); + + [Obsolete("Use the overload with IPublishStatusQuery instead, scheduled for removal in v17")] public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, @@ -1104,18 +1843,51 @@ public static class PublishedContentExtensions INavigationQueryService navigationQueryService, int level, string? culture = null) - where T : class, IPublishedContent => content - .EnumerateDescendantsOrSelfInternal(variationContextAccessor, publishedCache, navigationQueryService, culture, false) - .Where(p => p.Level >= level); + where T : class, IPublishedContent => + Descendants( + content, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + level, + culture); public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, string? culture = null) => - content.DescendantsOrSelf(variationContextAccessor, publishedCache, navigationQueryService, true, null, culture); + content.DescendantsOrSelf(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, true, null, culture); + [Obsolete("Use the overload with IPublishStatusQuery instead, scheduled for removal in v17")] + public static IEnumerable DescendantsOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + string? culture = null) => + DescendantsOrSelf( + content, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + culture); + + public static IEnumerable DescendantsOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + int level, + string? culture = null) => + content.DescendantsOrSelf(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, true, p => p.Level >= level, culture); + + [Obsolete("Use the overload with IPublishStatusQuery instead, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, @@ -1123,8 +1895,33 @@ public static class PublishedContentExtensions INavigationQueryService navigationQueryService, int level, string? culture = null) => - content.DescendantsOrSelf(variationContextAccessor, publishedCache, navigationQueryService, true, p => p.Level >= level, culture); + DescendantsOrSelf( + content, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + level, + culture); + public static IEnumerable DescendantsOrSelfOfType( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + string contentTypeAlias, + string? culture = null) => + content.EnumerateDescendantsOrSelfInternal( + variationContextAccessor, + publishedCache, + navigationQueryService, + publishStatusQueryService, + culture, + true, + contentTypeAlias); + + [Obsolete("Use the overload with IPublishStatusQuery instead, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelfOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, @@ -1132,14 +1929,26 @@ public static class PublishedContentExtensions INavigationQueryService navigationQueryService, string contentTypeAlias, string? culture = null) => - content.EnumerateDescendantsOrSelfInternal( + DescendantsOrSelfOfType( + content, variationContextAccessor, publishedCache, navigationQueryService, - culture, - true, - contentTypeAlias); + StaticServiceProvider.Instance.GetRequiredService(), + contentTypeAlias, + culture); + public static IEnumerable DescendantsOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + string? culture = null) + where T : class, IPublishedContent => + content.DescendantsOrSelf(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, culture).OfType(); + + [Obsolete("Use the overload with IPublishStatusQuery instead, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, @@ -1147,13 +1956,25 @@ public static class PublishedContentExtensions INavigationQueryService navigationQueryService, string? culture = null) where T : class, IPublishedContent => - content.EnumerateDescendantsOrSelfInternal( - variationContextAccessor, - publishedCache, - navigationQueryService, - culture, - true); + content.DescendantsOrSelf( + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + culture); + public static IEnumerable DescendantsOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + int level, + string? culture = null) + where T : class, IPublishedContent => + content.DescendantsOrSelf(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, level, culture).OfType(); + + [Obsolete("Use the overload with IPublishStatusQuery instead, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, @@ -1161,43 +1982,119 @@ public static class PublishedContentExtensions INavigationQueryService navigationQueryService, int level, string? culture = null) - where T : class, IPublishedContent => content - .EnumerateDescendantsOrSelfInternal(variationContextAccessor, publishedCache, navigationQueryService, culture, true) - .Where(p => p.Level >= level); + where T : class, IPublishedContent => + DescendantsOrSelf( + content, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + level, + culture); + public static IPublishedContent? Descendant( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + string? culture = null) => + content.Children( + variationContextAccessor, + publishedCache, + navigationQueryService, + publishStatusQueryService, + culture)?.FirstOrDefault(); + + [Obsolete("Use the overload with IPublishStatusQuery instead, scheduled for removal in v17")] public static IPublishedContent? Descendant( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string? culture = null) => - content.Children(variationContextAccessor, publishedCache, navigationQueryService, culture)?.FirstOrDefault(); + Descendant( + content, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + culture); public static IPublishedContent? Descendant( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, int level, string? culture = null) => content - .EnumerateDescendants(variationContextAccessor, publishedCache, navigationQueryService, false, culture).FirstOrDefault(x => x.Level == level); + .EnumerateDescendants(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, false, culture).FirstOrDefault(x => x.Level == level); + + [Obsolete("Use the overload with IPublishStatusQuery instead, scheduled for removal in v17")] + public static IPublishedContent? Descendant( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + int level, + string? culture = null) => + content + .EnumerateDescendants( + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + false, + culture) + .FirstOrDefault(x => x.Level == level); public static IPublishedContent? DescendantOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias, string? culture = null) => content - .EnumerateDescendantsOrSelfInternal( + .EnumerateDescendantsOrSelfInternal( + variationContextAccessor, + publishedCache, + navigationQueryService, + publishStatusQueryService, + culture, + false, + contentTypeAlias) + .FirstOrDefault(); + + [Obsolete("Use the overload with IPublishStatusQuery instead, scheduled for removal in v17")] + public static IPublishedContent? DescendantOfType( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + string contentTypeAlias, + string? culture = null) => + DescendantOfType( + content, variationContextAccessor, publishedCache, navigationQueryService, - culture, - false, - contentTypeAlias) - .FirstOrDefault(); + StaticServiceProvider.Instance.GetRequiredService(), + contentTypeAlias, + culture); + public static T? Descendant( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + string? culture = null) + where T : class, IPublishedContent => + content.EnumerateDescendants(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, false, culture).FirstOrDefault(x => x is T) as T; + + [Obsolete("Use the overload with IPublishStatusQuery instead, scheduled for removal in v17")] public static T? Descendant( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, @@ -1205,8 +2102,26 @@ public static class PublishedContentExtensions INavigationQueryService navigationQueryService, string? culture = null) where T : class, IPublishedContent => - content.EnumerateDescendants(variationContextAccessor, publishedCache, navigationQueryService, false, culture).FirstOrDefault(x => x is T) as T; + Descendant( + content, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + culture); + public static T? Descendant( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + int level, + string? culture = null) + where T : class, IPublishedContent => + content.Descendant(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, level, culture) as T; + + [Obsolete("Use the overload with IPublishStatusQuery instead, scheduled for removal in v17")] public static T? Descendant( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, @@ -1215,35 +2130,121 @@ public static class PublishedContentExtensions int level, string? culture = null) where T : class, IPublishedContent => - content.Descendant(variationContextAccessor, publishedCache, navigationQueryService, level, culture) as T; + Descendant( + content, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + level, + culture); - public static IPublishedContent DescendantOrSelf(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null) => content; + public static IPublishedContent DescendantOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, + string? culture = null) => + content.EnumerateDescendants( + variationContextAccessor, + GetPublishedCache(content), + GetNavigationQueryService(content), + publishStatusQueryService, + true, + culture) + .FirstOrDefault() ?? + content; + + [Obsolete("Use the overload with IPublishStatusQuery instead, scheduled for removal in v17")] + public static IPublishedContent DescendantOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + string? culture = null) => + DescendantOrSelf( + content, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + culture); public static IPublishedContent? DescendantOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, int level, string? culture = null) => content - .EnumerateDescendants(variationContextAccessor, publishedCache, navigationQueryService, true, culture).FirstOrDefault(x => x.Level == level); + .EnumerateDescendants( + variationContextAccessor, + publishedCache, + navigationQueryService, + publishStatusQueryService, + true, + culture) + .FirstOrDefault(x => x.Level == level); + + [Obsolete("Use the overload with IPublishStatusQuery instead, scheduled for removal in v17")] + public static IPublishedContent? DescendantOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + int level, + string? culture = null) => + DescendantOrSelf( + content, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + level, + culture); public static IPublishedContent? DescendantOrSelfOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias, string? culture = null) => content - .EnumerateDescendantsOrSelfInternal( + .EnumerateDescendantsOrSelfInternal( variationContextAccessor, publishedCache, navigationQueryService, + publishStatusQueryService, culture, true, contentTypeAlias) .FirstOrDefault(); + [Obsolete("Use the overload with IPublishStatusQuery instead, scheduled for removal in v17")] + public static IPublishedContent? DescendantOrSelfOfType( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + string contentTypeAlias, + string? culture = null) => + DescendantOrSelfOfType( + content, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + contentTypeAlias, + culture); + + public static T? DescendantOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + string? culture = null) + where T : class, IPublishedContent => + content.EnumerateDescendants(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, true, culture).FirstOrDefault(x => x is T) as T; + + [Obsolete("Use the overload with IPublishStatusQuery instead, scheduled for removal in v17")] public static T? DescendantOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, @@ -1251,8 +2252,26 @@ public static class PublishedContentExtensions INavigationQueryService navigationQueryService, string? culture = null) where T : class, IPublishedContent => - content.EnumerateDescendants(variationContextAccessor, publishedCache, navigationQueryService, true, culture).FirstOrDefault(x => x is T) as T; + DescendantOrSelf( + content, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + culture); + public static T? DescendantOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + int level, + string? culture = null) + where T : class, IPublishedContent => + content.DescendantOrSelf(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, level, culture) as T; + + [Obsolete("Use the overload with IPublishStatusQuery instead, scheduled for removal in v17")] public static T? DescendantOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, @@ -1261,17 +2280,25 @@ public static class PublishedContentExtensions int level, string? culture = null) where T : class, IPublishedContent => - content.DescendantOrSelf(variationContextAccessor, publishedCache, navigationQueryService, level, culture) as T; + DescendantOrSelf( + content, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + level, + culture); internal static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, bool orSelf, Func? func, string? culture = null) => - content.EnumerateDescendants(variationContextAccessor, publishedCache, navigationQueryService, orSelf, culture) + content.EnumerateDescendants(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, orSelf, culture) .Where(x => func == null || func(x)); internal static IEnumerable EnumerateDescendants( @@ -1279,23 +2306,92 @@ public static class PublishedContentExtensions IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, bool orSelf, string? culture = null) { ArgumentNullException.ThrowIfNull(content); - return content.EnumerateDescendantsOrSelfInternal( - variationContextAccessor, - publishedCache, - navigationQueryService, - culture, - orSelf); + foreach (IPublishedContent desc in content.EnumerateDescendantsOrSelfInternal( + variationContextAccessor, + publishedCache, + navigationQueryService, + publishStatusQueryService, + culture, + orSelf)) + { + yield return desc; + } + } + + internal static IEnumerable EnumerateDescendants( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + string? culture = null) + { + yield return content; + + foreach (IPublishedContent desc in content.EnumerateDescendantsOrSelfInternal( + variationContextAccessor, + publishedCache, + navigationQueryService, + publishStatusQueryService, + culture, + false)) + { + yield return desc; + } } #endregion #region Axes: children + /// + /// Gets the children of the content item. + /// + /// The content item. + /// + /// + /// + /// + /// The specific culture to get the URL children for. Default is null which will use the current culture in + /// + /// + /// + /// + /// Gets children that are available for the specified culture. + /// Children are sorted by their sortOrder. + /// + /// For culture, + /// if null is used the current culture is used. + /// If an empty string is used only invariant children are returned. + /// If "*" is used all children are returned. + /// + /// + /// If a variant culture is specified or there is a current culture in the then the + /// Children returned + /// will include both the variant children matching the culture AND the invariant children because the invariant + /// children flow with the current culture. + /// However, if an empty string is specified only invariant children are returned. + /// + /// + public static IEnumerable Children( + this IPublishedContent content, + IVariationContextAccessor? variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + string? culture = null) + { + IEnumerable children = GetChildren(navigationQueryService, publishedCache, content.Key, publishStatusQueryService, variationContextAccessor, null, culture); + + return children.FilterByCulture(culture, variationContextAccessor); + } + /// /// Gets the children of the content item. /// @@ -1324,13 +2420,44 @@ public static class PublishedContentExtensions /// However, if an empty string is specified only invariant children are returned. /// /// + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable Children( this IPublishedContent content, IVariationContextAccessor? variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, + string? culture = null) + { + IPublishStatusQueryService publishStatusQueryService = StaticServiceProvider.Instance.GetRequiredService(); + return Children(content, variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, culture); + } + + /// + /// Gets the children of the content, filtered by a predicate. + /// + /// The content. + /// The accessor for VariationContext + /// + /// + /// The predicate. + /// + /// The specific culture to filter for. If null is used the current culture is used. (Default is + /// null) + /// + /// + /// The children of the content, filtered by the predicate. + /// + /// Children are sorted by their sortOrder. + /// + public static IEnumerable Children( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + Func predicate, string? culture = null) => - GetChildren(navigationQueryService, publishedCache, content.Key).FilterByCulture(culture, variationContextAccessor); + content.Children(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, culture).Where(predicate); /// /// Gets the children of the content, filtered by a predicate. @@ -1348,6 +2475,7 @@ public static class PublishedContentExtensions /// /// Children are sorted by their sortOrder. /// + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable Children( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, @@ -1370,6 +2498,7 @@ public static class PublishedContentExtensions /// /// The content type alias. /// The children of the content, of any of the specified types. + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable ChildrenOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, @@ -1377,14 +2506,68 @@ public static class PublishedContentExtensions INavigationQueryService navigationQueryService, string? contentTypeAlias, string? culture = null) + { + IPublishStatusQueryService publishStatusQueryService = StaticServiceProvider.Instance.GetRequiredService(); + return ChildrenOfType(content, variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, contentTypeAlias, culture); + } + + /// + /// Gets the children of the content, of any of the specified types. + /// + /// The content. + /// + /// + /// + /// The accessor for the VariationContext + /// + /// The specific culture to filter for. If null is used the current culture is used. (Default is + /// null) + /// + /// The content type alias. + /// The children of the content, of any of the specified types. + public static IEnumerable ChildrenOfType( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + string? contentTypeAlias, + string? culture = null) { IEnumerable children = contentTypeAlias is not null - ? GetChildren(navigationQueryService, publishedCache, content.Key, contentTypeAlias) + ? GetChildren(navigationQueryService, publishedCache, content.Key, publishStatusQueryService, variationContextAccessor, contentTypeAlias, culture) : []; return children.FilterByCulture(culture, variationContextAccessor); } + /// + /// Gets the children of the content, of a given content type. + /// + /// The content type. + /// The content. + /// The accessor for the VariationContext + /// + /// + /// + /// The specific culture to filter for. If null is used the current culture is used. (Default is + /// null) + /// + /// + /// The children of content, of the given content type. + /// + /// Children are sorted by their sortOrder. + /// + public static IEnumerable Children( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + string? culture = null) + where T : class, IPublishedContent => + content.Children(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, culture).OfType(); + /// /// Gets the children of the content, of a given content type. /// @@ -1401,6 +2584,7 @@ public static class PublishedContentExtensions /// /// Children are sorted by their sortOrder. /// + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable Children( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, @@ -1408,15 +2592,25 @@ public static class PublishedContentExtensions INavigationQueryService navigationQueryService, string? culture = null) where T : class, IPublishedContent => - GetChildren(navigationQueryService, publishedCache, content.Key).FilterByCulture(culture, variationContextAccessor); + content.Children(variationContextAccessor, publishedCache, navigationQueryService, culture).OfType(); public static IPublishedContent? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, string? culture = null) => - content.Children(variationContextAccessor, publishedCache, navigationQueryService, culture)?.FirstOrDefault(); + content.Children(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, culture)?.FirstOrDefault(); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static IPublishedContent? FirstChild( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + string? culture = null) => + FirstChild(content, variationContextAccessor, publishedCache, navigationQueryService, StaticServiceProvider.Instance.GetRequiredService(), culture); /// /// Gets the first child of the content, of a given content type. @@ -1426,29 +2620,97 @@ public static class PublishedContentExtensions IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias, string? culture = null) => content - .ChildrenOfType(variationContextAccessor, publishedCache, navigationQueryService, contentTypeAlias, culture) + .ChildrenOfType(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, contentTypeAlias, culture) .FirstOrDefault(); + /// + /// Gets the first child of the content, of a given content type. + /// + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static IPublishedContent? FirstChildOfType( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + string contentTypeAlias, + string? culture = null) => + FirstChildOfType( + content, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + contentTypeAlias, + culture); + + public static IPublishedContent? FirstChild( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + Func predicate, + string? culture = null) + => content.Children(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, predicate, culture)?.FirstOrDefault(); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static IPublishedContent? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, Func predicate, - string? culture = null) - => content.Children(variationContextAccessor, publishedCache, navigationQueryService, predicate, culture)?.FirstOrDefault(); + string? culture = null) => + FirstChild( + content, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + predicate, + culture); public static IPublishedContent? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, Guid uniqueId, string? culture = null) => content - .Children(variationContextAccessor, publishedCache, navigationQueryService, x => x.Key == uniqueId, culture)?.FirstOrDefault(); + .Children(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, x => x.Key == uniqueId, culture)?.FirstOrDefault(); + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static IPublishedContent? FirstChild( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + Guid uniqueId, + string? culture = null) => + FirstChild( + content, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + uniqueId, + culture); + + public static T? FirstChild( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + string? culture = null) + where T : class, IPublishedContent => + content.Children(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, culture)?.FirstOrDefault(); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static T? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, @@ -1456,8 +2718,20 @@ public static class PublishedContentExtensions INavigationQueryService navigationQueryService, string? culture = null) where T : class, IPublishedContent => - content.Children(variationContextAccessor, publishedCache, navigationQueryService, culture)?.FirstOrDefault(); + FirstChild(content, variationContextAccessor, publishedCache, navigationQueryService, StaticServiceProvider.Instance.GetRequiredService(), culture); + public static T? FirstChild( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + Func predicate, + string? culture = null) + where T : class, IPublishedContent => + content.Children(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, culture)?.FirstOrDefault(predicate); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static T? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, @@ -1466,12 +2740,45 @@ public static class PublishedContentExtensions Func predicate, string? culture = null) where T : class, IPublishedContent => - content.Children(variationContextAccessor, publishedCache, navigationQueryService, culture)?.FirstOrDefault(predicate); + FirstChild( + content, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + predicate, + culture); #endregion #region Axes: siblings + /// + /// Gets the siblings of the content. + /// + /// The content. + /// The navigation service + /// Variation context accessor. + /// + /// + /// The specific culture to filter for. If null is used the current culture is used. (Default is + /// null) + /// + /// The content cache instance. + /// The siblings of the content. + /// + /// Note that in V7 this method also return the content node self. + /// + public static IEnumerable Siblings( + this IPublishedContent content, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, + string? culture = null) => + SiblingsAndSelf(content, publishedCache, navigationQueryService, variationContextAccessor, publishStatusQueryService, culture) + ?.Where(x => x.Id != content.Id) ?? Enumerable.Empty(); + /// /// Gets the siblings of the content. /// @@ -1487,14 +2794,48 @@ public static class PublishedContentExtensions /// /// Note that in V7 this method also return the content node self. /// + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable Siblings( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IVariationContextAccessor variationContextAccessor, string? culture = null) => - SiblingsAndSelf(content, publishedCache, navigationQueryService, variationContextAccessor, culture) - ?.Where(x => x.Id != content.Id) ?? Enumerable.Empty(); + Siblings( + content, + publishedCache, + navigationQueryService, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + culture); + + /// + /// Gets the siblings of the content, of a given content type. + /// + /// The content. + /// Variation context accessor. + /// + /// The specific culture to filter for. If null is used the current culture is used. (Default is + /// null) + /// + /// + /// + /// + /// The content type alias. + /// The siblings of the content, of the given content type. + /// + /// Note that in V7 this method also return the content node self. + /// + public static IEnumerable SiblingsOfType( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + string contentTypeAlias, + string? culture = null) => + SiblingsAndSelfOfType(content, variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, contentTypeAlias, culture) + .Where(x => x.Id != content.Id); /// /// Gets the siblings of the content, of a given content type. @@ -1512,6 +2853,7 @@ public static class PublishedContentExtensions /// /// Note that in V7 this method also return the content node self. /// + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable SiblingsOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, @@ -1519,8 +2861,14 @@ public static class PublishedContentExtensions INavigationQueryService navigationQueryService, string contentTypeAlias, string? culture = null) => - SiblingsAndSelfOfType(content, variationContextAccessor, publishedCache, navigationQueryService, contentTypeAlias, culture) - .Where(x => x.Id != content.Id); + SiblingsOfType( + content, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + contentTypeAlias, + culture); /// /// Gets the siblings of the content, of a given content type. @@ -1530,6 +2878,7 @@ public static class PublishedContentExtensions /// Variation context accessor. /// /// + /// /// /// The specific culture to filter for. If null is used the current culture is used. (Default is /// null) @@ -1543,11 +2892,87 @@ public static class PublishedContentExtensions IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent => - SiblingsAndSelf(content, variationContextAccessor, publishedCache, navigationQueryService, culture) + SiblingsAndSelf(content, variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, culture) ?.Where(x => x.Id != content.Id) ?? Enumerable.Empty(); + /// + /// Gets the siblings of the content, of a given content type. + /// + /// The content type. + /// The content. + /// Variation context accessor. + /// + /// + /// + /// The specific culture to filter for. If null is used the current culture is used. (Default is + /// null) + /// + /// The siblings of the content, of the given content type. + /// + /// Note that in V7 this method also return the content node self. + /// + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static IEnumerable Siblings( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + string? culture = null) + where T : class, IPublishedContent => + Siblings( + content, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + culture); + + /// + /// Gets the siblings of the content including the node itself to indicate the position. + /// + /// The content. + /// Cache instance. + /// The navigation service. + /// Variation context accessor. + /// + /// + /// The specific culture to filter for. If null is used the current culture is used. (Default is + /// null) + /// + /// The siblings of the content including the node itself. + public static IEnumerable? SiblingsAndSelf( + this IPublishedContent content, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, + string? culture = null) + { + var success = navigationQueryService.TryGetParentKey(content.Key, out Guid? parentKey); + + if (success is false || parentKey is null) + { + if (navigationQueryService.TryGetRootKeys(out IEnumerable childrenKeys) is false) + { + return null; + } + + culture ??= variationContextAccessor.VariationContext?.Culture ?? string.Empty; + return childrenKeys + .Where(x => publishStatusQueryService.IsDocumentPublished(x , culture)) + .Select(publishedCache.GetById) + .WhereNotNull() + .WhereIsInvariantOrHasCulture(variationContextAccessor, culture); + } + + return navigationQueryService.TryGetChildrenKeys(parentKey.Value, out IEnumerable siblingKeys) is false + ? null + : siblingKeys.Select(publishedCache.GetById).WhereNotNull(); + } + /// /// Gets the siblings of the content including the node itself to indicate the position. /// @@ -1560,31 +2985,66 @@ public static class PublishedContentExtensions /// null) /// /// The siblings of the content including the node itself. + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable? SiblingsAndSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IVariationContextAccessor variationContextAccessor, + string? culture = null) => + SiblingsAndSelf( + content, + publishedCache, + navigationQueryService, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + culture); + + /// + /// Gets the siblings of the content including the node itself to indicate the position, of a given content type. + /// + /// The content. + /// Variation context accessor. + /// + /// The specific culture to filter for. If null is used the current culture is used. (Default is + /// null) + /// + /// + /// + /// The content type alias. + /// + /// The siblings of the content including the node itself, of the given content type. + public static IEnumerable SiblingsAndSelfOfType( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, + string contentTypeAlias, string? culture = null) { - var success = navigationQueryService.TryGetParentKey(content.Key, out Guid? parentKey); + var parentExists = navigationQueryService.TryGetParentKey(content.Key, out Guid? parentKey); - if (success is false || parentKey is null) + IPublishedContent? parent = parentKey is null + ? null + : publishedCache.GetById(parentKey.Value); + + if (parentExists && parent is not null) { - if (navigationQueryService.TryGetRootKeys(out IEnumerable childrenKeys) is false) - { - return null; - } - - return childrenKeys - .Select(publishedCache.GetById) - .WhereNotNull() - .WhereIsInvariantOrHasCulture(variationContextAccessor, culture); + return parent.ChildrenOfType(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, contentTypeAlias, culture); } - return navigationQueryService.TryGetChildrenKeys(parentKey.Value, out IEnumerable siblingKeys) is false - ? null - : siblingKeys.Select(publishedCache.GetById).WhereNotNull(); + if (navigationQueryService.TryGetRootKeysOfType(contentTypeAlias, out IEnumerable rootKeysOfType) is false) + { + return []; + } + + culture ??= variationContextAccessor.VariationContext?.Culture ?? string.Empty; + return rootKeysOfType + .Where(x => publishStatusQueryService.IsDocumentPublished(x, culture)) + .Select(publishedCache.GetById) + .WhereNotNull() + .WhereIsInvariantOrHasCulture(variationContextAccessor, culture); } /// @@ -1600,34 +3060,67 @@ public static class PublishedContentExtensions /// The content type alias. /// /// The siblings of the content including the node itself, of the given content type. + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable SiblingsAndSelfOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string contentTypeAlias, + string? culture = null) => + SiblingsAndSelfOfType( + content, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + contentTypeAlias, + culture); + + /// + /// Gets the siblings of the content including the node itself to indicate the position, of a given content type. + /// + /// The content type. + /// The content. + /// Variation context accessor. + /// + /// + /// + /// The specific culture to filter for. If null is used the current culture is used. (Default is + /// null) + /// + /// + /// The siblings of the content including the node itself, of the given content type. + public static IEnumerable SiblingsAndSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, string? culture = null) + where T : class, IPublishedContent { - var parentExists = navigationQueryService.TryGetParentKey(content.Key, out Guid? parentKey); + var parentSuccess = navigationQueryService.TryGetParentKey(content.Key, out Guid? parentKey); + IPublishedContent? parent = parentKey is null ? null : publishedCache.GetById(parentKey.Value); - IPublishedContent? parent = parentKey is null - ? null - : publishedCache.GetById(parentKey.Value); - - if (parentExists && parent is not null) + if (parentSuccess is false || parent is null) { - return parent.ChildrenOfType(variationContextAccessor, publishedCache, navigationQueryService, contentTypeAlias, culture); + var rootSuccess = navigationQueryService.TryGetRootKeys(out IEnumerable rootKeys); + if (rootSuccess is false) + { + return []; + } + + culture ??= variationContextAccessor.VariationContext?.Culture ?? string.Empty; + return rootKeys + .Where(x => publishStatusQueryService.IsDocumentPublished(x, culture)) + .Select(publishedCache.GetById) + .WhereNotNull() + .WhereIsInvariantOrHasCulture(variationContextAccessor, culture) + .OfType(); } - if (navigationQueryService.TryGetRootKeysOfType(contentTypeAlias, out IEnumerable rootKeysOfType) is false) - { - return []; - } - - return rootKeysOfType - .Select(publishedCache.GetById) - .WhereNotNull() - .WhereIsInvariantOrHasCulture(variationContextAccessor, culture); + return parent.Children(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, culture); } /// @@ -1643,49 +3136,48 @@ public static class PublishedContentExtensions /// /// /// The siblings of the content including the node itself, of the given content type. + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable SiblingsAndSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string? culture = null) - where T : class, IPublishedContent - { - var contentTypeAlias = GetContentTypeAliasForTypeOrNull(); - var parentSuccess = navigationQueryService.TryGetParentKey(content.Key, out Guid? parentKey); - - if (parentSuccess is false) - { - return []; - } - - // parent exists so content is not at root - get the children of the parent - if (parentKey.HasValue) - { - return GetChildren(navigationQueryService, publishedCache, parentKey.Value, contentTypeAlias) - .FilterByCulture(culture, variationContextAccessor); - } - - // parent does not exist but parentSuccess is true - this means that the content is at root - var rootSuccess = contentTypeAlias is null - ? navigationQueryService.TryGetRootKeys(out IEnumerable rootKeys) - : navigationQueryService.TryGetRootKeysOfType(contentTypeAlias, out rootKeys); - - if (rootSuccess is false) - { - return []; - } - - return rootKeys - .Select(key => publishedCache.GetById(key) as T) - .WhereNotNull() - .WhereIsInvariantOrHasCulture(variationContextAccessor, culture); - } + where T : class, IPublishedContent => SiblingsAndSelf( + content, + variationContextAccessor, + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService(), + culture); #endregion #region Axes: custom + /// + /// Gets the root content (ancestor or self at level 1) for the specified . + /// + /// The content. + /// + /// The content cache. + /// The query service for the in-memory navigation structure. + /// + /// + /// The root content (ancestor or self at level 1) for the specified . + /// + /// + /// This is the same as calling + /// with maxLevel + /// set to 1. + /// + public static IPublishedContent Root( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService) => content.AncestorOrSelf(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, 1); + /// /// Gets the root content (ancestor or self at level 1) for the specified . /// @@ -1700,10 +3192,44 @@ public static class PublishedContentExtensions /// with maxLevel /// set to 1. /// + [Obsolete("Use the overload with IVariationContextAccessor & IPublishStatusQueryService, scheduled for removal in v17")] public static IPublishedContent Root( this IPublishedContent content, IPublishedCache publishedCache, - INavigationQueryService navigationQueryService) => content.AncestorOrSelf(publishedCache, navigationQueryService, 1); + INavigationQueryService navigationQueryService) => Root( + content, + StaticServiceProvider.Instance.GetRequiredService(), + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService()); + + /// + /// Gets the root content (ancestor or self at level 1) for the specified if it's of the + /// specified content type . + /// + /// The content type. + /// The content. + /// + /// The content cache. + /// The query service for the in-memory navigation structure. + /// + /// + /// The root content (ancestor or self at level 1) for the specified of content type + /// . + /// + /// + /// This is the same as calling + /// with + /// maxLevel set to 1. + /// + public static T? Root( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishedCache publishedCache, + INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService) + where T : class, IPublishedContent => + content.AncestorOrSelf(variationContextAccessor, publishedCache, navigationQueryService, publishStatusQueryService, 1); /// /// Gets the root content (ancestor or self at level 1) for the specified if it's of the @@ -1722,12 +3248,18 @@ public static class PublishedContentExtensions /// with /// maxLevel set to 1. /// + [Obsolete("Use the overload with IVariationContextAccessor & PublishStatusQueryService, scheduled for removal in v17")] public static T? Root( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService) where T : class, IPublishedContent => - content.AncestorOrSelf(publishedCache, navigationQueryService, 1); + Root( + content, + StaticServiceProvider.Instance.GetRequiredService(), + publishedCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService()); #endregion @@ -2035,35 +3567,78 @@ public static class PublishedContentExtensions public static IEnumerable Children( this IPublishedContent content, IVariationContextAccessor? variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, string? culture = null) - => Children(content, variationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture); + => Children(content, variationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), publishStatusQueryService, culture); + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static IEnumerable Children( + this IPublishedContent content, + IVariationContextAccessor? variationContextAccessor, + string? culture = null) + => Children(content, variationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), StaticServiceProvider.Instance.GetRequiredService(), culture); + + public static IEnumerable Children( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, + Func predicate, + string? culture = null) => + content.Children(variationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), publishStatusQueryService, culture).Where(predicate); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable Children( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, Func predicate, string? culture = null) => - content.Children(variationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture).Where(predicate); + Children( + content, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + predicate, + culture); + public static IEnumerable ChildrenOfType( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, + string? contentTypeAlias, + string? culture = null) + { + IEnumerable children = contentTypeAlias is not null + ? GetChildren(GetNavigationQueryService(content), GetPublishedCache(content), content.Key, publishStatusQueryService, variationContextAccessor, contentTypeAlias, culture) + : []; + + return children.FilterByCulture(culture, variationContextAccessor); + } + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable ChildrenOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? contentTypeAlias, string? culture = null) { - IEnumerable children = contentTypeAlias is not null - ? GetChildren(GetNavigationQueryService(content), GetPublishedCache(content), content.Key, contentTypeAlias) - : []; - - return children.FilterByCulture(culture, variationContextAccessor); + IPublishStatusQueryService publishStatusQueryService = StaticServiceProvider.Instance.GetRequiredService(); + return ChildrenOfType(content, variationContextAccessor, publishStatusQueryService, contentTypeAlias, culture); } public static IEnumerable Children( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent => - GetChildren(GetNavigationQueryService(content), GetPublishedCache(content), content.Key).FilterByCulture(culture, variationContextAccessor); + content.Children(variationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), publishStatusQueryService, culture).OfType(); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static IEnumerable Children( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + string? culture = null) + where T : class, IPublishedContent => + Children(content, variationContextAccessor, StaticServiceProvider.Instance.GetRequiredService(), culture); public static DataTable ChildrenAsTable( this IPublishedContent content, @@ -2080,242 +3655,591 @@ public static class PublishedContentExtensions public static IEnumerable DescendantsOrSelfOfType( this IEnumerable parentNodes, IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, string docTypeAlias, - string? culture = null) => parentNodes.SelectMany(x => - x.DescendantsOrSelfOfType(variationContextAccessor, GetPublishedCache(parentNodes.First()), - GetNavigationQueryService(parentNodes.First()), docTypeAlias, culture)); + string? culture = null) => + parentNodes.SelectMany(x => x.DescendantsOrSelfOfType( + variationContextAccessor, + GetPublishedCache(parentNodes.First()), + GetNavigationQueryService(parentNodes.First()), + publishStatusQueryService, + docTypeAlias, + culture)); + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static IEnumerable DescendantsOrSelfOfType( + this IEnumerable parentNodes, + IVariationContextAccessor variationContextAccessor, + string docTypeAlias, + string? culture = null) => + DescendantsOrSelfOfType( + parentNodes, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + docTypeAlias, + culture); + public static IEnumerable DescendantsOrSelf( + this IEnumerable parentNodes, + IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, + string? culture = null) + where T : class, IPublishedContent => + parentNodes.SelectMany( + x => x.DescendantsOrSelf( + variationContextAccessor, + GetPublishedCache(parentNodes.First()), + GetNavigationQueryService(parentNodes.First()), + publishStatusQueryService, + culture)); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IEnumerable parentNodes, IVariationContextAccessor variationContextAccessor, string? culture = null) where T : class, IPublishedContent => - parentNodes.SelectMany(x => x.DescendantsOrSelf(variationContextAccessor, GetPublishedCache(parentNodes.First()), - GetNavigationQueryService(parentNodes.First()), culture)); + DescendantsOrSelf(parentNodes, variationContextAccessor, StaticServiceProvider.Instance.GetRequiredService(), culture); + public static IEnumerable Descendants( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, + string? culture = null) => + content.DescendantsOrSelf(variationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), publishStatusQueryService, false, null, culture); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static IEnumerable Descendants( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + string? culture = null) => + Descendants(content, variationContextAccessor, StaticServiceProvider.Instance.GetRequiredService(), culture); public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, + int level, string? culture = null) => - content.DescendantsOrSelf(variationContextAccessor, GetPublishedCache(content), - GetNavigationQueryService(content), false, null, culture); - + content.DescendantsOrSelf(variationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), publishStatusQueryService, false, p => p.Level >= level, culture); + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string? culture = null) => - content.DescendantsOrSelf(variationContextAccessor, GetPublishedCache(content), - GetNavigationQueryService(content), false, p => p.Level >= level, culture); + Descendants( + content, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + level, + culture); public static IEnumerable DescendantsOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, - string contentTypeAlias, - string? culture = null) => - content.EnumerateDescendantsOrSelfInternal( + IPublishStatusQueryService publishStatusQueryService, + string contentTypeAlias, string? culture = null) => + content.EnumerateDescendantsOrSelfInternal( variationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), + publishStatusQueryService, culture, false, contentTypeAlias); + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static IEnumerable DescendantsOfType( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + string contentTypeAlias, + string? culture = null) => + DescendantsOfType( + content, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + contentTypeAlias, + culture); + + public static IEnumerable Descendants( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, + string? culture = null) + where T : class, IPublishedContent => + content.Descendants(variationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), publishStatusQueryService, culture).OfType(); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null) where T : class, IPublishedContent => - content.EnumerateDescendantsOrSelfInternal( - variationContextAccessor, - GetPublishedCache(content), - GetNavigationQueryService(content), - culture, - false); + Descendants(content, variationContextAccessor, StaticServiceProvider.Instance.GetRequiredService(), culture); public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, int level, string? culture = null) - where T : class, IPublishedContent => content - .EnumerateDescendantsOrSelfInternal(variationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture, false) - .Where(p => p.Level >= level); + where T : class, IPublishedContent => + content.Descendants(variationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), publishStatusQueryService, level, culture).OfType(); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static IEnumerable Descendants( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + int level, + string? culture = null) + where T : class, IPublishedContent => + Descendants( + content, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + level, + culture); public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, string? culture = null) => - content.DescendantsOrSelf(variationContextAccessor, GetPublishedCache(content), - GetNavigationQueryService(content), true, null, culture); + content.DescendantsOrSelf(variationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), publishStatusQueryService, true, null, culture); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static IEnumerable DescendantsOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + string? culture = null) => + DescendantsOrSelf( + content, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + culture); + public static IEnumerable DescendantsOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, + int level, + string? culture = null) => + content.DescendantsOrSelf( + variationContextAccessor, + GetPublishedCache(content), + GetNavigationQueryService(content), + publishStatusQueryService, + true, + p => p.Level >= level, + culture); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string? culture = null) => - content.DescendantsOrSelf(variationContextAccessor, GetPublishedCache(content), - GetNavigationQueryService(content), true, p => p.Level >= level, culture); + DescendantsOrSelf( + content, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + level, + culture); + public static IEnumerable DescendantsOrSelfOfType( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, + string contentTypeAlias, + string? culture = null) => + content.EnumerateDescendantsOrSelfInternal( + variationContextAccessor, + GetPublishedCache(content), + GetNavigationQueryService(content), + publishStatusQueryService, + culture, + true, + contentTypeAlias); + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelfOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string? culture = null) => - content.EnumerateDescendantsOrSelfInternal( + DescendantsOrSelfOfType( + content, variationContextAccessor, - GetPublishedCache(content), - GetNavigationQueryService(content), - culture, - true, - contentTypeAlias); + StaticServiceProvider.Instance.GetRequiredService(), + contentTypeAlias, + culture); + public static IEnumerable DescendantsOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, + string? culture = null) + where T : class, IPublishedContent => + content.DescendantsOrSelf( + variationContextAccessor, + GetPublishedCache(content), + GetNavigationQueryService(content), + publishStatusQueryService, + culture).OfType(); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null) where T : class, IPublishedContent => - content.EnumerateDescendantsOrSelfInternal( + DescendantsOrSelf( + content, variationContextAccessor, - GetPublishedCache(content), - GetNavigationQueryService(content), - culture, - true); + StaticServiceProvider.Instance.GetRequiredService(), + culture); public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, int level, string? culture = null) - where T : class, IPublishedContent => content - .EnumerateDescendantsOrSelfInternal(variationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture, true) - .Where(p => p.Level >= level); + where T : class, IPublishedContent => + content.DescendantsOrSelf( + variationContextAccessor, + GetPublishedCache(content), + GetNavigationQueryService(content), + publishStatusQueryService, + level, + culture).OfType(); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static IEnumerable DescendantsOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + int level, + string? culture = null) + where T : class, IPublishedContent => + DescendantsOrSelf( + content, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + level, + culture); + public static IPublishedContent? Descendant( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, + string? culture = null) => + content.Children(variationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), publishStatusQueryService, culture)?.FirstOrDefault(); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static IPublishedContent? Descendant( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null) => - content.Children(variationContextAccessor, GetPublishedCache(content), - GetNavigationQueryService(content), culture)?.FirstOrDefault(); + Descendant( + content, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + culture); public static IPublishedContent? Descendant( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, int level, string? culture = null) => content - .EnumerateDescendants(variationContextAccessor, GetPublishedCache(content), - GetNavigationQueryService(content), false, culture).FirstOrDefault(x => x.Level == level); + .EnumerateDescendants( + variationContextAccessor, + GetPublishedCache(content), + GetNavigationQueryService(content), + publishStatusQueryService, + false, + culture).FirstOrDefault(x => x.Level == level); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static IPublishedContent? Descendant( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + int level, + string? culture = null) => + Descendant( + content, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + level, + culture); public static IPublishedContent? DescendantOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias, string? culture = null) => content - .EnumerateDescendantsOrSelfInternal( + .EnumerateDescendantsOrSelfInternal( + variationContextAccessor, + GetPublishedCache(content), + GetNavigationQueryService(content), + publishStatusQueryService, + culture, + false, + contentTypeAlias) + .FirstOrDefault(); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static IPublishedContent? DescendantOfType( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + string contentTypeAlias, + string? culture = null) => + DescendantOfType( + content, variationContextAccessor, - GetPublishedCache(content), - GetNavigationQueryService(content), - culture, - false, - contentTypeAlias) - .FirstOrDefault(); + StaticServiceProvider.Instance.GetRequiredService(), + contentTypeAlias, + culture); public static T? Descendant( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent => - content.EnumerateDescendants(variationContextAccessor, GetPublishedCache(content), - GetNavigationQueryService(content), false, culture).FirstOrDefault(x => x is T) as T; + content.EnumerateDescendants( + variationContextAccessor, + GetPublishedCache(content), + GetNavigationQueryService(content), + publishStatusQueryService, + false, + culture) + .FirstOrDefault(x => x is T) as T; + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static T? Descendant( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + string? culture = null) + where T : class, IPublishedContent => + Descendant( + content, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + culture); + public static T? Descendant( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, + int level, + string? culture = null) + where T : class, IPublishedContent => + content.Descendant( + variationContextAccessor, + GetPublishedCache(content), + GetNavigationQueryService(content), + publishStatusQueryService, + level, + culture) as T; + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static T? Descendant( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string? culture = null) where T : class, IPublishedContent => - content.Descendant(variationContextAccessor, GetPublishedCache(content), - GetNavigationQueryService(content), level, culture) as T; + Descendant( + content, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + level, + culture); public static IPublishedContent? DescendantOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, int level, string? culture = null) => content - .EnumerateDescendants(variationContextAccessor, GetPublishedCache(content), - GetNavigationQueryService(content), true, culture).FirstOrDefault(x => x.Level == level); + .EnumerateDescendants( + variationContextAccessor, + GetPublishedCache(content), + GetNavigationQueryService(content), + publishStatusQueryService, + true, + culture).FirstOrDefault(x => x.Level == level); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static IPublishedContent? DescendantOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + int level, + string? culture = null) => DescendantOrSelf(content, variationContextAccessor, StaticServiceProvider.Instance.GetRequiredService(), level, culture); public static IPublishedContent? DescendantOrSelfOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias, string? culture = null) => content - .EnumerateDescendantsOrSelfInternal( + .EnumerateDescendantsOrSelfInternal( + variationContextAccessor, + GetPublishedCache(content), + GetNavigationQueryService(content), + publishStatusQueryService, + culture, + true, + contentTypeAlias) + .FirstOrDefault(); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static IPublishedContent? DescendantOrSelfOfType( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + string contentTypeAlias, + string? culture = null) => + DescendantOrSelfOfType( + content, variationContextAccessor, - GetPublishedCache(content), - GetNavigationQueryService(content), - culture, - true, - contentTypeAlias) - .FirstOrDefault(); + StaticServiceProvider.Instance.GetRequiredService(), + contentTypeAlias, + culture); public static T? DescendantOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent => - content.EnumerateDescendants(variationContextAccessor, GetPublishedCache(content), - GetNavigationQueryService(content), true, culture).FirstOrDefault(x => x is T) as T; + content.EnumerateDescendants( + variationContextAccessor, + GetPublishedCache(content), + GetNavigationQueryService(content), + publishStatusQueryService, + true, + culture).FirstOrDefault(x => x is T) as T; + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static T? DescendantOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + string? culture = null) + where T : class, IPublishedContent => + DescendantOrSelf( + content, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + culture); + public static T? DescendantOrSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, + int level, + string? culture = null) + where T : class, IPublishedContent => + content.DescendantOrSelf(variationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), publishStatusQueryService, level, culture) as T; + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static T? DescendantOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string? culture = null) where T : class, IPublishedContent => - content.DescendantOrSelf(variationContextAccessor, GetPublishedCache(content), - GetNavigationQueryService(content), level, culture) as T; + DescendantOrSelf( + content, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + level, + culture); public static IPublishedContent? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, string? culture = null) => - content.Children(variationContextAccessor, GetPublishedCache(content), - GetNavigationQueryService(content), culture)?.FirstOrDefault(); + content.Children( + variationContextAccessor, + GetPublishedCache(content), + GetNavigationQueryService(content), + publishStatusQueryService, + culture)?.FirstOrDefault(); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static IPublishedContent? FirstChild( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + string? culture = null) => + FirstChild(content, variationContextAccessor, StaticServiceProvider.Instance.GetRequiredService(), culture); public static IPublishedContent? FirstChildOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias, string? culture = null) => - content.ChildrenOfType(variationContextAccessor, GetPublishedCache(content), - GetNavigationQueryService(content), contentTypeAlias, culture)?.FirstOrDefault(); + content.ChildrenOfType( + variationContextAccessor, + GetPublishedCache(content), + GetNavigationQueryService(content), + publishStatusQueryService, + contentTypeAlias, + culture)?.FirstOrDefault(); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static IPublishedContent? FirstChildOfType( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + string contentTypeAlias, + string? culture = null) => + FirstChildOfType( + content, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + contentTypeAlias, + culture); + public static IPublishedContent? FirstChild( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, + Func predicate, + string? culture = null) => + content.Children( + variationContextAccessor, + GetPublishedCache(content), + GetNavigationQueryService(content), + publishStatusQueryService, + predicate, + culture)?.FirstOrDefault(); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] public static IPublishedContent? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, @@ -2328,20 +4252,70 @@ public static class PublishedContentExtensions public static IPublishedContent? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, Guid uniqueId, string? culture = null) => content - .Children(variationContextAccessor, GetPublishedCache(content), - GetNavigationQueryService(content), x => x.Key == uniqueId, culture)?.FirstOrDefault(); + .Children( + variationContextAccessor, + GetPublishedCache(content), + GetNavigationQueryService(content), + publishStatusQueryService, + x => x.Key == uniqueId, + culture)?.FirstOrDefault(); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static IPublishedContent? FirstChild( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + Guid uniqueId, + string? culture = null) => + FirstChild( + content, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + uniqueId, + culture); public static T? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent => - content.Children(variationContextAccessor, GetPublishedCache(content), - GetNavigationQueryService(content), culture)?.FirstOrDefault(); + content.Children( + variationContextAccessor, + GetPublishedCache(content), + GetNavigationQueryService(content), + publishStatusQueryService, + culture)?.FirstOrDefault(); + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static T? FirstChild( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + string? culture = null) + where T : class, IPublishedContent => + FirstChild( + content, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + culture); + + + public static T? FirstChild( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, + Func predicate, + string? culture = null) + where T : class, IPublishedContent => + content.Children( + variationContextAccessor, + GetPublishedCache(content), + GetNavigationQueryService(content), + publishStatusQueryService, + culture)?.FirstOrDefault(predicate); public static T? FirstChild( this IPublishedContent content, @@ -2349,8 +4323,12 @@ public static class PublishedContentExtensions Func predicate, string? culture = null) where T : class, IPublishedContent => - content.Children(variationContextAccessor, GetPublishedCache(content), - GetNavigationQueryService(content), culture)?.FirstOrDefault(predicate); + FirstChild( + content, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + predicate, + culture); [Obsolete( "Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")] @@ -2399,9 +4377,27 @@ public static class PublishedContentExtensions public static IEnumerable SiblingsAndSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, + IPublishStatusQueryService publishStatusQueryService, string? culture = null) - where T : class, IPublishedContent => SiblingsAndSelf(content, variationContextAccessor, GetPublishedCache(content), - GetNavigationQueryService(content), culture); + where T : class, IPublishedContent => + SiblingsAndSelf( + content, + variationContextAccessor, + GetPublishedCache(content), + GetNavigationQueryService(content), + publishStatusQueryService, + culture); + + [Obsolete("Use the overload with IPublishStatusQueryService, scheduled for removal in v17")] + public static IEnumerable SiblingsAndSelf( + this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, + string? culture = null) + where T : class, IPublishedContent => SiblingsAndSelf( + content, + variationContextAccessor, + StaticServiceProvider.Instance.GetRequiredService(), + culture); private static INavigationQueryService GetNavigationQueryService(IPublishedContent content) @@ -2415,6 +4411,7 @@ public static class PublishedContentExtensions default: throw new NotSupportedException("Unsupported content type."); } + } private static IPublishedCache GetPublishedCache(IPublishedContent content) @@ -2430,15 +4427,15 @@ public static class PublishedContentExtensions } } - private static IEnumerable GetChildren( + private static IEnumerable GetChildren( INavigationQueryService navigationQueryService, IPublishedCache publishedCache, Guid parentKey, - string? contentTypeAlias = null) - where T : class, IPublishedContent + IPublishStatusQueryService publishStatusQueryService, + IVariationContextAccessor? variationContextAccessor, + string? contentTypeAlias = null, + string? culture = null) { - contentTypeAlias ??= GetContentTypeAliasForTypeOrNull(); - var nodeExists = contentTypeAlias is null ? navigationQueryService.TryGetChildrenKeys(parentKey, out IEnumerable childrenKeys) : navigationQueryService.TryGetChildrenKeysOfType(parentKey, contentTypeAlias, out childrenKeys); @@ -2447,17 +4444,22 @@ public static class PublishedContentExtensions { return []; } + // We need to filter what keys are published, as calling the GetById + // with a non-existing published node, will get cache misses and call the DB + // making it a very slow operation. + + culture ??= variationContextAccessor?.VariationContext?.Culture ?? string.Empty; return childrenKeys - .Select(key => publishedCache.GetById(key) as T) + .Where(x => publishStatusQueryService.IsDocumentPublished(x, culture)) + .Select(publishedCache.GetById) .WhereNotNull(); } - private static IEnumerable FilterByCulture( - this IEnumerable contentNodes, + private static IEnumerable FilterByCulture( + this IEnumerable contentNodes, string? culture, IVariationContextAccessor? variationContextAccessor) - where T : class, IPublishedContent { // Determine the culture if not provided culture ??= variationContextAccessor?.VariationContext?.Culture ?? string.Empty; @@ -2467,49 +4469,24 @@ public static class PublishedContentExtensions : contentNodes.Where(x => x.IsInvariantOrHasCulture(culture)); } - /// - /// Gets the content type alias from the PublishedModelAttribute of a specified type. - /// - /// The content type. - /// The content type alias, or null if the type is IPublishedContent. - private static string? GetContentTypeAliasForTypeOrNull() - where T : class, IPublishedContent - { - // IPublishedContent doesn't have PublishedModelAttribute - if (typeof(T) == typeof(IPublishedContent)) - { - return null; - } - - PublishedModelAttribute? attribute = typeof(T).GetCustomAttribute(false); - - if (attribute is null) - { - throw new InvalidOperationException($"The type {typeof(T).FullName} does not have the {nameof(PublishedModelAttribute)}, so the content type alias cannot be inferred."); - } - - return attribute.ContentTypeAlias; - } - - private static IEnumerable EnumerateDescendantsOrSelfInternal( + private static IEnumerable EnumerateDescendantsOrSelfInternal( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, string? culture, bool orSelf, string? contentTypeAlias = null) - where T : class, IPublishedContent { - contentTypeAlias ??= GetContentTypeAliasForTypeOrNull(); - - // Yield the content node itself if it matches the type and alias (if applicable) - if (orSelf && content.TryGetOfType(contentTypeAlias, out T? self)) + if (orSelf) { - yield return self; + if (contentTypeAlias is null || content.ContentType.Alias == contentTypeAlias) + { + yield return content; + } } - // Try to get the descendant keys var nodeExists = contentTypeAlias is null ? navigationQueryService.TryGetDescendantsKeys(content.Key, out IEnumerable descendantsKeys) : navigationQueryService.TryGetDescendantsKeysOfType(content.Key, contentTypeAlias, out descendantsKeys); @@ -2519,35 +4496,37 @@ public static class PublishedContentExtensions yield break; } - // Retrieve descendants from the cache - IEnumerable descendants = descendantsKeys - .Select(key => publishedCache.GetById(key) as T) + culture ??= variationContextAccessor?.VariationContext?.Culture ?? string.Empty; + IEnumerable descendants = descendantsKeys + .Where(x => publishStatusQueryService.IsDocumentPublished(x, culture)) + .Select(publishedCache.GetById) .WhereNotNull() .FilterByCulture(culture, variationContextAccessor); - foreach (T descendant in descendants) + foreach (IPublishedContent descendant in descendants) { yield return descendant; } } - private static IEnumerable EnumerateAncestorsOrSelfInternal( + private static IEnumerable EnumerateAncestorsOrSelfInternal( this IPublishedContent content, + IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService, bool orSelf, - string? contentTypeAlias = null) - where T : class, IPublishedContent + string? contentTypeAlias = null, + string? culture = null) { - contentTypeAlias ??= GetContentTypeAliasForTypeOrNull(); - - // Yield the content node itself if it matches the type and alias (if applicable) - if (orSelf && content.TryGetOfType(contentTypeAlias, out T? self)) + if (orSelf) { - yield return self; + if (contentTypeAlias is null || content.ContentType.Alias == contentTypeAlias) + { + yield return content; + } } - // Try to get the ancestors keys var nodeExists = contentTypeAlias is null ? navigationQueryService.TryGetAncestorsKeys(content.Key, out IEnumerable ancestorsKeys) : navigationQueryService.TryGetAncestorsKeysOfType(content.Key, contentTypeAlias, out ancestorsKeys); @@ -2557,36 +4536,19 @@ public static class PublishedContentExtensions yield break; } - // Retrieve ancestors from the cache + culture ??= variationContextAccessor.VariationContext?.Culture ?? string.Empty; foreach (Guid ancestorKey in ancestorsKeys) { - IPublishedContent? ancestor = publishedCache.GetById(ancestorKey); - if (ancestor is T ancestorOfTypeT) + if (publishStatusQueryService.IsDocumentPublished(ancestorKey, culture) is false) { - yield return ancestorOfTypeT; + yield break; + } + + IPublishedContent? ancestor = publishedCache.GetById(ancestorKey); + if (ancestor is not null) + { + yield return ancestor; } } } - - private static bool TryGetOfType( - this IPublishedContent content, - string? contentTypeAlias, - [NotNullWhen(true)] out T? contentOfType) - where T : class, IPublishedContent - { - contentOfType = null; - - if (content is not T typedContent) - { - return false; - } - - if (contentTypeAlias is not null && typedContent.ContentType.Alias != contentTypeAlias) - { - return false; - } - - contentOfType = typedContent; - return true; - } } diff --git a/src/Umbraco.Core/Routing/ContentFinderByUrlAlias.cs b/src/Umbraco.Core/Routing/ContentFinderByUrlAlias.cs index f592fb0a0f..39cd4c8854 100644 --- a/src/Umbraco.Core/Routing/ContentFinderByUrlAlias.cs +++ b/src/Umbraco.Core/Routing/ContentFinderByUrlAlias.cs @@ -1,4 +1,6 @@ +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.PublishedCache; using Umbraco.Cms.Core.Services.Navigation; @@ -24,6 +26,7 @@ public class ContentFinderByUrlAlias : IContentFinder private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly IPublishedContentCache _contentCache; private readonly IDocumentNavigationQueryService _documentNavigationQueryService; + private readonly IPublishStatusQueryService _publishStatusQueryService; private readonly IVariationContextAccessor _variationContextAccessor; /// @@ -35,16 +38,37 @@ public class ContentFinderByUrlAlias : IContentFinder IVariationContextAccessor variationContextAccessor, IUmbracoContextAccessor umbracoContextAccessor, IPublishedContentCache contentCache, - IDocumentNavigationQueryService documentNavigationQueryService) + IDocumentNavigationQueryService documentNavigationQueryService, + IPublishStatusQueryService publishStatusQueryService) { _publishedValueFallback = publishedValueFallback; _variationContextAccessor = variationContextAccessor; _umbracoContextAccessor = umbracoContextAccessor; _contentCache = contentCache; _documentNavigationQueryService = documentNavigationQueryService; + _publishStatusQueryService = publishStatusQueryService; _logger = logger; } + [Obsolete("Please use constructor that takes an IPublishStatusQueryService instead. Scheduled removal in v17")] + public ContentFinderByUrlAlias( + ILogger logger, + IPublishedValueFallback publishedValueFallback, + IVariationContextAccessor variationContextAccessor, + IUmbracoContextAccessor umbracoContextAccessor, + IPublishedContentCache contentCache, + IDocumentNavigationQueryService documentNavigationQueryService) + : this( + logger, + publishedValueFallback, + variationContextAccessor, + umbracoContextAccessor, + contentCache, + documentNavigationQueryService, + StaticServiceProvider.Instance.GetRequiredService()) + { + } + /// /// Tries to find and assign an Umbraco document to a PublishedRequest. /// @@ -145,14 +169,14 @@ public class ContentFinderByUrlAlias : IContentFinder if (rootNodeId > 0) { IPublishedContent? rootNode = cache?.GetById(rootNodeId); - return rootNode?.Descendants(_variationContextAccessor, _contentCache, _documentNavigationQueryService).FirstOrDefault(x => IsMatch(x, test1, test2)); + return rootNode?.Descendants(_variationContextAccessor, _contentCache, _documentNavigationQueryService, _publishStatusQueryService).FirstOrDefault(x => IsMatch(x, test1, test2)); } if (cache is not null) { foreach (IPublishedContent rootContent in cache.GetAtRoot()) { - IPublishedContent? c = rootContent.DescendantsOrSelf(_variationContextAccessor, _contentCache, _documentNavigationQueryService) + IPublishedContent? c = rootContent.DescendantsOrSelf(_variationContextAccessor, _contentCache, _documentNavigationQueryService, _publishStatusQueryService) .FirstOrDefault(x => IsMatch(x, test1, test2)); if (c != null) { diff --git a/src/Umbraco.Core/Routing/UrlProvider.cs b/src/Umbraco.Core/Routing/UrlProvider.cs index f40c240a73..f034fbf8b9 100644 --- a/src/Umbraco.Core/Routing/UrlProvider.cs +++ b/src/Umbraco.Core/Routing/UrlProvider.cs @@ -27,6 +27,28 @@ namespace Umbraco.Cms.Core.Routing /// The current variation accessor. /// The content cache. /// The query service for the in-memory navigation structure. + /// The publish status query service, to query if a given content is published in a given culture. + public UrlProvider( + IUmbracoContextAccessor umbracoContextAccessor, + IOptions routingSettings, + UrlProviderCollection urlProviders, + MediaUrlProviderCollection mediaUrlProviders, + IVariationContextAccessor variationContextAccessor, + IPublishedContentCache contentCache, + IDocumentNavigationQueryService navigationQueryService, + IPublishStatusQueryService publishStatusQueryService) + { + _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); + _urlProviders = urlProviders; + _mediaUrlProviders = mediaUrlProviders; + _variationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor)); + _contentCache = contentCache; + _navigationQueryService = navigationQueryService; + _publishStatusQueryService = publishStatusQueryService; + Mode = routingSettings.Value.UrlProviderMode; + } + + [Obsolete("Use the constructor that takes all parameters. Scheduled for removal in V17.")] public UrlProvider( IUmbracoContextAccessor umbracoContextAccessor, IOptions routingSettings, @@ -35,14 +57,16 @@ namespace Umbraco.Cms.Core.Routing IVariationContextAccessor variationContextAccessor, IPublishedContentCache contentCache, IDocumentNavigationQueryService navigationQueryService) + : this( + umbracoContextAccessor, + routingSettings, + urlProviders, + mediaUrlProviders, + variationContextAccessor, + contentCache, + navigationQueryService, + StaticServiceProvider.Instance.GetRequiredService()) { - _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); - _urlProviders = urlProviders; - _mediaUrlProviders = mediaUrlProviders; - _variationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor)); - _contentCache = contentCache; - _navigationQueryService = navigationQueryService; - Mode = routingSettings.Value.UrlProviderMode; } [Obsolete("Use the constructor that takes all parameters. Scheduled for removal in V17.")] @@ -59,7 +83,8 @@ namespace Umbraco.Cms.Core.Routing mediaUrlProviders, variationContextAccessor, StaticServiceProvider.Instance.GetRequiredService(), - StaticServiceProvider.Instance.GetRequiredService()) + StaticServiceProvider.Instance.GetRequiredService(), + StaticServiceProvider.Instance.GetRequiredService()) { } @@ -69,6 +94,7 @@ namespace Umbraco.Cms.Core.Routing private readonly IVariationContextAccessor _variationContextAccessor; private readonly IPublishedContentCache _contentCache; private readonly IDocumentNavigationQueryService _navigationQueryService; + private readonly IPublishStatusQueryService _publishStatusQueryService; /// /// Gets or sets the provider URL mode. @@ -147,7 +173,7 @@ namespace Umbraco.Cms.Core.Routing // be nice with tests, assume things can be null, ultimately fall back to invariant // (but only for variant content of course) // We need to check all ancestors because urls are variant even for invariant content, if an ancestor is variant. - if (culture == null && content.AncestorsOrSelf(_contentCache, _navigationQueryService).Any(x => x.ContentType.VariesByCulture())) + if (culture == null && content.AncestorsOrSelf(_variationContextAccessor, _contentCache, _navigationQueryService, _publishStatusQueryService).Any(x => x.ContentType.VariesByCulture())) { culture = _variationContextAccessor?.VariationContext?.Culture ?? string.Empty; } diff --git a/src/Umbraco.Core/Services/DomainService.cs b/src/Umbraco.Core/Services/DomainService.cs index c527e40b82..58f776a45a 100644 --- a/src/Umbraco.Core/Services/DomainService.cs +++ b/src/Umbraco.Core/Services/DomainService.cs @@ -311,12 +311,17 @@ public class DomainService : RepositoryService, IDomainService var sortOrder = 0; foreach (DomainModel domainModel in updateModel.Domains) { - IDomain assignedDomain = currentlyAssignedDomains.FirstOrDefault(domain => domainModel.DomainName.InvariantEquals(domain.DomainName)) - ?? new UmbracoDomain(domainModel.DomainName) - { - LanguageId = languageIdByIsoCode[domainModel.IsoCode], - RootContentId = contentId - }; + IDomain? assignedDomain = currentlyAssignedDomains.FirstOrDefault(domain => domainModel.DomainName.InvariantEquals(domain.DomainName)); + + // If we do not have an assigned domain, or the domain-language has been changed, create new domain. + if (assignedDomain is null || assignedDomain.LanguageId != languageIdByIsoCode[domainModel.IsoCode]) + { + assignedDomain = new UmbracoDomain(domainModel.DomainName) + { + LanguageId = languageIdByIsoCode[domainModel.IsoCode], + RootContentId = contentId + }; + } assignedDomain.SortOrder = sortOrder++; newAssignedDomains.Add(assignedDomain); diff --git a/src/Umbraco.Core/Services/IPublicAccessService.cs b/src/Umbraco.Core/Services/IPublicAccessService.cs index fc919baf37..b04ab230e4 100644 --- a/src/Umbraco.Core/Services/IPublicAccessService.cs +++ b/src/Umbraco.Core/Services/IPublicAccessService.cs @@ -85,8 +85,23 @@ public interface IPublicAccessService : IService /// /// /// Returns null if no entry is found + /// + /// This method supports inheritance by considering ancestor entries (if any), + /// if no entry is found for the specified content key. + /// Task> GetEntryByContentKeyAsync(Guid key); + /// + /// Gets the entry defined for the content item based on a content key, without taking ancestor entries into account. + /// + /// + /// Returns null if no entry is found + /// + /// This method does not support inheritance. Use to include ancestor entries (if any). + /// + Task> GetEntryByContentKeyWithoutAncestorsAsync(Guid key) + => Task.FromResult(Attempt.SucceedWithStatus(PublicAccessOperationStatus.EntryNotFound, null)); + /// /// Deletes the entry and all associated rules for a given key. /// diff --git a/src/Umbraco.Core/Services/PublicAccessService.cs b/src/Umbraco.Core/Services/PublicAccessService.cs index ab9675fb09..f44ba15022 100644 --- a/src/Umbraco.Core/Services/PublicAccessService.cs +++ b/src/Umbraco.Core/Services/PublicAccessService.cs @@ -1,5 +1,7 @@ using System.Globalization; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Entities; @@ -16,7 +18,9 @@ internal class PublicAccessService : RepositoryService, IPublicAccessService private readonly IPublicAccessRepository _publicAccessRepository; private readonly IEntityService _entityService; private readonly IContentService _contentService; + private readonly IIdKeyMap _idKeyMap; + [Obsolete("Please use the constructor that accepts all parameter. Will be removed in V16.")] public PublicAccessService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -24,11 +28,31 @@ internal class PublicAccessService : RepositoryService, IPublicAccessService IPublicAccessRepository publicAccessRepository, IEntityService entityService, IContentService contentService) + : this( + provider, + loggerFactory, + eventMessagesFactory, + publicAccessRepository, + entityService, + contentService, + StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public PublicAccessService( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IPublicAccessRepository publicAccessRepository, + IEntityService entityService, + IContentService contentService, + IIdKeyMap idKeyMap) : base(provider, loggerFactory, eventMessagesFactory) { _publicAccessRepository = publicAccessRepository; _entityService = entityService; _contentService = contentService; + _idKeyMap = idKeyMap; } /// @@ -381,6 +405,23 @@ internal class PublicAccessService : RepositoryService, IPublicAccessService return Task.FromResult(Attempt.SucceedWithStatus(PublicAccessOperationStatus.Success, entry)); } + public async Task> GetEntryByContentKeyWithoutAncestorsAsync(Guid key) + { + Attempt result = await GetEntryByContentKeyAsync(key); + if (result.Success is false || result.Result is null) + { + return result; + } + + Attempt idToKeyAttempt = _idKeyMap.GetKeyForId(result.Result.ProtectedNodeId, UmbracoObjectTypes.Document); + if (idToKeyAttempt.Success is false || idToKeyAttempt.Result != key) + { + return Attempt.SucceedWithStatus(PublicAccessOperationStatus.EntryNotFound, null); + } + + return result; + } + public async Task> DeleteAsync(Guid key) { using (ICoreScope scope = ScopeProvider.CreateCoreScope()) diff --git a/src/Umbraco.Core/Services/PublishStatus/PublishStatusService.cs b/src/Umbraco.Core/Services/PublishStatus/PublishStatusService.cs index 17694873c5..c6d1f7481f 100644 --- a/src/Umbraco.Core/Services/PublishStatus/PublishStatusService.cs +++ b/src/Umbraco.Core/Services/PublishStatus/PublishStatusService.cs @@ -1,5 +1,7 @@ using System.Collections.Concurrent; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Persistence.Repositories; using Umbraco.Cms.Core.Scoping; @@ -10,15 +12,31 @@ public class PublishStatusService : IPublishStatusManagementService, IPublishSta private readonly ILogger _logger; private readonly IPublishStatusRepository _publishStatusRepository; private readonly ICoreScopeProvider _coreScopeProvider; + private readonly ILanguageService _languageService; private readonly IDictionary> _publishedCultures = new Dictionary>(); + + private string? DefaultCulture { get; set; } + + [Obsolete("Use non-obsolete constructor. This will be removed in Umbraco 17.")] public PublishStatusService( ILogger logger, IPublishStatusRepository publishStatusRepository, ICoreScopeProvider coreScopeProvider) + : this(logger, publishStatusRepository, coreScopeProvider, StaticServiceProvider.Instance.GetRequiredService()) + { + + } + + public PublishStatusService( + ILogger logger, + IPublishStatusRepository publishStatusRepository, + ICoreScopeProvider coreScopeProvider, + ILanguageService languageService) { _logger = logger; _publishStatusRepository = publishStatusRepository; _coreScopeProvider = coreScopeProvider; + _languageService = languageService; } public async Task InitializeAsync(CancellationToken cancellationToken) @@ -39,11 +57,16 @@ public class PublishStatusService : IPublishStatusManagementService, IPublishSta } } - + DefaultCulture = await _languageService.GetDefaultIsoCodeAsync(); } public bool IsDocumentPublished(Guid documentKey, string culture) { + if (string.IsNullOrEmpty(culture) && DefaultCulture is not null) + { + culture = DefaultCulture; + } + if (_publishedCultures.TryGetValue(documentKey, out ISet? publishedCultures)) { return publishedCultures.Contains(culture, StringComparer.InvariantCultureIgnoreCase); diff --git a/src/Umbraco.Web.Common/Extensions/FriendlyPublishedContentExtensions.cs b/src/Umbraco.Web.Common/Extensions/FriendlyPublishedContentExtensions.cs index 97bf4c8839..c4c839f695 100644 --- a/src/Umbraco.Web.Common/Extensions/FriendlyPublishedContentExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/FriendlyPublishedContentExtensions.cs @@ -67,6 +67,9 @@ public static class FriendlyPublishedContentExtensions private static IMemberTypeService MemberTypeService { get; } = StaticServiceProvider.Instance.GetRequiredService(); + private static IPublishStatusQueryService PublishStatusQueryService { get; } = + StaticServiceProvider.Instance.GetRequiredService(); + private static INavigationQueryService GetNavigationQueryService(IPublishedContent content) { switch (content.ContentType.ItemType) @@ -240,7 +243,7 @@ public static class FriendlyPublishedContentExtensions /// set to 1. /// public static IPublishedContent Root(this IPublishedContent content) - => content.Root(GetPublishedCache(content), GetNavigationQueryService(content)); + => content.Root(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService); /// /// Gets the root content (ancestor or self at level 1) for the specified if it's of the @@ -259,7 +262,7 @@ public static class FriendlyPublishedContentExtensions /// public static T? Root(this IPublishedContent content) where T : class, IPublishedContent - => content.Root(GetPublishedCache(content), GetNavigationQueryService(content)); + => content.Root(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService); /// /// Gets the parent of the content item. @@ -286,7 +289,7 @@ public static class FriendlyPublishedContentExtensions /// The ancestors of the content, in down-top order. /// Does not consider the content itself. public static IEnumerable Ancestors(this IPublishedContent content) - => content.Ancestors(GetPublishedCache(content), GetNavigationQueryService(content)); + => content.Ancestors(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService); /// /// Gets the content and its ancestors. @@ -294,7 +297,7 @@ public static class FriendlyPublishedContentExtensions /// The content. /// The content and its ancestors, in down-top order. public static IEnumerable AncestorsOrSelf(this IPublishedContent content) - => content.AncestorsOrSelf(GetPublishedCache(content), GetNavigationQueryService(content)); + => content.AncestorsOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService); /// /// Gets the content and its ancestors, of a specified content type. @@ -305,7 +308,7 @@ public static class FriendlyPublishedContentExtensions /// May or may not begin with the content itself, depending on its content type. public static IEnumerable AncestorsOrSelf(this IPublishedContent content) where T : class, IPublishedContent - => content.AncestorsOrSelf(GetPublishedCache(content), GetNavigationQueryService(content)); + => content.AncestorsOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService); /// /// Gets the ancestor of the content, i.e. its parent. @@ -324,7 +327,7 @@ public static class FriendlyPublishedContentExtensions /// Does not consider the content itself. May return null. public static T? Ancestor(this IPublishedContent content) where T : class, IPublishedContent - => content.Ancestor(GetPublishedCache(content), GetNavigationQueryService(content)); + => content.Ancestor(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService); /// /// Gets the content or its nearest ancestor, of a specified content type. @@ -335,7 +338,7 @@ public static class FriendlyPublishedContentExtensions /// May or may not return the content itself depending on its content type. May return null. public static T? AncestorOrSelf(this IPublishedContent content) where T : class, IPublishedContent - => content.AncestorOrSelf(GetPublishedCache(content), GetNavigationQueryService(content)); + => content.AncestorOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService); /// /// Returns all DescendantsOrSelf of all content referenced @@ -352,7 +355,7 @@ public static class FriendlyPublishedContentExtensions /// public static IEnumerable DescendantsOrSelfOfType( this IEnumerable parentNodes, string docTypeAlias, string? culture = null) - => parentNodes.DescendantsOrSelfOfType(VariationContextAccessor, GetPublishedCache(parentNodes.First()), GetNavigationQueryService(parentNodes.First()), docTypeAlias, culture); + => parentNodes.DescendantsOrSelfOfType(VariationContextAccessor, GetPublishedCache(parentNodes.First()), GetNavigationQueryService(parentNodes.First()), PublishStatusQueryService, docTypeAlias, culture); /// /// Returns all DescendantsOrSelf of all content referenced @@ -370,77 +373,77 @@ public static class FriendlyPublishedContentExtensions this IEnumerable parentNodes, string? culture = null) where T : class, IPublishedContent - => parentNodes.DescendantsOrSelf(VariationContextAccessor, GetPublishedCache(parentNodes.First()), GetNavigationQueryService(parentNodes.First()), culture); + => parentNodes.DescendantsOrSelf(VariationContextAccessor, GetPublishedCache(parentNodes.First()), GetNavigationQueryService(parentNodes.First()), PublishStatusQueryService, culture); public static IEnumerable Descendants(this IPublishedContent content, string? culture = null) - => content.Descendants(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture); + => content.Descendants(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, culture); public static IEnumerable Descendants(this IPublishedContent content, int level, string? culture = null) - => content.Descendants(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), level, culture); + => content.Descendants(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, level, culture); public static IEnumerable DescendantsOfType(this IPublishedContent content, string contentTypeAlias, string? culture = null) - => content.DescendantsOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), contentTypeAlias, culture); + => content.DescendantsOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, contentTypeAlias, culture); public static IEnumerable Descendants(this IPublishedContent content, string? culture = null) where T : class, IPublishedContent - => content.Descendants(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture); + => content.Descendants(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, culture); public static IEnumerable Descendants(this IPublishedContent content, int level, string? culture = null) where T : class, IPublishedContent - => content.Descendants(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), level, culture); + => content.Descendants(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, level, culture); public static IEnumerable DescendantsOrSelf( this IPublishedContent content, string? culture = null) - => content.DescendantsOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture); + => content.DescendantsOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, culture); public static IEnumerable DescendantsOrSelf(this IPublishedContent content, int level, string? culture = null) - => content.DescendantsOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), level, culture); + => content.DescendantsOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, level, culture); public static IEnumerable DescendantsOrSelfOfType(this IPublishedContent content, string contentTypeAlias, string? culture = null) - => content.DescendantsOrSelfOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), contentTypeAlias, culture); + => content.DescendantsOrSelfOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, contentTypeAlias, culture); public static IEnumerable DescendantsOrSelf(this IPublishedContent content, string? culture = null) where T : class, IPublishedContent - => content.DescendantsOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture); + => content.DescendantsOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, culture); public static IEnumerable DescendantsOrSelf(this IPublishedContent content, int level, string? culture = null) where T : class, IPublishedContent - => content.DescendantsOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), level, culture); + => content.DescendantsOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, level, culture); public static IPublishedContent? Descendant(this IPublishedContent content, string? culture = null) - => content.Descendant(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture); + => content.Descendant(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, culture); public static IPublishedContent? Descendant(this IPublishedContent content, int level, string? culture = null) - => content.Descendant(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), level, culture); + => content.Descendant(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, level, culture); public static IPublishedContent? DescendantOfType(this IPublishedContent content, string contentTypeAlias, string? culture = null) - => content.DescendantOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), contentTypeAlias, culture); + => content.DescendantOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, contentTypeAlias, culture); public static T? Descendant(this IPublishedContent content, string? culture = null) where T : class, IPublishedContent - => content.Descendant(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture); + => content.Descendant(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, culture); public static T? Descendant(this IPublishedContent content, int level, string? culture = null) where T : class, IPublishedContent - => content.Descendant(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), level, culture); + => content.Descendant(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, level, culture); public static IPublishedContent DescendantOrSelf(this IPublishedContent content, string? culture = null) - => content.DescendantOrSelf(VariationContextAccessor, culture); + => content.DescendantOrSelf(VariationContextAccessor, PublishStatusQueryService, culture); public static IPublishedContent? DescendantOrSelf(this IPublishedContent content, int level, string? culture = null) - => content.DescendantOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), level, culture); + => content.DescendantOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, level, culture); public static IPublishedContent? DescendantOrSelfOfType(this IPublishedContent content, string contentTypeAlias, string? culture = null) - => content.DescendantOrSelfOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), contentTypeAlias, culture); + => content.DescendantOrSelfOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, contentTypeAlias, culture); public static T? DescendantOrSelf(this IPublishedContent content, string? culture = null) where T : class, IPublishedContent - => content.DescendantOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture); + => content.DescendantOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, culture); public static T? DescendantOrSelf(this IPublishedContent content, int level, string? culture = null) where T : class, IPublishedContent - => content.DescendantOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), level, culture); + => content.DescendantOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, level, culture); /// /// Gets the children of the content item. @@ -468,7 +471,7 @@ public static class FriendlyPublishedContentExtensions /// /// public static IEnumerable Children(this IPublishedContent content, string? culture = null) - => content.Children(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture); + => content.Children(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, culture); /// /// Gets the children of the content, filtered by a predicate. @@ -487,7 +490,7 @@ public static class FriendlyPublishedContentExtensions this IPublishedContent content, Func predicate, string? culture = null) - => content.Children(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), predicate, culture); + => content.Children(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, predicate, culture); /// /// Gets the children of the content, of any of the specified types. @@ -500,7 +503,7 @@ public static class FriendlyPublishedContentExtensions /// The content type alias. /// The children of the content, of any of the specified types. public static IEnumerable? ChildrenOfType(this IPublishedContent content, string contentTypeAlias, string? culture = null) - => content.ChildrenOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), contentTypeAlias, culture); + => content.ChildrenOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, contentTypeAlias, culture); /// /// Gets the children of the content, of a given content type. @@ -517,30 +520,30 @@ public static class FriendlyPublishedContentExtensions /// public static IEnumerable? Children(this IPublishedContent content, string? culture = null) where T : class, IPublishedContent - => content.Children(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture); + => content.Children(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, culture); public static IPublishedContent? FirstChild(this IPublishedContent content, string? culture = null) - => content.FirstChild(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture); + => content.FirstChild(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, culture); /// /// Gets the first child of the content, of a given content type. /// public static IPublishedContent? FirstChildOfType(this IPublishedContent content, string contentTypeAlias, string? culture = null) - => content.FirstChildOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), contentTypeAlias, culture); + => content.FirstChildOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, contentTypeAlias, culture); public static IPublishedContent? FirstChild(this IPublishedContent content, Func predicate, string? culture = null) - => content.FirstChild(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), predicate, culture); + => content.FirstChild(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, predicate, culture); public static IPublishedContent? FirstChild(this IPublishedContent content, Guid uniqueId, string? culture = null) - => content.FirstChild(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), uniqueId, culture); + => content.FirstChild(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, uniqueId, culture); public static T? FirstChild(this IPublishedContent content, string? culture = null) where T : class, IPublishedContent - => content.FirstChild(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture); + => content.FirstChild(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, culture); public static T? FirstChild(this IPublishedContent content, Func predicate, string? culture = null) where T : class, IPublishedContent - => content.FirstChild(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), predicate, culture); + => content.FirstChild(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, predicate, culture); /// /// Gets the siblings of the content. @@ -555,7 +558,7 @@ public static class FriendlyPublishedContentExtensions /// Note that in V7 this method also return the content node self. /// public static IEnumerable? Siblings(this IPublishedContent content, string? culture = null) - => content.Siblings(GetPublishedCache(content), GetNavigationQueryService(content), VariationContextAccessor, culture); + => content.Siblings(GetPublishedCache(content), GetNavigationQueryService(content), VariationContextAccessor, PublishStatusQueryService, culture); /// /// Gets the siblings of the content, of a given content type. @@ -571,7 +574,7 @@ public static class FriendlyPublishedContentExtensions /// Note that in V7 this method also return the content node self. /// public static IEnumerable? SiblingsOfType(this IPublishedContent content, string contentTypeAlias, string? culture = null) - => content.SiblingsOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), contentTypeAlias, culture); + => content.SiblingsOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, contentTypeAlias, culture); /// /// Gets the siblings of the content, of a given content type. @@ -588,7 +591,7 @@ public static class FriendlyPublishedContentExtensions /// public static IEnumerable? Siblings(this IPublishedContent content, string? culture = null) where T : class, IPublishedContent - => content.Siblings(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture); + => content.Siblings(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, culture); /// /// Gets the siblings of the content including the node itself to indicate the position. @@ -602,7 +605,7 @@ public static class FriendlyPublishedContentExtensions public static IEnumerable? SiblingsAndSelf( this IPublishedContent content, string? culture = null) - => content.SiblingsAndSelf(GetPublishedCache(content), GetNavigationQueryService(content), VariationContextAccessor, culture); + => content.SiblingsAndSelf(GetPublishedCache(content), GetNavigationQueryService(content), VariationContextAccessor, PublishStatusQueryService, culture); /// /// Gets the siblings of the content including the node itself to indicate the position, of a given content type. @@ -618,7 +621,7 @@ public static class FriendlyPublishedContentExtensions this IPublishedContent content, string contentTypeAlias, string? culture = null) - => content.SiblingsAndSelfOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), contentTypeAlias, culture); + => content.SiblingsAndSelfOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, contentTypeAlias, culture); /// /// Gets the siblings of the content including the node itself to indicate the position, of a given content type. @@ -632,7 +635,7 @@ public static class FriendlyPublishedContentExtensions /// The siblings of the content including the node itself, of the given content type. public static IEnumerable? SiblingsAndSelf(this IPublishedContent content, string? culture = null) where T : class, IPublishedContent - => content.SiblingsAndSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture); + => content.SiblingsAndSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), PublishStatusQueryService, culture); /// /// Gets the url of the content item. diff --git a/src/Umbraco.Web.UI.Client/examples/custom-modal/index.ts b/src/Umbraco.Web.UI.Client/examples/custom-modal/index.ts index 2ddf119f38..78610ced64 100644 --- a/src/Umbraco.Web.UI.Client/examples/custom-modal/index.ts +++ b/src/Umbraco.Web.UI.Client/examples/custom-modal/index.ts @@ -1,14 +1,14 @@ import type { ManifestDashboard } from '@umbraco-cms/backoffice/dashboard'; import type { ManifestModal } from '@umbraco-cms/backoffice/modal'; -const demoModal : ManifestModal = { +const demoModal: ManifestModal = { type: 'modal', name: 'Example Custom Modal Element', alias: 'example.modal.custom.element', js: () => import('./example-modal-view.element.js'), -} +}; -const demoModalsDashboard : ManifestDashboard = { +const demoModalsDashboard: ManifestDashboard = { type: 'dashboard', name: 'Example Custom Modal Dashboard', alias: 'example.dashboard.custom.modal.element', @@ -18,12 +18,12 @@ const demoModalsDashboard : ManifestDashboard = { label: 'Custom Modal', pathname: 'custom-modal', }, - conditions : [ + conditions: [ { alias: 'Umb.Condition.SectionAlias', - match: 'Umb.Section.Content' - } - ] -} + match: 'Umb.Section.Content', + }, + ], +}; -export default [demoModal,demoModalsDashboard]; +export default [demoModal, demoModalsDashboard]; diff --git a/src/Umbraco.Web.UI.Client/examples/validation-context/index.ts b/src/Umbraco.Web.UI.Client/examples/validation-context/index.ts index b64c960171..d21809b882 100644 --- a/src/Umbraco.Web.UI.Client/examples/validation-context/index.ts +++ b/src/Umbraco.Web.UI.Client/examples/validation-context/index.ts @@ -1,23 +1,21 @@ import type { ManifestDashboard } from '@umbraco-cms/backoffice/dashboard'; -const dashboard : ManifestDashboard = { +const dashboard: ManifestDashboard = { type: 'dashboard', alias: 'Demo.Dashboard', name: 'Demo Dashboard Validation Context', weight: 1000, element: () => import('./validation-context-dashboard.js'), meta: { - label: 'Validation Context Demo', - pathname: 'demo' + label: 'Validation Context Demo', + pathname: 'demo', }, - conditions : [ - { - alias : "Umb.Condition.SectionAlias", - match : "Umb.Section.Content" - } - ] -} + conditions: [ + { + alias: 'Umb.Condition.SectionAlias', + match: 'Umb.Section.Content', + }, + ], +}; -export const manifests = [ - dashboard -]; +export const manifests = [dashboard]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-areas-config/property-editor-ui-block-grid-areas-config.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-areas-config/property-editor-ui-block-grid-areas-config.element.ts index 34e10974b9..ebadbed801 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-areas-config/property-editor-ui-block-grid-areas-config.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-areas-config/property-editor-ui-block-grid-areas-config.element.ts @@ -11,6 +11,7 @@ import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import { incrementString } from '@umbraco-cms/backoffice/utils'; +import '../../components/block-grid-area-config-entry/index.js'; @customElement('umb-property-editor-ui-block-grid-areas-config') export class UmbPropertyEditorUIBlockGridAreasConfigElement extends UmbLitElement diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.element.ts index cbe0d0a5c4..e1fe416bf0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.element.ts @@ -38,12 +38,9 @@ export class UmbPropertyEditorUIBlockGridElement #settingsDataPathTranslator?: UmbBlockElementDataValidationPathTranslator; #managerContext = new UmbBlockGridManagerContext(this); // - private _value: UmbBlockGridValueModel = { - layout: {}, - contentData: [], - settingsData: [], - expose: [], - }; + private _value: UmbBlockGridValueModel | undefined = undefined; + + #lastValue: UmbBlockGridValueModel | undefined = undefined; public set config(config: UmbPropertyEditorConfigCollection | undefined) { if (!config) return; @@ -68,6 +65,13 @@ export class UmbPropertyEditorUIBlockGridElement @property({ attribute: false }) public override set value(value: UmbBlockGridValueModel | undefined) { + this.#lastValue = value; + + if (!value) { + this._value = undefined; + return; + } + const buildUpValue: Partial = value ? { ...value } : {}; buildUpValue.layout ??= {}; buildUpValue.contentData ??= []; @@ -80,7 +84,7 @@ export class UmbPropertyEditorUIBlockGridElement this.#managerContext.setSettings(this._value.settingsData); this.#managerContext.setExposes(this._value.expose); } - public override get value(): UmbBlockGridValueModel { + public override get value(): UmbBlockGridValueModel | undefined { return this._value; } @@ -116,13 +120,24 @@ export class UmbPropertyEditorUIBlockGridElement this.#managerContext.exposes, ]).pipe(debounceTime(20)), ([layouts, contents, settings, exposes]) => { - this._value = { - ...this._value, - layout: { [UMB_BLOCK_GRID_PROPERTY_EDITOR_SCHEMA_ALIAS]: layouts }, - contentData: contents, - settingsData: settings, - expose: exposes, - }; + if (layouts.length === 0) { + this._value = undefined; + } else { + this._value = { + ...this._value, + layout: { [UMB_BLOCK_GRID_PROPERTY_EDITOR_SCHEMA_ALIAS]: layouts }, + contentData: contents, + settingsData: settings, + expose: exposes, + }; + } + + // If we don't have a value set from the outside or an internal value, we don't want to set the value. + // This is added to prevent the block grid from setting an empty value on startup. + if (this.#lastValue === undefined && this._value === undefined) { + return; + } + propertyContext.setValue(this._value); }, 'motherObserver', diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts index 1559e4899a..d608e3c373 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts @@ -56,15 +56,19 @@ export class UmbPropertyEditorUIBlockListElement //#catalogueModal: UmbModalRouteRegistrationController; - private _value: UmbBlockListValueModel = { - layout: {}, - contentData: [], - settingsData: [], - expose: [], - }; + private _value: UmbBlockListValueModel | undefined = undefined; + + #lastValue: UmbBlockListValueModel | undefined = undefined; @property({ attribute: false }) public override set value(value: UmbBlockListValueModel | undefined) { + this.#lastValue = value; + + if (!value) { + this._value = undefined; + return; + } + const buildUpValue: Partial = value ? { ...value } : {}; buildUpValue.layout ??= {}; buildUpValue.contentData ??= []; @@ -188,13 +192,24 @@ export class UmbPropertyEditorUIBlockListElement this.#managerContext.exposes, ]).pipe(debounceTime(20)), ([layouts, contents, settings, exposes]) => { - this._value = { - ...this._value, - layout: { [UMB_BLOCK_LIST_PROPERTY_EDITOR_SCHEMA_ALIAS]: layouts }, - contentData: contents, - settingsData: settings, - expose: exposes, - }; + if (layouts.length === 0) { + this._value = undefined; + } else { + this._value = { + ...this._value, + layout: { [UMB_BLOCK_LIST_PROPERTY_EDITOR_SCHEMA_ALIAS]: layouts }, + contentData: contents, + settingsData: settings, + expose: exposes, + }; + } + + // If we don't have a value set from the outside or an internal value, we don't want to set the value. + // This is added to prevent the block list from setting an empty value on startup. + if (this.#lastValue === undefined && this._value === undefined) { + return; + } + context.setValue(this._value); }, 'motherObserver', diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts index 3696f7ba05..7b684e2014 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts @@ -300,9 +300,9 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert ? html`` + look="secondary"> + + ` : nothing; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts index 4e5ed4917d..11fa3c7b1f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts @@ -625,10 +625,18 @@ export abstract class UmbBlockEntryContext< //activate public edit() { - window.location.href = this.#generateWorkspaceEditContentPath(this.#workspacePath.value, this.getContentKey()); + window.history.pushState( + {}, + '', + this.#generateWorkspaceEditContentPath(this.#workspacePath.value, this.getContentKey()), + ); } public editSettings() { - window.location.href = this.#generateWorkspaceEditSettingsPath(this.#workspacePath.value, this.getContentKey()); + window.history.pushState( + {}, + '', + this.#generateWorkspaceEditSettingsPath(this.#workspacePath.value, this.getContentKey()), + ); } async requestDelete() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/index.ts index 6c15689d02..e7a2d3b39b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/auth/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/index.ts @@ -5,6 +5,5 @@ export * from './auth.context.token.js'; export * from './modals/index.js'; export type * from './models/openApiConfiguration.js'; export * from './components/index.js'; -export type * from './auth-provider.extension.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/types.ts index a0022a4344..601bc5c3b6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/auth/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/types.ts @@ -1,5 +1,7 @@ import type { ManifestAuthProvider } from './auth-provider.extension.js'; +export type * from './auth-provider.extension.js'; + /** * User login state that can be used to determine the current state of the user. * @example 'loggedIn' diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/types.ts index 50ef773e2c..5afc1fb6f1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/types.ts @@ -1,4 +1,4 @@ -import type { ManifestCollectionAction } from '../../extensions/index.js'; +import type { ManifestCollectionAction } from '../../extensions/types.js'; export interface ManifestCollectionActionCreateKind extends ManifestCollectionAction { type: 'collectionAction'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-view.manager.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-view.manager.test.ts index 10566af70d..793b9d0343 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-view.manager.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-view.manager.test.ts @@ -1,4 +1,4 @@ -import type { ManifestCollectionView } from './extensions/index.js'; +import type { ManifestCollectionView } from './extensions/types.js'; import { umbExtensionsRegistry } from '../extension-registry/index.js'; import { UmbCollectionViewManager } from './collection-view.manager.js'; import { expect } from '@open-wc/testing'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-view.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-view.manager.ts index 4b09399702..98ebdd6dd6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-view.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-view.manager.ts @@ -1,4 +1,4 @@ -import type { ManifestCollectionView } from './extensions/index.js'; +import type { ManifestCollectionView } from './extensions/types.js'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import { UmbExtensionsManifestInitializer, createExtensionElement } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection.element.ts index 83f6710f28..52f3837354 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection.element.ts @@ -1,5 +1,5 @@ import type { UmbCollectionConfiguration } from './types.js'; -import type { ManifestCollection } from './extensions/index.js'; +import type { ManifestCollection } from './extensions/types.js'; import { customElement, property } from '@umbraco-cms/backoffice/external/lit'; import { UmbExtensionElementAndApiSlotElementBase } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-view-bundle.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-view-bundle.element.ts index 5dc7283450..bc0007a73a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-view-bundle.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-view-bundle.element.ts @@ -1,5 +1,5 @@ import { UMB_COLLECTION_CONTEXT } from '../default/index.js'; -import type { ManifestCollectionView } from '../extensions/index.js'; +import type { ManifestCollectionView } from '../extensions/types.js'; import type { UmbCollectionLayoutConfiguration } from '../types.js'; import { UMB_ROUTE_CONTEXT } from '../../router/route.context.js'; import { css, customElement, html, nothing, query, repeat, state } from '@umbraco-cms/backoffice/external/lit'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/default/collection-default.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/default/collection-default.context.ts index 768341bfba..8400d72aa5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/default/collection-default.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/default/collection-default.context.ts @@ -8,7 +8,7 @@ import type { } from '../types.js'; import type { UmbCollectionFilterModel } from '../collection-filter-model.interface.js'; import type { UmbCollectionRepository } from '../repository/collection-repository.interface.js'; -import type { ManifestCollection } from '../extensions/index.js'; +import type { ManifestCollection } from '../extensions/types.js'; import { UMB_COLLECTION_CONTEXT } from './collection-default.context-token.js'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { UmbArrayState, UmbBasicState, UmbNumberState, UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/extensions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/extensions/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/collection/extensions/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/collection/extensions/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts index a083dd8beb..f449868688 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts @@ -1,9 +1,11 @@ -import type { ManifestCollection } from './extensions/index.js'; +import type { ManifestCollection } from './extensions/types.js'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; import type { UmbPaginationManager } from '@umbraco-cms/backoffice/utils'; -export type * from './extensions/index.js'; +export type * from './action/create/types.js'; +export type * from './extensions/types.js'; export type * from './conditions/types.js'; +export type * from './workspace-view/types.js'; /** @deprecated No longer used internally. This will be removed in Umbraco 17. [LK] */ export interface UmbCollectionBulkActionPermissions { @@ -50,5 +52,3 @@ export interface UmbCollectionContext { items: Observable; totalItems: Observable; } - -export type * from './extensions/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor.element.ts index d00b3ed3b9..9eefddaebd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor.element.ts @@ -269,9 +269,8 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements #deleteTab(tabId?: string) { if (!tabId) return; this.#workspaceContext?.structure.removeContainer(null, tabId); - // TODO: We should only navigate away if it was the last tab and if it was the active one... [NL] - if (this.#tabsStructureHelper?.isOwnerChildContainer(tabId)) { - window.history.replaceState(null, '', this._routerPath + (this._routes[0]?.path ?? '/root')); + if (this._activeTabId === tabId) { + this._activeTabId = undefined; } } async #addTab() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/types.ts index 169c1d43b0..4cded9d86c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/types.ts @@ -1,6 +1,8 @@ import type { UmbPropertyValueData } from '@umbraco-cms/backoffice/property'; import type { UmbEntityVariantModel } from '@umbraco-cms/backoffice/variant'; +export type * from './collection/types.js'; + export interface UmbElementDetailModel { values: Array; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/types.ts index 7d102e750a..d6b9038acb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/types.ts @@ -1,5 +1,4 @@ -import type { MetaEntityActionDefaultKind } from '../../default/index.js'; -import type { ManifestEntityAction } from '../../entity-action.extension.js'; +import type { ManifestEntityAction, MetaEntityActionDefaultKind } from '../../types.js'; export interface ManifestEntityActionCreateKind extends ManifestEntityAction { type: 'entityAction'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/delete/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/delete/types.ts index 51c0b06a95..e01e50df2b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/delete/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/delete/types.ts @@ -1,5 +1,4 @@ -import type { MetaEntityActionDefaultKind } from '../../default/index.js'; -import type { ManifestEntityAction } from '../../entity-action.extension.js'; +import type { ManifestEntityAction, MetaEntityActionDefaultKind } from '../../types.js'; export interface ManifestEntityActionDeleteKind extends ManifestEntityAction { type: 'entityAction'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/default/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/default/index.ts deleted file mode 100644 index 06c33f562f..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/default/index.ts +++ /dev/null @@ -1 +0,0 @@ -export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/index.ts index be1122bf5a..4347644d1f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/index.ts @@ -5,10 +5,6 @@ export * from './constants.js'; export * from './entity-action-base.js'; export * from './entity-action-list.element.js'; export * from './entity-action.event.js'; -export type * from './default/index.js'; -export type * from './entity-action-element.interface.js'; -export type * from './entity-action.extension.js'; -export type * from './entity-action.interface.js'; export type * from './types.js'; export { UmbRequestReloadStructureForEntityEvent } from './request-reload-structure-for-entity.event.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/types.ts index 445778b75a..5fc6da7380 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/types.ts @@ -1,5 +1,10 @@ import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; +export type * from './default/types.js'; +export type * from './entity-action-element.interface.js'; +export type * from './entity-action.extension.js'; +export type * from './entity-action.interface.js'; + export interface UmbEntityActionArgs extends UmbEntityModel { meta: MetaArgsType; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts index eb9efdc39a..e33dc3439b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts @@ -1,5 +1,3 @@ export * from './constants.js'; export * from './entity-create-option-action-base.js'; -export type * from './entity-create-option-action.extension.js'; -export type * from './entity-create-option-action.interface.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/types.ts index ca6db2fc24..f25781d059 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/types.ts @@ -1,5 +1,8 @@ import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; +export type * from './entity-create-option-action.extension.js'; +export type * from './entity-create-option-action.interface.js'; + export interface UmbEntityCreateOptionActionArgs extends UmbEntityModel { meta: MetaArgsType; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/extensions/external-login-provider-element.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/extensions/external-login-provider-element.interface.ts index bc7c5fcf4e..beeebcde24 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/extensions/external-login-provider-element.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/extensions/external-login-provider-element.interface.ts @@ -1,4 +1,4 @@ -import type { ManifestExternalLoginProvider } from '../extensions/index.js'; +import type { ManifestExternalLoginProvider } from './types.js'; export interface UmbExternalLoginProviderElement extends HTMLElement { manifest?: ManifestExternalLoginProvider; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/extensions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/extensions/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/extensions/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/extensions/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/index.ts index 12af91e886..c73d5980e7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/index.ts @@ -2,7 +2,7 @@ export * from './conditions/index.js'; export * from './initializers/index.js'; export * from './registry.js'; export * from './utils/index.js'; -export type * from './models/index.js'; -export type * from './extensions/index.js'; +export type * from './models/types.js'; +export type * from './extensions/types.js'; export { UmbExtensionElementAndApiSlotElementBase } from './extension-element-and-api-slot-element-base.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/index.ts index d2d7785f3b..504fcdf2ce 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/index.ts @@ -3,4 +3,3 @@ export * from './icon-registry.context-token.js'; export * from './icon-registry.context.js'; export * from './icon.registry.js'; export type * from './types.js'; -export type * from './extensions/icons.extension.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/types.ts index 49cea90d9c..ffc7c9d5db 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/types.ts @@ -1,5 +1,7 @@ import type { JsLoaderProperty } from '@umbraco-cms/backoffice/extension-api'; +export type * from './extensions/icons.extension.js'; + export interface UmbIconDefinition { name: string; path: JsLoaderProperty; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/menu-item/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/menu-item/index.ts index 461398c950..c324209993 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/menu-item/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/menu-item/index.ts @@ -1,2 +1 @@ export * from './menu-item-default.element.js'; -export type * from './link/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/menu-item/link/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/menu-item/link/index.ts deleted file mode 100644 index 06c33f562f..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/menu-item/link/index.ts +++ /dev/null @@ -1 +0,0 @@ -export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/menu-item/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/menu-item/types.ts new file mode 100644 index 0000000000..680bac4330 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/menu-item/types.ts @@ -0,0 +1 @@ +export type * from './link/types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/types.ts new file mode 100644 index 0000000000..c858b14791 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/types.ts @@ -0,0 +1 @@ +export type * from './menu-item/types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/menu/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/menu/index.ts index 1509c986d2..46a6c42b4b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/menu/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/menu/index.ts @@ -1,9 +1,7 @@ export * from './components/index.js'; export * from './menu-tree-structure-workspace-context-base.js'; export * from './menu-variant-tree-structure-workspace-context-base.js'; -export type * from './menu-item-element.interface.js'; -export type * from './menu-item.extension.js'; -export type * from './menu.extension.js'; + export type * from './types.js'; export type { UmbMenuStructureWorkspaceContext } from './menu-structure-workspace-context.interface.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/menu/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/menu/types.ts index 32ef22c9d1..93dda2eb92 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/menu/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/menu/types.ts @@ -1,5 +1,10 @@ import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; + +export type * from './components/types.js'; export type * from './conditions/types.js'; +export type * from './menu-item-element.interface.js'; +export type * from './menu-item.extension.js'; +export type * from './menu.extension.js'; // eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface UmbStructureItemModelBase extends UmbEntityModel {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/extensions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/extensions/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/extensions/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/modal/extensions/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts index ce18bc606e..061086786c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts @@ -1,7 +1,7 @@ import type { UUIModalElement, UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui'; import type { ElementLoaderProperty } from '@umbraco-cms/backoffice/extension-api'; -export type * from './extensions/index.js'; +export type * from './extensions/types.js'; export interface UmbPickerModalData { multiple?: boolean; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/picker/search/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/picker/search/index.ts index 736921ff3c..8ebaf3c542 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/picker/search/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/picker/search/index.ts @@ -1,4 +1,3 @@ export * from './manager/index.js'; export * from './picker-search-field.element.js'; export * from './picker-search-result.element.js'; -export type * from './result-item/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/picker/search/result-item/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/picker/search/result-item/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/picker/search/result-item/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/picker/search/result-item/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/picker/search/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/picker/search/types.ts new file mode 100644 index 0000000000..d68007d9e0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/picker/search/types.ts @@ -0,0 +1 @@ +export type * from './result-item/types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/picker/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/picker/types.ts index 1d134b429b..c537c39007 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/picker/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/picker/types.ts @@ -4,3 +4,5 @@ export interface UmbPickerContextConfig { queryParams?: object; }; } + +export type * from './search/types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/extensions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/extensions/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/property-editor/extensions/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/property-editor/extensions/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/index.ts index d17140d5ba..116b486efd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/index.ts @@ -2,5 +2,5 @@ export * from './components/index.js'; export * from './config/index.js'; export * from './constants.js'; export * from './events/index.js'; -export type * from './extensions/index.js'; export * from './ui-picker-modal/index.js'; +export type * from './extensions/types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/index.ts index 8359d84fd8..61e6863f58 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/index.ts @@ -1,2 +1 @@ -export type * from './types.js'; export * from './empty-recycle-bin.action.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/default/default-tree.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/default/default-tree.context.ts index c3d92d0a25..317869be1b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/default/default-tree.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/default/default-tree.context.ts @@ -2,7 +2,7 @@ import type { UmbTreeItemModel, UmbTreeRootModel, UmbTreeStartNode } from '../ty import type { UmbTreeRepository } from '../data/tree-repository.interface.js'; import type { UmbTreeContext } from '../tree-context.interface.js'; import type { UmbTreeRootItemsRequestArgs } from '../data/types.js'; -import type { ManifestTree } from '../extensions/index.js'; +import type { ManifestTree } from '../extensions/types.js'; import { UMB_TREE_CONTEXT } from './default-tree.context-token.js'; import { type UmbActionEventContext, UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; import { type ManifestRepository, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/entity-actions/move/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/entity-actions/move/index.ts index 4487f1c64e..aa9bd2d833 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/entity-actions/move/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/entity-actions/move/index.ts @@ -1,3 +1 @@ -export type { UmbMoveDataSource } from './move-data-source.interface.js'; -export type { UmbMoveRepository } from './move-repository.interface.js'; -export type * from './types.js'; +export { UmbMoveToEntityAction } from './move-to.action.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/entity-actions/move/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/entity-actions/move/types.ts index 43ecc9e964..ad260f0c7d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/entity-actions/move/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/entity-actions/move/types.ts @@ -1,5 +1,7 @@ import type { ManifestEntityAction, MetaEntityActionDefaultKind } from '@umbraco-cms/backoffice/entity-action'; +export type { UmbMoveDataSource } from './move-data-source.interface.js'; +export type { UmbMoveRepository } from './move-repository.interface.js'; export interface UmbMoveToRequestArgs { unique: string; destination: { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/entity-actions/sort-children-of/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/entity-actions/sort-children-of/index.ts index b25182fbbd..2e789e1917 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/entity-actions/sort-children-of/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/entity-actions/sort-children-of/index.ts @@ -1,4 +1 @@ export { UmbSortChildrenOfEntityAction } from './sort-children-of.action.js'; -export type { UmbSortChildrenOfRepository } from './sort-children-of-repository.interface.js'; -export type { UmbSortChildrenOfDataSource } from './sort-children-of-data-source.interface.js'; -export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/entity-actions/sort-children-of/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/entity-actions/sort-children-of/types.ts index 324542a93d..2e76d9d2d0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/entity-actions/sort-children-of/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/entity-actions/sort-children-of/types.ts @@ -1,5 +1,8 @@ import type { ManifestEntityAction, MetaEntityActionDefaultKind } from '@umbraco-cms/backoffice/entity-action'; +export type { UmbSortChildrenOfRepository } from './sort-children-of-repository.interface.js'; +export type { UmbSortChildrenOfDataSource } from './sort-children-of-data-source.interface.js'; + export interface UmbSortChildrenOfArgs { unique: string | null; sorting: Array<{ unique: string; sortOrder: number }>; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/entity-actions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/entity-actions/types.ts new file mode 100644 index 0000000000..ee4b8c7728 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/entity-actions/types.ts @@ -0,0 +1,4 @@ +export type * from './duplicate-to/types.js'; +export type * from './move/types.js'; +export type * from './reload-tree-item-children/types.js'; +export type * from './sort-children-of/types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/extensions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/extensions/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/tree/extensions/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/tree/extensions/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/create-folder/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/create-folder/index.ts index ffc37905b7..eece44714b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/create-folder/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/create-folder/index.ts @@ -1,2 +1 @@ export * from './create-folder.action.js'; -export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/delete-folder/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/delete-folder/index.ts index 965837eee2..933bf348d0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/delete-folder/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/delete-folder/index.ts @@ -1,2 +1 @@ export * from './delete-folder.action.js'; -export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/types.ts new file mode 100644 index 0000000000..f6fab2375b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/types.ts @@ -0,0 +1,3 @@ +export type * from './create-folder/types.js'; +export type * from './delete-folder/types.js'; +export type * from './update-folder/types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/update-folder/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/update-folder/index.ts index 4d0b526c1e..b8d1e36559 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/update-folder/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/update-folder/index.ts @@ -1,2 +1 @@ -export type * from './types.js'; export * from './update-folder.action.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/index.ts index ece5260792..7386cf5ee7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/index.ts @@ -1,3 +1,2 @@ -export type * from './types.js'; export * from './modal/index.js'; export * from './entity-action/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/types.ts index b82e6bc065..3594aaba33 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/types.ts @@ -1,6 +1,8 @@ import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; import type { MetaEntityActionDefaultKind } from '@umbraco-cms/backoffice/entity-action'; +export type * from './entity-action/types.js'; + export interface UmbFolderModel extends UmbEntityModel { name: string; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/index.ts index cc5849cd02..e80702822e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/index.ts @@ -8,8 +8,6 @@ export * from './folder/index.js'; export * from './tree-item/index.js'; export * from './tree-menu-item-default/index.js'; export * from './tree.element.js'; -export type * from './entity-actions/move/index.js'; -export type * from './extensions/index.js'; export type * from './types.js'; export type { UmbTreePickerModalData, UmbTreePickerModalValue } from './tree-picker-modal/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts index 5014d62716..45b440be74 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts @@ -2,7 +2,7 @@ import type { UmbTreeItemContext } from '../tree-item-context.interface.js'; import { UMB_TREE_CONTEXT, type UmbDefaultTreeContext } from '../../default/index.js'; import type { UmbTreeItemModel, UmbTreeRootModel } from '../../types.js'; import { UmbRequestReloadTreeItemChildrenEvent } from '../../entity-actions/reload-tree-item-children/index.js'; -import type { ManifestTreeItem } from '../../extensions/index.js'; +import type { ManifestTreeItem } from '../../extensions/types.js'; import { map } from '@umbraco-cms/backoffice/external/rxjs'; import { UmbArrayState, UmbBooleanState, UmbObjectState, UmbStringState } from '@umbraco-cms/backoffice/observable-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item.element.ts index 80b0f96288..54ae3c4580 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item.element.ts @@ -1,4 +1,4 @@ -import type { ManifestTreeItem } from '../extensions/index.js'; +import type { ManifestTreeItem } from '../extensions/types.js'; import { customElement, property } from '@umbraco-cms/backoffice/external/lit'; import { UmbExtensionElementAndApiSlotElementBase, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-menu-item-default/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-menu-item-default/index.ts index e6567452fe..af047cc2d4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-menu-item-default/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-menu-item-default/index.ts @@ -1,2 +1 @@ export * from './tree-menu-item-default.element.js'; -export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree.element.ts index dcb2340d9b..889ab0849b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree.element.ts @@ -1,4 +1,4 @@ -import type { ManifestTree } from './extensions/index.js'; +import type { ManifestTree } from './extensions/types.js'; import { customElement } from '@umbraco-cms/backoffice/external/lit'; import { UmbExtensionElementAndApiSlotElementBase } from '@umbraco-cms/backoffice/extension-registry'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/types.ts index 42ade241fd..f4cbd05593 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/types.ts @@ -1,5 +1,9 @@ import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; -export type * from './extensions/index.js'; + +export type * from './entity-actions/types.js'; +export type * from './extensions/types.js'; +export type * from './folder/types.js'; +export type * from './tree-menu-item-default/types.js'; export interface UmbTreeItemModelBase extends UmbEntityModel { name: string; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/index.ts deleted file mode 100644 index 06c33f562f..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/index.ts +++ /dev/null @@ -1 +0,0 @@ -export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-is-new-redirect.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-is-new-redirect.controller.ts index b553b2c00b..37c8bf0bec 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-is-new-redirect.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-is-new-redirect.controller.ts @@ -34,7 +34,7 @@ export class UmbWorkspaceIsNewRedirectController extends UmbControllerBase { id: unique, }); this.destroy(); - window.history.pushState({}, '', newPath); + window.history.replaceState({}, '', newPath); } } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/data-manager/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/data-manager/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/data-manager/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/data-manager/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts index 7188c11f93..04221017dd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts @@ -15,7 +15,4 @@ export * from './utils/object-to-property-value-array.function.js'; export * from './workspace-property-dataset/index.js'; export * from './workspace.context-token.js'; export * from './workspace.element.js'; -export type * from './conditions/index.js'; -export type * from './data-manager/index.js'; export type * from './types.js'; -export type * from './workspace-context.interface.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/kinds/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/kinds/types.ts new file mode 100644 index 0000000000..8bc5236dc9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/kinds/types.ts @@ -0,0 +1 @@ +export type * from './default/types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/types.ts index eae653cf08..82b14a3fec 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/types.ts @@ -1,6 +1,11 @@ import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity'; export type * from './extensions/types.js'; +export type * from './kinds/types.js'; +export type * from './conditions/types.js'; +export type * from './data-manager/types.js'; +export type * from './workspace-context.interface.js'; + /** * @deprecated Use `UmbEntityUnique`instead. */ diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/public-access/repository/public-access.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/public-access/repository/public-access.server.data.ts index 693c751dff..7221bc40d0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/public-access/repository/public-access.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/public-access/repository/public-access.server.data.ts @@ -1,7 +1,7 @@ import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api'; import type { PublicAccessRequestModel } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute, tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; /** * A data source for the Document Public Access that fetches data from the server @@ -41,7 +41,9 @@ export class UmbDocumentPublicAccessServerDataSource { */ async read(unique: string) { if (!unique) throw new Error('unique is missing'); - return tryExecuteAndNotify(this.#host, DocumentService.getDocumentByIdPublicAccess({ id: unique })); + // NOTE: The entity will not be present, when fetching Public Access for a descendant of a protected Document. + // This is a perfectly valid scenario, which is handled in the view. In other words, just use tryExecute here. + return tryExecute(DocumentService.getDocumentByIdPublicAccess({ id: unique })); } /** diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace-editor.element.ts index 0482a812a3..581d6c19c4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace-editor.element.ts @@ -102,11 +102,11 @@ export class UmbDocumentWorkspaceEditorElement extends UmbLitElement { if (!route) { // TODO: Notice: here is a specific index used for fallback, this could be made more solid [NL] - history.pushState({}, '', `${this.#workspaceRoute}/${routes[routes.length - 3].path}`); + history.replaceState({}, '', `${this.#workspaceRoute}/${routes[routes.length - 3].path}`); return; } - history.pushState({}, '', `${this.#workspaceRoute}/${route?.path}`); + history.replaceState({}, '', `${this.#workspaceRoute}/${route?.path}`); }, }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/packages/package/extensions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/packages/package/extensions/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/packages/package/extensions/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/packages/package/extensions/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/packages/package/index.ts b/src/Umbraco.Web.UI.Client/src/packages/packages/package/index.ts index 0343887cda..47e56552ee 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/packages/package/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/packages/package/index.ts @@ -1,3 +1,3 @@ export * from './constants.js'; export * from './repository/index.js'; -export type * from './extensions/index.js'; +export type * from './extensions/types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/components/rte-base.element.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/components/rte-base.element.ts index 60f61c75b3..1ad7e3406e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/rte/components/rte-base.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/rte/components/rte-base.element.ts @@ -10,11 +10,10 @@ import type { import { UmbBlockRteEntriesContext, UmbBlockRteManagerContext, - type UmbBlockRteLayoutModel, type UmbBlockRteTypeModel, } from '@umbraco-cms/backoffice/block-rte'; import { UMB_PROPERTY_CONTEXT, UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; -import type { UmbBlockValueType } from '@umbraco-cms/backoffice/block'; +import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; // eslint-disable-next-line local-rules/enforce-element-suffix-on-element-class-name export abstract class UmbPropertyEditorUiRteElementBase extends UmbLitElement implements UmbPropertyEditorUiElement { @@ -39,7 +38,7 @@ export abstract class UmbPropertyEditorUiRteElementBase extends UmbLitElement im public set value(value: UmbPropertyEditorUiValueType | undefined) { if (!value) { this._value = undefined; - this._markup = ''; + this._markup = this._latestMarkup = ''; this.#managerContext.setLayouts([]); this.#managerContext.setContents([]); this.#managerContext.setSettings([]); @@ -134,30 +133,38 @@ export abstract class UmbPropertyEditorUiRteElementBase extends UmbLitElement im this.#managerContext.setLayouts(layouts); }); - // Observe the value of the property and update the editor value. - this.observe(this.#managerContext.layouts, (layouts) => { - const blocksValue = - this._value && layouts?.length > 0 - ? { ...this._value.blocks, layout: { [UMB_BLOCK_RTE_PROPERTY_EDITOR_SCHEMA_ALIAS]: layouts } } - : undefined; + this.observe( + observeMultiple([ + this.#managerContext.layouts, + this.#managerContext.contents, + this.#managerContext.settings, + this.#managerContext.exposes, + ]), + ([layouts, contents, settings, exposes]) => { + if (layouts.length === 0) { + this._value = undefined; + } else { + this._value = { + markup: this._latestMarkup, + blocks: { + layout: { [UMB_BLOCK_RTE_PROPERTY_EDITOR_SCHEMA_ALIAS]: layouts }, + contentData: contents, + settingsData: settings, + expose: exposes, + }, + }; + } - this.#setBlocksValue(blocksValue); - }); + // If we don't have a value set from the outside or an internal value, we don't want to set the value. + // This is added to prevent the block list from setting an empty value on startup. + if (!this._latestMarkup && !this._value?.markup) { + return; + } - this.observe(this.#managerContext.contents, (contents) => { - const blocksValue = this._value ? { ...this._value.blocks, contentData: contents } : undefined; - this.#setBlocksValue(blocksValue); - }); - - this.observe(this.#managerContext.settings, (settings) => { - const blocksValue = this._value ? { ...this._value.blocks, settingsData: settings } : undefined; - this.#setBlocksValue(blocksValue); - }); - - this.observe(this.#managerContext.exposes, (exposes) => { - const blocksValue = this._value ? { ...this._value.blocks, expose: exposes } : undefined; - this.#setBlocksValue(blocksValue); - }); + context.setValue(this._value); + }, + 'motherObserver', + ); }); this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, (context) => { @@ -181,19 +188,6 @@ export abstract class UmbPropertyEditorUiRteElementBase extends UmbLitElement im }); } - #setBlocksValue(blocksValue?: UmbBlockValueType) { - if (!blocksValue || !this._value) { - return; - } - - this._value = { - ...this._value, - blocks: blocksValue, - }; - - this._fireChangeEvent(); - } - protected _fireChangeEvent() { this.dispatchEvent(new UmbPropertyValueChangeEvent()); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/extensions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/search/extensions/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/search/extensions/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/search/extensions/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts index 1de42cf897..fbaf7b411d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/search-modal/search-modal.element.ts @@ -16,7 +16,7 @@ import { UmbExtensionsManifestInitializer, createExtensionApi } from '@umbraco-c import '../search-result/search-result-item.element.js'; import type { UmbModalContext } from '@umbraco-cms/backoffice/modal'; -import type { ManifestSearchResultItem } from '../extensions/index.js'; +import type { ManifestSearchResultItem } from '../extensions/types.js'; type SearchProvider = { name: string; diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/types.ts b/src/Umbraco.Web.UI.Client/src/packages/search/types.ts index 2506d4d36e..a6e917353a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/types.ts @@ -2,6 +2,11 @@ import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; import type { UmbPagedModel, UmbRepositoryResponse } from '@umbraco-cms/backoffice/repository'; +export type { UmbSearchDataSource } from './search-data-source.interface.js'; +export type { UmbSearchRepository } from './search-repository.interface.js'; + +export type * from './extensions/types.js'; + // TODO: lower requirement for search provider item type export type UmbSearchResultItemModel = { entityType: string; @@ -22,8 +27,3 @@ export interface UmbSearchProvider< > extends UmbApi { search(args: SearchRequestArgsType): Promise>>; } - -export type { UmbSearchDataSource } from './search-data-source.interface.js'; -export type { UmbSearchRepository } from './search-repository.interface.js'; - -export type * from './extensions/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.defaults.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.defaults.ts index ac1260b8ce..a9c7b6255b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.defaults.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/components/input-tiny-mce/input-tiny-mce.defaults.ts @@ -76,31 +76,31 @@ export const defaultFallbackConfig: RawEditorOptions = { // If we try to open link in a new tab, then we want to skip skip: //if ((isWindows && e.ctrlKey) || (!isWindows && e.metaKey)) return; + const composedPaths = 'composedPath' in e ? e.composedPath() : null; + // Find the target by using the composed path to get the element through the shadow boundaries. // Notice the difference here compared to RouterSlots implementation [NL] - const $anchor: HTMLAnchorElement = (('composedPath' in e) as any) - ? (e - .composedPath() - .find(($elem) => $elem instanceof HTMLAnchorElement || ($elem as any).tagName === 'A') as HTMLAnchorElement) - : (e.target as HTMLAnchorElement); + const $anchor: HTMLAnchorElement = + (composedPaths?.find( + ($elem) => $elem instanceof HTMLAnchorElement || ($elem as any).tagName === 'A', + ) as HTMLAnchorElement) ?? (e.target as HTMLAnchorElement); - // Abort if the event is not about the anchor tag - if ($anchor == null || !($anchor instanceof HTMLAnchorElement || ($anchor as any).tagName === 'A')) { + // Abort if the event is not about the anchor tag or the anchor tag has the attribute [data-router-slot]="disabled" + if ( + $anchor == null || + !($anchor instanceof HTMLAnchorElement || ($anchor as any).tagName === 'A') || + $anchor.dataset['routerSlot'] === 'disabled' + ) { return; } - // Get the HREF value from the anchor tag - const href = $anchor.href; + // Abort if the anchor tag is not inside a block element + const isInsideBlockElement = + composedPaths?.some( + ($elem) => ($elem as any).tagName === 'UMB-RTE-BLOCK' || ($elem as any).tagName === 'UMB-RTE-BLOCK-INLINE', + ) ?? false; - // Only handle the anchor tag if the follow holds true: - // - The HREF is relative to the origin of the current location. - // - The target is targeting the current frame. - // - The anchor doesn't have the attribute [data-router-slot]="disabled" - if ( - !href.startsWith(location.origin) || - ($anchor.target !== '' && $anchor.target !== '_self') || - $anchor.dataset['routerSlot'] === 'disabled' - ) { + if (!isInsideBlockElement) { return; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/index.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/index.ts index 0d1c827429..3c7345719d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/index.ts @@ -1,3 +1,3 @@ export * from './constants.js'; export * from './components/index.js'; -export type * from './plugins/index.js'; +export type * from './plugins/types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/plugins/index.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/plugins/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/tiny-mce/plugins/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/tiny-mce/plugins/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/index.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/index.ts index 63d54ceaa8..aa343771ca 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/index.ts @@ -4,5 +4,3 @@ export * from './controllers/ufm-virtual-render.controller.js'; export * from './filters/base.filter.js'; export * from './plugins/index.js'; export type * from './types.js'; -export type * from './ufm-component.extension.js'; -export type * from './ufm-filter.extension.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts index 5a25901cdb..c95539b10d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts @@ -1 +1,2 @@ export type * from './ufm-filter.extension.js'; +export type * from './ufm-component.extension.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/types.ts index 8a4022dba3..fbd158e6d0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/types.ts @@ -1,2 +1 @@ -export type * from './is-admin/is-admin.condition-config.js'; export type * from './is-admin/types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/index.ts index 7d4396f5e4..64b0d29e78 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/index.ts @@ -1,6 +1,4 @@ export * from './components/index.js'; export * from './modals/index.js'; -export type * from './user-granular-permission.extension.js'; -export type * from './entity-user-permission.extension.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/types.ts index e84687e8bb..7f10a7e1b0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/types.ts @@ -1,3 +1,5 @@ +export type * from './user-granular-permission.extension.js'; +export type * from './entity-user-permission.extension.js'; export interface UmbUserPermissionModel { $type: string; verbs: Array; diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/PublishStatusServiceTest.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/PublishStatusServiceTest.cs index 861b8bac6c..3580d0314b 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/PublishStatusServiceTest.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/PublishStatusServiceTest.cs @@ -98,7 +98,9 @@ public class PublishStatusServiceTest : UmbracoIntegrationTestWithContent var sut = new PublishStatusService( GetRequiredService>(), GetRequiredService(), - GetRequiredService()); + GetRequiredService(), + GetRequiredService() + ); Assert.IsFalse(sut.IsDocumentPublished(Textpage.Key, DefaultCulture)); @@ -118,7 +120,8 @@ public class PublishStatusServiceTest : UmbracoIntegrationTestWithContent var sut = new PublishStatusService( GetRequiredService>(), GetRequiredService(), - GetRequiredService()); + GetRequiredService(), + GetRequiredService()); Assert.IsFalse(sut.IsDocumentPublished(Textpage.Key, DefaultCulture)); diff --git a/tests/Umbraco.Tests.UnitTests/AutoFixture/Customizations/UmbracoCustomizations.cs b/tests/Umbraco.Tests.UnitTests/AutoFixture/Customizations/UmbracoCustomizations.cs index ea794faeb7..eb29633166 100644 --- a/tests/Umbraco.Tests.UnitTests/AutoFixture/Customizations/UmbracoCustomizations.cs +++ b/tests/Umbraco.Tests.UnitTests/AutoFixture/Customizations/UmbracoCustomizations.cs @@ -11,6 +11,7 @@ using Umbraco.Cms.Core; using Umbraco.Cms.Core.Configuration; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Hosting; +using Umbraco.Cms.Core.Routing; using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Infrastructure.Install; @@ -34,7 +35,8 @@ internal class UmbracoCustomizations : ICustomization .Customize(new ConstructorCustomization(typeof(DatabaseSchemaCreatorFactory), new GreedyConstructorQuery())) .Customize(new ConstructorCustomization(typeof(InstallHelper), new GreedyConstructorQuery())) .Customize(new ConstructorCustomization(typeof(DatabaseBuilder), new GreedyConstructorQuery())) - .Customize(new ConstructorCustomization(typeof(ContentVersionService), new GreedyConstructorQuery())); + .Customize(new ConstructorCustomization(typeof(ContentVersionService), new GreedyConstructorQuery())) + .Customize(new ConstructorCustomization(typeof(ContentFinderByUrlAlias), new GreedyConstructorQuery())); // When requesting an IUserStore ensure we actually uses a IUserLockoutStore fixture.Customize>(cc => diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/ContentRouteBuilderTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/ContentRouteBuilderTests.cs index 06950c4ba9..c0001bf067 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/ContentRouteBuilderTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/ContentRouteBuilderTests.cs @@ -429,9 +429,10 @@ public class ContentRouteBuilderTests : DeliveryApiTests { var variantContextAccessor = Mock.Of(); + string Url(IPublishedContent content, string? culture) { - var ancestorsOrSelf = content.AncestorsOrSelf(contentCache, navigationQueryService).ToArray(); + var ancestorsOrSelf = content.AncestorsOrSelf(variantContextAccessor, contentCache, navigationQueryService, PublishStatusQueryService).ToArray(); return ancestorsOrSelf.All(c => c.IsPublished(culture)) ? string.Join("/", ancestorsOrSelf.Reverse().Skip(hideTopLevelNodeFromPath ? 1 : 0).Select(c => c.UrlSegment(variantContextAccessor, culture))).EnsureStartsWith("/") : "#"; diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/DeliveryApiTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/DeliveryApiTests.cs index 5b349671d6..2764dd21d3 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/DeliveryApiTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/DeliveryApiTests.cs @@ -20,6 +20,8 @@ public class DeliveryApiTests protected IPublishedPropertyType DefaultPropertyType { get; private set; } + protected IPublishStatusQueryService PublishStatusQueryService { get; private set; } + [SetUp] public virtual void Setup() { @@ -57,6 +59,13 @@ public class DeliveryApiTests defaultPropertyValueConverter.Setup(p => p.GetPropertyCacheLevel(It.IsAny())).Returns(PropertyCacheLevel.None); DefaultPropertyType = SetupPublishedPropertyType(defaultPropertyValueConverter.Object, "default", "Default.Editor"); + + var publishStatusQueryService = new Mock(); + publishStatusQueryService + .Setup(x => x.IsDocumentPublished(It.IsAny(), It.IsAny())) + .Returns(true); + + PublishStatusQueryService = publishStatusQueryService.Object; } protected IPublishedPropertyType SetupPublishedPropertyType(IPropertyValueConverter valueConverter, string propertyTypeAlias, string editorAlias, object? dataTypeConfiguration = null) @@ -117,7 +126,8 @@ public class DeliveryApiTests IRequestPreviewService? requestPreviewService = null, IOptionsMonitor? requestHandlerSettingsMonitor = null, IPublishedContentCache? contentCache = null, - IDocumentNavigationQueryService? navigationQueryService = null) + IDocumentNavigationQueryService? navigationQueryService = null, + IPublishStatusQueryService? publishStatusQueryService = null) { if (requestHandlerSettingsMonitor == null) { @@ -133,6 +143,7 @@ public class DeliveryApiTests requestPreviewService ?? Mock.Of(), requestHandlerSettingsMonitor, contentCache ?? Mock.Of(), - navigationQueryService ?? Mock.Of()); + navigationQueryService ?? Mock.Of(), + publishStatusQueryService ?? PublishStatusQueryService); } } diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Routing/ContentFinderByUrlAliasTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Routing/ContentFinderByUrlAliasTests.cs index 1977c918a5..d7f86ff11e 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Routing/ContentFinderByUrlAliasTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Routing/ContentFinderByUrlAliasTests.cs @@ -7,6 +7,7 @@ using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.PublishedCache; using Umbraco.Cms.Core.Routing; using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Core.Services.Navigation; using Umbraco.Cms.Core.Web; using Umbraco.Cms.Tests.UnitTests.AutoFixture; @@ -30,6 +31,7 @@ public class ContentFinderByUrlAliasTests [Frozen] IUmbracoContextAccessor umbracoContextAccessor, [Frozen] IUmbracoContext umbracoContext, [Frozen] IVariationContextAccessor variationContextAccessor, + [Frozen] IPublishStatusQueryService publishStatusQueryService, IFileService fileService, ContentFinderByUrlAlias sut, IPublishedContent[] rootContents, @@ -48,6 +50,7 @@ public class ContentFinderByUrlAliasTests Mock.Get(urlProperty).Setup(x => x.GetValue(null, null)).Returns(relativeUrl); Mock.Get(variationContextAccessor).Setup(x => x.VariationContext).Returns(variationContext); + Mock.Get(publishStatusQueryService).Setup(x => x.IsDocumentPublished(It.IsAny(), It.IsAny())).Returns(true); var publishedRequestBuilder = new PublishedRequestBuilder(new Uri(absoluteUrl, UriKind.Absolute), fileService); // Act diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Templates/HtmlImageSourceParserTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Templates/HtmlImageSourceParserTests.cs index b98d1b1731..1a4a73f800 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Templates/HtmlImageSourceParserTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Templates/HtmlImageSourceParserTests.cs @@ -99,7 +99,8 @@ public class HtmlImageSourceParserTests new MediaUrlProviderCollection(() => new[] { mediaUrlProvider.Object }), Mock.Of(), Mock.Of(), - Mock.Of()); + Mock.Of(), + Mock.Of()); using (var reference = umbracoContextFactory.EnsureUmbracoContext()) { diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Templates/HtmlLocalLinkParserTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Templates/HtmlLocalLinkParserTests.cs index 5a35a096ee..ad2fb0b231 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Templates/HtmlLocalLinkParserTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Templates/HtmlLocalLinkParserTests.cs @@ -235,6 +235,11 @@ public class HtmlLocalLinkParserTests mediaCache.Setup(x => x.GetById(It.IsAny())).Returns(media.Object); mediaCache.Setup(x => x.GetById(It.IsAny())).Returns(media.Object); + var publishStatusQueryService = new Mock(); + publishStatusQueryService + .Setup(x => x.IsDocumentPublished(It.IsAny(), It.IsAny())) + .Returns(true); + var publishedUrlProvider = new UrlProvider( umbracoContextAccessor, Options.Create(webRoutingSettings), @@ -242,7 +247,8 @@ public class HtmlLocalLinkParserTests new MediaUrlProviderCollection(() => new[] { mediaUrlProvider.Object }), Mock.Of(), contentCache.Object, - navigationQueryService.Object); + navigationQueryService.Object, + publishStatusQueryService.Object); var linkParser = new HtmlLocalLinkParser(publishedUrlProvider);