// Copyright (c) Umbraco. // See LICENSE for more details. using System.Data; using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Membership; 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; namespace Umbraco.Extensions; public static class PublishedContentExtensions { #region Name /// /// Gets the name of the content item. /// /// The content item. /// /// /// The specific culture to get the name for. If null is used the current culture is used (Default is /// null). /// public static string Name(this IPublishedContent content, IVariationContextAccessor? variationContextAccessor, string? culture = null) { if (content == null) { throw new ArgumentNullException(nameof(content)); } // invariant has invariant value (whatever the requested culture) if (!content.ContentType.VariesByCulture()) { return content.Cultures.TryGetValue(string.Empty, out PublishedCultureInfo? invariantInfos) ? invariantInfos.Name : string.Empty; } // handle context culture for variant if (culture == null) { culture = variationContextAccessor?.VariationContext?.Culture ?? string.Empty; } // get return culture != string.Empty && content.Cultures.TryGetValue(culture, out PublishedCultureInfo? infos) ? infos.Name : string.Empty; } #endregion #region Url segment /// /// Gets the URL segment of the content item. /// /// The content item. /// /// /// The specific culture to get the URL segment for. If null is used the current culture is used /// (Default is null). /// [Obsolete("Please use GetUrlSegment() on IDocumentUrlService instead. Scheduled for removal in V16.")] public static string? UrlSegment(this IPublishedContent content, IVariationContextAccessor? variationContextAccessor, string? culture = null) { if (content == null) { throw new ArgumentNullException(nameof(content)); } // invariant has invariant value (whatever the requested culture) if (!content.ContentType.VariesByCulture()) { return content.Cultures.TryGetValue(string.Empty, out PublishedCultureInfo? invariantInfos) ? invariantInfos.UrlSegment : null; } // handle context culture for variant if (culture == null) { culture = variationContextAccessor?.VariationContext?.Culture ?? string.Empty; } // get return culture != string.Empty && content.Cultures.TryGetValue(culture, out PublishedCultureInfo? infos) ? infos.UrlSegment : null; } #endregion #region IsComposedOf /// /// Gets a value indicating whether the content is of a content type composed of the given alias /// /// The content. /// The content type alias. /// /// A value indicating whether the content is of a content type composed of a content type identified by the /// alias. /// public static bool IsComposedOf(this IPublishedContent content, string alias) => content.ContentType.CompositionAliases.InvariantContains(alias); #endregion #region Axes: parent // Parent is native /// /// Gets the parent of the content, of a given content type. /// /// The content type. /// The content. /// The query service for the in-memory navigation structure. /// /// The parent of content, of the given content type, else null. public static T? Parent( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService) where T : class, IPublishedContent { ArgumentNullException.ThrowIfNull(content); return content.GetParent(navigationQueryService, publishedStatusFilteringService) as T; } [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static T? Parent( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService) where T : class, IPublishedContent => content.Parent(navigationQueryService, GetPublishedStatusFilteringService(content)); private static IPublishedContent? GetParent( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService) { if (navigationQueryService.TryGetParentKey(content.Key, out Guid? parentKey) is false) { throw new KeyNotFoundException($"Content with key '{content.Key}' was not found in the in-memory navigation structure."); } // parent key is null if content is at root return parentKey.HasValue ? publishedStatusFilteringService.FilterAvailable([parentKey.Value], null).FirstOrDefault() : null; } #endregion #region Url /// /// Gets the url of the content item. /// /// /// /// If the content item is a document, then this method returns the url of the /// document. If it is a media, then this methods return the media url for the /// 'umbracoFile' property. Use the MediaUrl() method to get the media url for other /// properties. /// /// /// The value of this property is contextual. It depends on the 'current' request uri, /// if any. In addition, when the content type is multi-lingual, this is the url for the /// specified culture. Otherwise, it is the invariant url. /// /// public static string Url(this IPublishedContent content, IPublishedUrlProvider publishedUrlProvider, string? culture = null, UrlMode mode = UrlMode.Default) { if (publishedUrlProvider == null) { throw new InvalidOperationException( "Cannot resolve a Url when Current.UmbracoContext.UrlProvider is null."); } switch (content.ContentType.ItemType) { case PublishedItemType.Content: return publishedUrlProvider.GetUrl(content, mode, culture); case PublishedItemType.Media: return publishedUrlProvider.GetMediaUrl(content, mode, culture); default: throw new NotSupportedException(); } } #endregion #region Culture /// /// Determines whether the content has a culture. /// /// Culture is case-insensitive. public static bool HasCulture(this IPublishedContent content, string? culture) { if (content == null) { throw new ArgumentNullException(nameof(content)); } return content.Cultures.ContainsKey(culture ?? string.Empty); } /// /// Determines whether the content is invariant, or has a culture. /// /// Culture is case-insensitive. public static bool IsInvariantOrHasCulture(this IPublishedContent content, string culture) => !content.ContentType.VariesByCulture() || content.Cultures.ContainsKey(culture ?? string.Empty); /// /// Gets the culture date of the content item. /// /// The content item. /// /// /// The specific culture to get the name for. If null is used the current culture is used (Default is /// null). /// public static DateTime CultureDate(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null) { // invariant has invariant value (whatever the requested culture) if (!content.ContentType.VariesByCulture()) { return content.UpdateDate; } // handle context culture for variant if (culture == null) { culture = variationContextAccessor?.VariationContext?.Culture ?? string.Empty; } // get return culture != string.Empty && content.Cultures.TryGetValue(culture, out PublishedCultureInfo? infos) ? infos.Date : DateTime.MinValue; } #endregion #region Template /// /// Returns the current template Alias /// /// Empty string if none is set. public static string GetTemplateAlias(this IPublishedContent content, IFileService fileService) { if (content.TemplateId.HasValue == false) { return string.Empty; } ITemplate? template = fileService.GetTemplate(content.TemplateId.Value); return template?.Alias ?? string.Empty; } public static bool IsAllowedTemplate(this IPublishedContent content, IContentTypeService contentTypeService, WebRoutingSettings webRoutingSettings, int templateId) => content.IsAllowedTemplate(contentTypeService, webRoutingSettings.DisableAlternativeTemplates, webRoutingSettings.ValidateAlternativeTemplates, templateId); public static bool IsAllowedTemplate(this IPublishedContent content, IContentTypeService contentTypeService, bool disableAlternativeTemplates, bool validateAlternativeTemplates, int templateId) { if (disableAlternativeTemplates) { return content.TemplateId == templateId; } if (content.TemplateId == templateId || !validateAlternativeTemplates) { return true; } IContentType? publishedContentContentType = contentTypeService.Get(content.ContentType.Id); if (publishedContentContentType == null) { throw new NullReferenceException("No content type returned for published content (contentType='" + content.ContentType.Id + "')"); } return publishedContentContentType.IsAllowedTemplate(templateId); } public static bool IsAllowedTemplate(this IPublishedContent content, IFileService fileService, IContentTypeService contentTypeService, bool disableAlternativeTemplates, bool validateAlternativeTemplates, string templateAlias) { ITemplate? template = fileService.GetTemplate(templateAlias); return template != null && content.IsAllowedTemplate(contentTypeService, disableAlternativeTemplates, validateAlternativeTemplates, template.Id); } #endregion #region HasValue, Value, Value /// /// Gets a value indicating whether the content has a value for a property identified by its alias. /// /// The content. /// The published value fallback implementation. /// The property alias. /// The variation language. /// The variation segment. /// Optional fallback strategy. /// A value indicating whether the content has a value for the property identified by the alias. /// Returns true if HasValue is true, or a fallback strategy can provide a value. public static bool HasValue(this IPublishedContent content, IPublishedValueFallback publishedValueFallback, string alias, string? culture = null, string? segment = null, Fallback fallback = default) { IPublishedProperty? property = content.GetProperty(alias); // if we have a property, and it has a value, return that value if (property != null && property.HasValue(culture, segment)) { return true; } // else let fallback try to get a value return publishedValueFallback.TryGetValue(content, alias, culture, segment, fallback, null, out _, out _); } /// /// Gets the value of a content's property identified by its alias, if it exists, otherwise a default value. /// /// The content. /// The published value fallback implementation. /// The property alias. /// The variation language. /// The variation segment. /// Optional fallback strategy. /// The default value. /// The value of the content's property identified by the alias, if it exists, otherwise a default value. public static object? Value( this IPublishedContent content, IPublishedValueFallback publishedValueFallback, string alias, string? culture = null, string? segment = null, Fallback fallback = default, object? defaultValue = default) { IPublishedProperty? property = content.GetProperty(alias); // if we have a property, and it has a value, return that value if (property != null && property.HasValue(culture, segment)) { return property.GetValue(culture, segment); } // else let fallback try to get a value if (publishedValueFallback.TryGetValue(content, alias, culture, segment, fallback, defaultValue, out var value, out property)) { return value; } // else... if we have a property, at least let the converter return its own // vision of 'no value' (could be an empty enumerable) return property?.GetValue(culture, segment); } /// /// Gets the value of a content's property identified by its alias, converted to a specified type. /// /// The target property type. /// The content. /// The published value fallback implementation. /// The property alias. /// The variation language. /// The variation segment. /// Optional fallback strategy. /// The default value. /// The value of the content's property identified by the alias, converted to the specified type. public static T? Value( this IPublishedContent content, IPublishedValueFallback publishedValueFallback, string alias, string? culture = null, string? segment = null, Fallback fallback = default, T? defaultValue = default) { IPublishedProperty? property = content.GetProperty(alias); // if we have a property, and it has a value, return that value if (property != null && property.HasValue(culture, segment)) { return property.Value(publishedValueFallback, culture, segment); } // else let fallback try to get a value if (publishedValueFallback.TryGetValue(content, alias, culture, segment, fallback, defaultValue, out T? value, out property)) { return value; } // else... if we have a property, at least let the converter return its own // vision of 'no value' (could be an empty enumerable) - otherwise, default return property == null ? default : property.Value(publishedValueFallback, culture, segment); } #endregion #region IsSomething: misc. /// /// Determines whether the specified content is a specified content type. /// /// The content to determine content type of. /// The alias of the content type to test against. /// True if the content is of the specified content type; otherwise false. public static bool IsDocumentType(this IPublishedContent content, string docTypeAlias) => content.ContentType.Alias.InvariantEquals(docTypeAlias); /// /// Determines whether the specified content is a specified content type or it's derived types. /// /// The content to determine content type of. /// The alias of the content type to test against. /// /// When true, recurses up the content type tree to check inheritance; when false just calls /// IsDocumentType(this IPublishedContent content, string docTypeAlias). /// /// True if the content is of the specified content type or a derived content type; otherwise false. public static bool IsDocumentType(this IPublishedContent content, string docTypeAlias, bool recursive) { if (content.IsDocumentType(docTypeAlias)) { return true; } return recursive && content.IsComposedOf(docTypeAlias); } #endregion #region IsSomething: equality public static bool IsEqual(this IPublishedContent content, IPublishedContent other) => content.Id == other.Id; public static bool IsNotEqual(this IPublishedContent content, IPublishedContent other) => content.IsEqual(other) == false; #endregion #region IsSomething: ancestors and descendants public static bool IsDescendant(this IPublishedContent content, IPublishedContent other) => other.Level < content.Level && content.Path.InvariantStartsWith(other.Path.EnsureEndsWith(',')); public static bool IsDescendantOrSelf(this IPublishedContent content, IPublishedContent other) => content.Path.InvariantEquals(other.Path) || content.IsDescendant(other); public static bool IsAncestor(this IPublishedContent content, IPublishedContent other) => content.Level < other.Level && other.Path.InvariantStartsWith(content.Path.EnsureEndsWith(',')); public static bool IsAncestorOrSelf(this IPublishedContent content, IPublishedContent other) => other.Path.InvariantEquals(content.Path) || content.IsAncestor(other); #endregion #region Axes: ancestors, ancestors-or-self // as per XPath 1.0 specs �2.2, // - the ancestor axis contains the ancestors of the context node; the ancestors of the context node consist // of the parent of context node and the parent's parent and so on; thus, the ancestor axis will always // include the root node, unless the context node is the root node. // - the ancestor-or-self axis contains the context node and the ancestors of the context node; thus, // the ancestor axis will always include the root node. // // as per XPath 2.0 specs �3.2.1.1, // - the ancestor axis is defined as the transitive closure of the parent axis; it contains the ancestors // of the context node (the parent, the parent of the parent, and so on) - The ancestor axis includes the // root node of the tree in which the context node is found, unless the context node is the root node. // - the ancestor-or-self axis contains the context node and the ancestors of the context node; thus, // the ancestor-or-self axis will always include the root node. // // the ancestor and ancestor-or-self axis are reverse axes ie they contain the context node or nodes that // are before the context node in document order. // // document order is defined by �2.4.1 as: // - the root node is the first node. // - every node occurs before all of its children and descendants. // - the relative order of siblings is the order in which they occur in the children property of their parent node. // - children and descendants occur before following siblings. /// /// Gets the ancestors of the content. /// /// The content. /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService) => content.AncestorsOrSelf(navigationQueryService, publishedStatusFilteringService, false, null); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Ancestors( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService) => content.Ancestors(navigationQueryService, GetPublishedStatusFilteringService(content)); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Ancestors( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService) => content.Ancestors(navigationQueryService, GetPublishedStatusFilteringService(content)); /// /// Gets the ancestors of the content, at a level lesser or equal to a specified level. /// /// The content. /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, int maxLevel) => content.AncestorsOrSelf( navigationQueryService, publishedStatusFilteringService, false, n => n.Level <= maxLevel); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Ancestors( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, int maxLevel) => content.Ancestors(navigationQueryService, GetPublishedStatusFilteringService(content), maxLevel); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Ancestors( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int maxLevel) => content.Ancestors(navigationQueryService, GetPublishedStatusFilteringService(content), maxLevel); /// /// Gets the ancestors of the content, of a specified content type. /// /// The content. /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string contentTypeAlias) { ArgumentNullException.ThrowIfNull(content); return content.EnumerateAncestorsOrSelfInternal( navigationQueryService, publishedStatusFilteringService, false, contentTypeAlias); } [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Ancestors( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias) => content.Ancestors(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Ancestors( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string contentTypeAlias) => content.Ancestors(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias); /// /// Gets the ancestors of the content, of a specified content type. /// /// The content type. /// The content. /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService) where T : class, IPublishedContent => content.Ancestors(navigationQueryService, publishedStatusFilteringService).OfType(); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Ancestors( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService) where T : class, IPublishedContent => content.Ancestors(navigationQueryService, GetPublishedStatusFilteringService(content)); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Ancestors( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService) where T : class, IPublishedContent => content.Ancestors(navigationQueryService, GetPublishedStatusFilteringService(content)); /// /// 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 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, int maxLevel) where T : class, IPublishedContent => content.Ancestors(navigationQueryService, publishedStatusFilteringService, maxLevel).OfType(); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Ancestors( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, int maxLevel) where T : class, IPublishedContent => content.Ancestors(navigationQueryService, GetPublishedStatusFilteringService(content), maxLevel); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Ancestors( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int maxLevel) where T : class, IPublishedContent => content.Ancestors(navigationQueryService, GetPublishedStatusFilteringService(content), maxLevel); /// /// Gets the content and its ancestors. /// /// The content. /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService) => content.AncestorsOrSelf(navigationQueryService, publishedStatusFilteringService, true, null); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable AncestorsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService) => content.AncestorsOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content)); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable AncestorsOrSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService) => content.AncestorsOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content)); /// /// Gets the content and its ancestors, at a level lesser or equal to a specified level. /// /// The content. /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, int maxLevel) => content.AncestorsOrSelf( navigationQueryService, publishedStatusFilteringService, true, n => n.Level <= maxLevel); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable AncestorsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, int maxLevel) => content.AncestorsOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), maxLevel); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable AncestorsOrSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int maxLevel) => content.AncestorsOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), maxLevel); /// /// Gets the content and its ancestors, of a specified content type. /// /// The content. /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string contentTypeAlias) { ArgumentNullException.ThrowIfNull(content); return content.EnumerateAncestorsOrSelfInternal( navigationQueryService, publishedStatusFilteringService, true, contentTypeAlias); } [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable AncestorsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias) => content.AncestorsOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable AncestorsOrSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string contentTypeAlias) => content.AncestorsOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias); /// /// Gets the content and its ancestors, of a specified content type. /// /// The content type. /// The content. /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService) where T : class, IPublishedContent => content.AncestorsOrSelf(navigationQueryService, publishedStatusFilteringService).OfType(); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable AncestorsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService) where T : class, IPublishedContent => content.AncestorsOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content)); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable AncestorsOrSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService) where T : class, IPublishedContent => content.AncestorsOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content)); /// /// 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 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, int maxLevel) where T : class, IPublishedContent => content.AncestorsOrSelf(navigationQueryService, publishedStatusFilteringService, maxLevel).OfType(); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable AncestorsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, int maxLevel) where T : class, IPublishedContent => content.AncestorsOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), maxLevel); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable AncestorsOrSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int maxLevel) where T : class, IPublishedContent => content.AncestorsOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), maxLevel); /// /// Gets the ancestor of the content, ie its parent. /// /// The content. /// The query service for the in-memory navigation structure. /// /// The ancestor of the content. /// This method is here for consistency purposes but does not make much sense. public static IPublishedContent? Ancestor( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService) => content.GetParent(navigationQueryService, publishedStatusFilteringService); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? Ancestor( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService) => content.Ancestor(navigationQueryService, GetPublishedStatusFilteringService(content)); /// /// Gets the nearest ancestor of the content, at a lever lesser or equal to a specified level. /// /// The content. /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, int maxLevel) => content .EnumerateAncestors(navigationQueryService, publishedStatusFilteringService, false) .FirstOrDefault(x => x.Level <= maxLevel); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? Ancestor( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, int maxLevel) => content.Ancestor(navigationQueryService, GetPublishedStatusFilteringService(content), maxLevel); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? Ancestor( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int maxLevel) => content.Ancestor(navigationQueryService, GetPublishedStatusFilteringService(content), maxLevel); /// /// Gets the nearest ancestor of the content, of a specified content type. /// /// The content. /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string contentTypeAlias) { ArgumentNullException.ThrowIfNull(content); return content .EnumerateAncestorsOrSelfInternal( navigationQueryService, publishedStatusFilteringService, false, contentTypeAlias) .FirstOrDefault(); } [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? Ancestor( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias) => content.Ancestor(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? Ancestor( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string contentTypeAlias) => content.Ancestor(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias); /// /// Gets the nearest ancestor of the content, of a specified content type. /// /// The content type. /// The content. /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService) where T : class, IPublishedContent => content.Ancestors(navigationQueryService, publishedStatusFilteringService).FirstOrDefault(); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static T? Ancestor( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService) where T : class, IPublishedContent => content.Ancestor(navigationQueryService, GetPublishedStatusFilteringService(content)); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static T? Ancestor( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService) where T : class, IPublishedContent => content.Ancestor(navigationQueryService, GetPublishedStatusFilteringService(content)); /// /// Gets the nearest ancestor of the content, at the specified level and of the specified content type. /// /// The content type. /// The content. /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, int maxLevel) where T : class, IPublishedContent => content.Ancestors(navigationQueryService, publishedStatusFilteringService, maxLevel).FirstOrDefault(); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static T? Ancestor( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, int maxLevel) where T : class, IPublishedContent => content.Ancestor(navigationQueryService, GetPublishedStatusFilteringService(content), maxLevel); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static T? Ancestor( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int maxLevel) where T : class, IPublishedContent => content.Ancestor(navigationQueryService, GetPublishedStatusFilteringService(content), maxLevel); /// /// Gets the content or its nearest ancestor. /// /// The content. /// The content. /// This method is here for consistency purposes but does not make much sense. public static IPublishedContent AncestorOrSelf(this IPublishedContent content) => content; /// /// Gets the content or its nearest ancestor, at a lever lesser or equal to a specified level. /// /// The content. /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, int maxLevel) => content .EnumerateAncestors(navigationQueryService, publishedStatusFilteringService, true) .FirstOrDefault(x => x.Level <= maxLevel) ?? content; [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent AncestorOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, int maxLevel) => content.AncestorOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), maxLevel); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent AncestorOrSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int maxLevel) => content.AncestorOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), maxLevel); /// /// Gets the content or its nearest ancestor, of a specified content type. /// /// The content. /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string contentTypeAlias) { ArgumentNullException.ThrowIfNull(content); return content .EnumerateAncestorsOrSelfInternal( navigationQueryService, publishedStatusFilteringService, true, contentTypeAlias) .FirstOrDefault() ?? content; } [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent AncestorOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias) => content.AncestorOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent AncestorOrSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string contentTypeAlias) => content.AncestorOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias); /// /// Gets the content or its nearest ancestor, of a specified content type. /// /// The content type. /// The content. /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService) where T : class, IPublishedContent => content.AncestorsOrSelf(navigationQueryService, publishedStatusFilteringService).FirstOrDefault(); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static T? AncestorOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService) where T : class, IPublishedContent => content.AncestorOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content)); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static T? AncestorOrSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService) where T : class, IPublishedContent => content.AncestorOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content)); /// /// 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 query service for the in-memory navigation structure. /// /// The level. /// public static T? AncestorOrSelf( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, int maxLevel) where T : class, IPublishedContent => content.AncestorsOrSelf(navigationQueryService, publishedStatusFilteringService, maxLevel).FirstOrDefault(); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static T? AncestorOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, int maxLevel) where T : class, IPublishedContent => content.AncestorOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), maxLevel); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static T? AncestorOrSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int maxLevel) where T : class, IPublishedContent => content.AncestorOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), maxLevel); public static IEnumerable AncestorsOrSelf( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, bool orSelf, Func? func) { IEnumerable ancestorsOrSelf = content.EnumerateAncestors( navigationQueryService, publishedStatusFilteringService, orSelf); return func == null ? ancestorsOrSelf : ancestorsOrSelf.Where(func); } [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable AncestorsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, bool orSelf, Func? func) => content.AncestorsOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), orSelf, func); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable AncestorsOrSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, bool orSelf, Func? func) => content.AncestorsOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), orSelf, func); private static IEnumerable EnumerateAncestors( this IPublishedContent? content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, bool orSelf) { ArgumentNullException.ThrowIfNull(content); return content.EnumerateAncestorsOrSelfInternal(navigationQueryService, publishedStatusFilteringService, orSelf); } #endregion #region Axes: breadcrumbs /// /// Gets the breadcrumbs (ancestors and self, top to bottom) for the specified . /// /// The content. /// The query service for the in-memory navigation structure. /// /// Indicates whether the specified content should be included. /// /// The breadcrumbs (ancestors and self, top to bottom) for the specified . /// public static IEnumerable Breadcrumbs( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, bool andSelf = true) => content.AncestorsOrSelf(navigationQueryService, publishedStatusFilteringService, andSelf, null).Reverse(); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Breadcrumbs( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, bool andSelf = true) => content.Breadcrumbs(navigationQueryService, GetPublishedStatusFilteringService(content), andSelf); /// /// Gets the breadcrumbs (ancestors and self, top to bottom) for the specified at a level /// higher or equal to . /// /// The content. /// The query service for the in-memory navigation structure. /// /// The minimum level. /// Indicates whether the specified content should be included. /// /// The breadcrumbs (ancestors and self, top to bottom) for the specified at a level higher /// or equal to . /// public static IEnumerable Breadcrumbs( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, int minLevel, bool andSelf = true) => content.AncestorsOrSelf(navigationQueryService, publishedStatusFilteringService, andSelf, n => n.Level >= minLevel).Reverse(); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Breadcrumbs( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int minLevel, bool andSelf = true) => content.Breadcrumbs(navigationQueryService, GetPublishedStatusFilteringService(content), minLevel, andSelf); /// /// Gets the breadcrumbs (ancestors and self, top to bottom) for the specified at a level /// higher or equal to the specified root content type . /// /// The root content type. /// The content. /// The query service for the in-memory navigation structure. /// /// Indicates whether the specified content should be included. /// /// The breadcrumbs (ancestors and self, top to bottom) for the specified at a level higher /// or equal to the specified root content type . /// public static IEnumerable Breadcrumbs( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, bool andSelf = true) where T : class, IPublishedContent => content .AncestorsOrSelf(navigationQueryService, publishedStatusFilteringService, andSelf, null) .TakeWhile(n => n is T) .Reverse(); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Breadcrumbs( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, bool andSelf = true) where T : class, IPublishedContent => content.Breadcrumbs(navigationQueryService, GetPublishedStatusFilteringService(content), andSelf); #endregion #region Axes: descendants, descendants-or-self [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelfOfType( this IEnumerable parentNodes, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string docTypeAlias, string? culture = null) { IPublishedContent[] parentNodesAsArray = parentNodes as IPublishedContent[] ?? parentNodes.ToArray(); return parentNodesAsArray.DescendantsOrSelfOfType( navigationQueryService, GetPublishedStatusFilteringService(parentNodesAsArray.First()), docTypeAlias, culture); } [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelfOfType( this IEnumerable parentNodes, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string docTypeAlias, string? culture = null) { IPublishedContent[] parentNodesAsArray = parentNodes as IPublishedContent[] ?? parentNodes.ToArray(); return parentNodesAsArray.DescendantsOrSelfOfType( navigationQueryService, GetPublishedStatusFilteringService(parentNodesAsArray.First()), docTypeAlias, culture); } [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IEnumerable parentNodes, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent { IPublishedContent[] parentNodesAsArray = parentNodes as IPublishedContent[] ?? parentNodes.ToArray(); return parentNodesAsArray.DescendantsOrSelf( navigationQueryService, GetPublishedStatusFilteringService(parentNodesAsArray.First()), culture); } [Obsolete("Use the overload with IPublishStatusQueryService instead, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IEnumerable parentNodes, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string? culture = null) where T : class, IPublishedContent { IPublishedContent[] parentNodesAsArray = parentNodes as IPublishedContent[] ?? parentNodes.ToArray(); return parentNodesAsArray.DescendantsOrSelf( navigationQueryService, GetPublishedStatusFilteringService(parentNodesAsArray.First()), 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 // the descendant axis never contains attribute or namespace nodes. // - the descendant-or-self axis contains the context node and the descendants of the context node. // // as per XPath 2.0 specs �3.2.1.1, // - the descendant axis is defined as the transitive closure of the child axis; it contains the descendants of the context node (the // children, the children of the children, and so on). // - the descendant-or-self axis contains the context node and the descendants of the context node. // // the descendant and descendant-or-self axis are forward axes ie they contain the context node or nodes that are after the context // node in document order. // // document order is defined by �2.4.1 as: // - the root node is the first node. // - every node occurs before all of its children and descendants. // - the relative order of siblings is the order in which they occur in the children property of their parent node. // - children and descendants occur before following siblings. public static IEnumerable Descendants( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string? culture = null) => content.DescendantsOrSelf(navigationQueryService, publishedStatusFilteringService, false, null, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string? culture = null) => content.Descendants(navigationQueryService, GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string? culture = null) => content.Descendants(navigationQueryService, GetPublishedStatusFilteringService(content), culture); public static IEnumerable Descendants( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, int level, string? culture = null) => content.DescendantsOrSelf( navigationQueryService, publishedStatusFilteringService, false, p => p.Level >= level, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, int level, string? culture = null) => content.Descendants(navigationQueryService, GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int level, string? culture = null) => content.Descendants(navigationQueryService, GetPublishedStatusFilteringService(content), level, culture); public static IEnumerable DescendantsOfType( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string contentTypeAlias, string? culture = null) => content.EnumerateDescendantsOrSelfInternal( navigationQueryService, publishedStatusFilteringService, culture, false, contentTypeAlias); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable DescendantsOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias, string? culture = null) => content.DescendantsOfType(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable DescendantsOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string contentTypeAlias, string? culture = null) => content.DescendantsOfType(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias, culture); public static IEnumerable Descendants( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string? culture = null) where T : class, IPublishedContent => content.Descendants(navigationQueryService, publishedStatusFilteringService, culture).OfType(); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent => content.Descendants(navigationQueryService, GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string? culture = null) where T : class, IPublishedContent => content.Descendants(navigationQueryService, GetPublishedStatusFilteringService(content), culture); public static IEnumerable Descendants( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, int level, string? culture = null) where T : class, IPublishedContent => content.Descendants(navigationQueryService, publishedStatusFilteringService, level, culture).OfType(); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] 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(navigationQueryService, GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int level, string? culture = null) where T : class, IPublishedContent => content.Descendants(navigationQueryService, GetPublishedStatusFilteringService(content), level, culture); public static IEnumerable DescendantsOrSelf( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string? culture = null) => content.DescendantsOrSelf(navigationQueryService, publishedStatusFilteringService, true, null, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string? culture = null) => content.DescendantsOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string? culture = null) => content.DescendantsOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), culture); public static IEnumerable DescendantsOrSelf( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, int level, string? culture = null) => content.DescendantsOrSelf(navigationQueryService, publishedStatusFilteringService, true, p => p.Level >= level, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, int level, string? culture = null) => content.DescendantsOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int level, string? culture = null) => content.DescendantsOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), level, culture); public static IEnumerable DescendantsOrSelfOfType( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string contentTypeAlias, string? culture = null) => content.EnumerateDescendantsOrSelfInternal( navigationQueryService, publishedStatusFilteringService, culture, true, contentTypeAlias); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelfOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias, string? culture = null) => content.DescendantsOrSelfOfType(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelfOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string contentTypeAlias, string? culture = null) => content.DescendantsOrSelfOfType(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias, culture); public static IEnumerable DescendantsOrSelf( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string? culture = null) where T : class, IPublishedContent => content.DescendantsOrSelf(navigationQueryService, publishedStatusFilteringService, culture).OfType(); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent => content.DescendantsOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string? culture = null) where T : class, IPublishedContent => content.DescendantsOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), culture); public static IEnumerable DescendantsOrSelf( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, int level, string? culture = null) where T : class, IPublishedContent => content.DescendantsOrSelf(navigationQueryService, publishedStatusFilteringService, level, culture).OfType(); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] 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(navigationQueryService, GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int level, string? culture = null) where T : class, IPublishedContent => content.DescendantsOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), level, culture); public static IPublishedContent? Descendant( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string? culture = null) => content.Children(navigationQueryService, publishedStatusFilteringService, culture)?.FirstOrDefault(); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IPublishedContent? Descendant( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string? culture = null) => content.Descendant(navigationQueryService, GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IPublishedContent? Descendant( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string? culture = null) => content.Descendant(navigationQueryService, GetPublishedStatusFilteringService(content), culture); public static IPublishedContent? Descendant( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, int level, string? culture = null) => content .EnumerateDescendants(navigationQueryService, publishedStatusFilteringService, false, culture) .FirstOrDefault(x => x.Level == level); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IPublishedContent? Descendant( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, int level, string? culture = null) => content.Descendant(navigationQueryService, GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService 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.Descendant(navigationQueryService, GetPublishedStatusFilteringService(content), level, culture); public static IPublishedContent? DescendantOfType( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string contentTypeAlias, string? culture = null) => content .EnumerateDescendantsOrSelfInternal( navigationQueryService, publishedStatusFilteringService, culture, false, contentTypeAlias) .FirstOrDefault(); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IPublishedContent? DescendantOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias, string? culture = null) => content.DescendantOfType(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IPublishedContent? DescendantOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string contentTypeAlias, string? culture = null) => content.DescendantOfType(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias, culture); public static T? Descendant( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string? culture = null) where T : class, IPublishedContent => content .EnumerateDescendants(navigationQueryService, publishedStatusFilteringService, false, culture) .FirstOrDefault(x => x is T) as T; [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static T? Descendant( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent => content.Descendant(navigationQueryService, GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static T? Descendant( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string? culture = null) where T : class, IPublishedContent => content.Descendant(navigationQueryService, GetPublishedStatusFilteringService(content), culture); public static T? Descendant( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, int level, string? culture = null) where T : class, IPublishedContent => content.Descendant(navigationQueryService, publishedStatusFilteringService, level, culture) as T; [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] 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(navigationQueryService, GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static T? Descendant( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int level, string? culture = null) where T : class, IPublishedContent => content.Descendant(navigationQueryService, GetPublishedStatusFilteringService(content), level, culture); public static IPublishedContent DescendantOrSelf( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string? culture = null) => content.EnumerateDescendants( navigationQueryService, publishedStatusFilteringService, true, culture) .FirstOrDefault() ?? content; [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IPublishedContent DescendantOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string? culture = null) => content.DescendantOrSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IPublishedContent DescendantOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null) => content.DescendantOrSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); public static IPublishedContent? DescendantOrSelf( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, int level, string? culture = null) => content .EnumerateDescendants(navigationQueryService, publishedStatusFilteringService, true, culture) .FirstOrDefault(x => x.Level == level); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IPublishedContent? DescendantOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, int level, string? culture = null) => content.DescendantOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IPublishedContent? DescendantOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int level, string? culture = null) => content.DescendantOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), level, culture); public static IPublishedContent? DescendantOrSelfOfType( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string contentTypeAlias, string? culture = null) => content .EnumerateDescendantsOrSelfInternal( navigationQueryService, publishedStatusFilteringService, culture, true, contentTypeAlias) .FirstOrDefault(); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IPublishedContent? DescendantOrSelfOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias, string? culture = null) => content.DescendantOrSelfOfType(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IPublishedContent? DescendantOrSelfOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string contentTypeAlias, string? culture = null) => content.DescendantOrSelfOfType(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias, culture); public static T? DescendantOrSelf( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string? culture = null) where T : class, IPublishedContent => content .EnumerateDescendants(navigationQueryService, publishedStatusFilteringService, true, culture) .FirstOrDefault(x => x is T) as T; [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static T? DescendantOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent => content.DescendantOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static T? DescendantOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string? culture = null) where T : class, IPublishedContent => content.DescendantOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), culture); public static T? DescendantOrSelf( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, int level, string? culture = null) where T : class, IPublishedContent => content.DescendantOrSelf(navigationQueryService, publishedStatusFilteringService, level, culture) as T; [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] 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(navigationQueryService, GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static T? DescendantOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, int level, string? culture = null) where T : class, IPublishedContent => content.DescendantOrSelf(navigationQueryService, GetPublishedStatusFilteringService(content), level, culture); private static IEnumerable DescendantsOrSelf( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, bool orSelf, Func? func, string? culture = null) => content .EnumerateDescendants(navigationQueryService, publishedStatusFilteringService, orSelf, culture) .Where(x => func == null || func(x)); private static IEnumerable EnumerateDescendants( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, bool orSelf, string? culture = null) { ArgumentNullException.ThrowIfNull(content); foreach (IPublishedContent desc in content.EnumerateDescendantsOrSelfInternal( navigationQueryService, publishedStatusFilteringService, culture, orSelf)) { 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string? culture = null) => GetChildren(navigationQueryService, publishedStatusFilteringService, content.Key, null, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable Children( this IPublishedContent content, IVariationContextAccessor? variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string? culture = null) => content.Children(navigationQueryService, GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable Children( this IPublishedContent content, IVariationContextAccessor? variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string? culture = null) => content.Children(navigationQueryService, GetPublishedStatusFilteringService(content), culture); /// /// Gets the children of the content, filtered by a predicate. /// /// The content. /// /// /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, Func predicate, string? culture = null) => content.Children(navigationQueryService, publishedStatusFilteringService, culture).Where(predicate); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable Children( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, Func predicate, string? culture = null) => content.Children(navigationQueryService, GetPublishedStatusFilteringService(content), predicate, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable Children( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, Func predicate, string? culture = null) => content.Children(navigationQueryService, GetPublishedStatusFilteringService(content), predicate, culture); /// /// Gets the children of the content, of any of the specified types. /// /// The content. /// /// /// The content type alias. /// /// The specific culture to filter for. If null is used the current culture is used. (Default is /// null) /// /// The children of the content, of any of the specified types. public static IEnumerable ChildrenOfType( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string? contentTypeAlias, string? culture = null) => contentTypeAlias is not null ? GetChildren(navigationQueryService, publishedStatusFilteringService, content.Key, contentTypeAlias, culture) : []; [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable ChildrenOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string? contentTypeAlias, string? culture = null) => content.ChildrenOfType(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable ChildrenOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string? contentTypeAlias, string? culture = null) => content.ChildrenOfType(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias, culture); /// /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string? culture = null) where T : class, IPublishedContent => content.Children(navigationQueryService, publishedStatusFilteringService, culture).OfType(); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable Children( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent => content.Children(navigationQueryService, GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IEnumerable Children( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string? culture = null) where T : class, IPublishedContent => content.Children(navigationQueryService, GetPublishedStatusFilteringService(content), culture); public static IPublishedContent? FirstChild( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string? culture = null) => content .Children(navigationQueryService, publishedStatusFilteringService, culture) .FirstOrDefault(); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IPublishedContent? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string? culture = null) => content.FirstChild(navigationQueryService, GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IPublishedContent? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string? culture = null) => content.FirstChild(navigationQueryService, GetPublishedStatusFilteringService(content), culture); /// /// Gets the first child of the content, of a given content type. /// public static IPublishedContent? FirstChildOfType( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string contentTypeAlias, string? culture = null) => content .ChildrenOfType(navigationQueryService, publishedStatusFilteringService, contentTypeAlias, culture) .FirstOrDefault(); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IPublishedContent? FirstChildOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias, string? culture = null) => content.FirstChildOfType(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IPublishedContent? FirstChildOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string contentTypeAlias, string? culture = null) => content.FirstChildOfType(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias, culture); public static IPublishedContent? FirstChild( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, Func predicate, string? culture = null) => content .Children(navigationQueryService, publishedStatusFilteringService, predicate, culture) .FirstOrDefault(); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IPublishedContent? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, Func predicate, string? culture = null) => content.FirstChild(navigationQueryService, GetPublishedStatusFilteringService(content), predicate, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IPublishedContent? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, Func predicate, string? culture = null) => content.FirstChild(navigationQueryService, GetPublishedStatusFilteringService(content), predicate, culture); public static IPublishedContent? FirstChild( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, Guid uniqueId, string? culture = null) => content .Children(navigationQueryService, publishedStatusFilteringService, x => x.Key == uniqueId, culture) .FirstOrDefault(); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IPublishedContent? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, Guid uniqueId, string? culture = null) => content.FirstChild(navigationQueryService, GetPublishedStatusFilteringService(content), uniqueId, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static IPublishedContent? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, Guid uniqueId, string? culture = null) => content.FirstChild(navigationQueryService, GetPublishedStatusFilteringService(content), uniqueId, culture); public static T? FirstChild( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string? culture = null) where T : class, IPublishedContent => content .Children(navigationQueryService, publishedStatusFilteringService, culture) .FirstOrDefault(); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static T? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent => content.FirstChild(navigationQueryService, GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static T? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string? culture = null) where T : class, IPublishedContent => content.FirstChild(navigationQueryService, GetPublishedStatusFilteringService(content), culture); public static T? FirstChild( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, Func predicate, string? culture = null) where T : class, IPublishedContent => content .Children(navigationQueryService, publishedStatusFilteringService, culture) .FirstOrDefault(predicate); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] 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.FirstChild(navigationQueryService, GetPublishedStatusFilteringService(content), predicate, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService instead, scheduled for removal in v17")] public static T? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, Func predicate, string? culture = null) where T : class, IPublishedContent => content.FirstChild(navigationQueryService, GetPublishedStatusFilteringService(content), predicate, culture); #endregion #region Axes: siblings /// /// Gets the siblings of the content. /// /// The content. /// The navigation service /// /// /// The specific culture to filter for. If null is used the current culture is used. (Default is /// null) /// /// The siblings of the content. /// /// Note that in V7 this method also return the content node self. /// public static IEnumerable Siblings( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string? culture = null) => content .SiblingsAndSelf(navigationQueryService, publishedStatusFilteringService, culture) .Where(x => x.Id != content.Id); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Siblings( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string? culture = null) => content.Siblings(navigationQueryService, GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Siblings( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IVariationContextAccessor variationContextAccessor, string? culture = null) => content.Siblings(navigationQueryService, GetPublishedStatusFilteringService(content), culture); /// /// Gets the siblings of the content, of a given content type. /// /// The content. /// /// /// /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string contentTypeAlias, string? culture = null) => content .SiblingsAndSelfOfType(navigationQueryService, publishedStatusFilteringService, contentTypeAlias, culture) .Where(x => x.Id != content.Id); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable SiblingsOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias, string? culture = null) => content.SiblingsOfType(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable SiblingsOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string contentTypeAlias, string? culture = null) => content.SiblingsOfType(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias, culture); /// /// Gets the siblings of the content, of a given content type. /// /// The content type. /// The content. /// /// /// /// 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. /// public static IEnumerable Siblings( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string? culture = null) where T : class, IPublishedContent => content .SiblingsAndSelf(navigationQueryService, publishedStatusFilteringService, culture) .Where(x => x.Id != content.Id); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Siblings( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent => content.Siblings(navigationQueryService, GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with IPublishedStatusFilteringService, 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 => content.Siblings(navigationQueryService, GetPublishedStatusFilteringService(content), culture); /// /// Gets the siblings of the content including the node itself to indicate the position. /// /// The content. /// The navigation service. /// /// /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string? culture = null) => content.SiblingsAndSelfInternal(navigationQueryService, publishedStatusFilteringService, null, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable SiblingsAndSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string? culture = null) => content.SiblingsAndSelf(navigationQueryService, GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable SiblingsAndSelf( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IVariationContextAccessor variationContextAccessor, string? culture = null) => content.SiblingsAndSelf(navigationQueryService, GetPublishedStatusFilteringService(content), culture); /// /// Gets the siblings of the content including the node itself to indicate the position, of a given content type. /// /// The content. /// /// /// /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string contentTypeAlias, string? culture = null) => content.SiblingsAndSelfInternal(navigationQueryService, publishedStatusFilteringService, contentTypeAlias, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable SiblingsAndSelfOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias, string? culture = null) => content.SiblingsAndSelfOfType(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable SiblingsAndSelfOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, string contentTypeAlias, string? culture = null) => content.SiblingsAndSelfOfType(navigationQueryService, GetPublishedStatusFilteringService(content), 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. /// /// /// /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string? culture = null) where T : class, IPublishedContent => content .SiblingsAndSelfInternal(navigationQueryService, publishedStatusFilteringService, null, culture) .OfType(); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable SiblingsAndSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent => content.SiblingsAndSelf(navigationQueryService, GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with IPublishedStatusFilteringService, 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 => content.SiblingsAndSelf(navigationQueryService, GetPublishedStatusFilteringService(content), culture); #endregion #region Axes: custom /// /// Gets the root content (ancestor or self at level 1) for the specified . /// /// The content. /// 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService) => content.AncestorOrSelf(navigationQueryService, publishedStatusFilteringService, 1); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent Root( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService) => content.Root(navigationQueryService, GetPublishedStatusFilteringService(content)); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent Root( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService) => content.Root(navigationQueryService, GetPublishedStatusFilteringService(content)); /// /// 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 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, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService) where T : class, IPublishedContent => content.AncestorOrSelf(navigationQueryService, publishedStatusFilteringService, 1); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static T? Root( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IPublishStatusQueryService publishStatusQueryService) where T : class, IPublishedContent => content.Root(navigationQueryService, GetPublishedStatusFilteringService(content)); [Obsolete("Use the overload with IPublishedStatusFilteringService, scheduled for removal in v17")] public static T? Root( this IPublishedContent content, IPublishedCache publishedCache, INavigationQueryService navigationQueryService) where T : class, IPublishedContent => content.Root(navigationQueryService, GetPublishedStatusFilteringService(content)); #endregion #region Writer and creator public static string GetCreatorName(this IPublishedContent content, IUserService userService) { IProfile? user = userService.GetProfileById(content.CreatorId); return user?.Name ?? string.Empty; } public static string GetWriterName(this IPublishedContent content, IUserService userService) { IProfile? user = userService.GetProfileById(content.WriterId); return user?.Name ?? string.Empty; } #endregion #region Axes: children /// /// Gets the children of the content in a DataTable. /// /// The content. /// /// /// The content type service. /// The media type service. /// The member type service. /// The published url provider. /// An optional content type alias. /// /// The specific culture to filter for. If null is used the current culture is used. (Default is /// null) /// /// The children of the content. [Obsolete("This method is no longer used in Umbraco. The method will be removed in Umbraco 17.")] public static DataTable ChildrenAsTable( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, IMemberTypeService memberTypeService, IPublishedUrlProvider publishedUrlProvider, string contentTypeAliasFilter = "", string? culture = null) => content.GenerateDataTable(navigationQueryService, publishedStatusFilteringService, contentTypeService, mediaTypeService, memberTypeService, publishedUrlProvider, contentTypeAliasFilter, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static DataTable ChildrenAsTable( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishedCache publishedCache, INavigationQueryService navigationQueryService, IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, IMemberTypeService memberTypeService, IPublishedUrlProvider publishedUrlProvider, string contentTypeAliasFilter = "", string? culture = null) => content.GenerateDataTable(navigationQueryService, GetPublishedStatusFilteringService(content), contentTypeService, mediaTypeService, memberTypeService, publishedUrlProvider, contentTypeAliasFilter, culture); private static DataTable GenerateDataTable( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, IMemberTypeService memberTypeService, IPublishedUrlProvider publishedUrlProvider, string contentTypeAliasFilter = "", string? culture = null) { IPublishedContent[] children = content.Children(navigationQueryService, publishedStatusFilteringService, culture).ToArray(); IPublishedContent? firstNode = contentTypeAliasFilter.IsNullOrWhiteSpace() ? children.Length > 0 ? children.ElementAt(0) : null : children.FirstOrDefault(x => x.ContentType.Alias.InvariantEquals(contentTypeAliasFilter)); if (firstNode == null) { // No children found return new DataTable(); } // use new utility class to create table so that we don't have to maintain code in many places, just one DataTable dt = DataTableExtensions.GenerateDataTable( // pass in the alias of the first child node since this is the node type we're rendering headers for firstNode.ContentType.Alias, // pass in the callback to extract the Dictionary of all defined aliases to their names alias => GetPropertyAliasesAndNames(contentTypeService, mediaTypeService, memberTypeService, alias), () => { // here we pass in a callback to populate the datatable, yup its a bit ugly but it's already legacy and we just want to maintain code in one place. // create all row data List>, IEnumerable>>> tableData = DataTableExtensions.CreateTableData(); IOrderedEnumerable? children = content.Children(navigationQueryService, publishedStatusFilteringService).OrderBy(x => x.SortOrder); if (children is not null) { // loop through each child and create row data for it foreach (IPublishedContent n in children) { if (contentTypeAliasFilter.IsNullOrWhiteSpace() == false) { if (n.ContentType.Alias.InvariantEquals(contentTypeAliasFilter) == false) { continue; // skip this one, it doesn't match the filter } } var standardVals = new Dictionary { { "Id", n.Id }, { "NodeName", n.Name(null, culture) }, { "NodeTypeAlias", n.ContentType.Alias }, { "CreateDate", n.CreateDate }, { "UpdateDate", n.UpdateDate }, { "CreatorId", n.CreatorId }, { "WriterId", n.WriterId }, { "Url", n.Url(publishedUrlProvider) }, }; var userVals = new Dictionary(); IEnumerable properties = n.Properties?.Where(p => p.GetSourceValue() is not null) ?? Array.Empty(); foreach (IPublishedProperty p in properties) { // probably want the "object value" of the property here... userVals[p.Alias] = p.GetValue(); } // Add the row data DataTableExtensions.AddRowData(tableData, standardVals, userVals); } } return tableData; }); return dt; } #endregion #region PropertyAliasesAndNames private static Func>? _getPropertyAliasesAndNames; /// /// This is used only for unit tests to set the delegate to look up aliases/names dictionary of a content type /// internal static Func> GetPropertyAliasesAndNames { get => _getPropertyAliasesAndNames ?? GetAliasesAndNames; set => _getPropertyAliasesAndNames = value; } private static Dictionary GetAliasesAndNames(IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, IMemberTypeService memberTypeService, string alias) { IContentTypeBase? type = contentTypeService.Get(alias) ?? mediaTypeService.Get(alias) ?? (IContentTypeBase?)memberTypeService.Get(alias); Dictionary fields = GetAliasesAndNames(type); // ensure the standard fields are there var stdFields = new Dictionary { { "Id", "Id" }, { "NodeName", "NodeName" }, { "NodeTypeAlias", "NodeTypeAlias" }, { "CreateDate", "CreateDate" }, { "UpdateDate", "UpdateDate" }, { "CreatorId", "CreatorId" }, { "WriterId", "WriterId" }, { "Url", "Url" }, }; foreach (KeyValuePair field in stdFields) { fields.TryAdd(field.Key, field.Value); } return fields; } private static Dictionary GetAliasesAndNames(IContentTypeBase? contentType) => contentType?.PropertyTypes.ToDictionary(x => x.Alias, x => x.Name) ?? new Dictionary(); #endregion public static IPublishedContent? Ancestor(this IPublishedContent content, int maxLevel) => content.Ancestor(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), maxLevel); public static IPublishedContent? Ancestor(this IPublishedContent content, string contentTypeAlias) => content.Ancestor(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), contentTypeAlias); public static T? Ancestor(this IPublishedContent content, int maxLevel) where T : class, IPublishedContent => content.Ancestor(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), maxLevel); public static IEnumerable Ancestors(this IPublishedContent content, int maxLevel) => content.Ancestors(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), maxLevel); public static IEnumerable Ancestors(this IPublishedContent content, string contentTypeAlias) => content.Ancestors(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), contentTypeAlias); public static IEnumerable Ancestors(this IPublishedContent content) where T : class, IPublishedContent => content.Ancestors(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content)); public static IEnumerable Ancestors(this IPublishedContent content, int maxLevel) where T : class, IPublishedContent => content.Ancestors(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), maxLevel); public static IPublishedContent AncestorOrSelf(this IPublishedContent content, int maxLevel) => content.AncestorOrSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), maxLevel); public static IPublishedContent AncestorOrSelf(this IPublishedContent content, string contentTypeAlias) => content.AncestorOrSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), contentTypeAlias); public static T? AncestorOrSelf(this IPublishedContent content, int maxLevel) where T : class, IPublishedContent => content.AncestorOrSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), maxLevel); public static IEnumerable AncestorsOrSelf(this IPublishedContent content, int maxLevel) => content.AncestorsOrSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), maxLevel); public static IEnumerable AncestorsOrSelf(this IPublishedContent content, string contentTypeAlias) => content.Ancestors(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), contentTypeAlias); public static IEnumerable AncestorsOrSelf(this IPublishedContent content, int maxLevel) where T : class, IPublishedContent => content.AncestorsOrSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), maxLevel); public static IEnumerable AncestorsOrSelf(this IPublishedContent content, bool orSelf, Func? func) => content.AncestorsOrSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), orSelf, func); public static IEnumerable Breadcrumbs( this IPublishedContent content, bool andSelf = true) => content.Breadcrumbs(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), andSelf); public static IEnumerable Breadcrumbs( this IPublishedContent content, int minLevel, bool andSelf = true) => content.Breadcrumbs(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), minLevel, andSelf); public static IEnumerable Breadcrumbs( this IPublishedContent content, bool andSelf = true) where T : class, IPublishedContent=> content.Breadcrumbs(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), andSelf); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Children( this IPublishedContent content, IVariationContextAccessor? variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string? culture = null) => content.Children(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Children( this IPublishedContent content, IVariationContextAccessor? variationContextAccessor, string? culture = null) => content.Children(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Children( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, Func predicate, string? culture = null) => content.Children(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), predicate, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Children( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, Func predicate, string? culture = null) => content.Children(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), predicate, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable ChildrenOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string? contentTypeAlias, string? culture = null) => content.ChildrenOfType(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable ChildrenOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? contentTypeAlias, string? culture = null) => content.ChildrenOfType(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Children( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent => content.Children(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Children( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null) where T : class, IPublishedContent => content.Children(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("This method is no longer used in Umbraco. The method will be removed in Umbraco 17.")] public static DataTable ChildrenAsTable( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, IMemberTypeService memberTypeService, IPublishedUrlProvider publishedUrlProvider, string contentTypeAliasFilter = "", string? culture = null) => content.GenerateDataTable(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), contentTypeService, mediaTypeService, memberTypeService, publishedUrlProvider, contentTypeAliasFilter, culture); public static IEnumerable DescendantsOrSelfOfType( this IEnumerable parentNodes, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string docTypeAlias, string? culture = null) => parentNodes.SelectMany(x => x.DescendantsOrSelfOfType( navigationQueryService, publishedStatusFilteringService, docTypeAlias, culture)); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelfOfType( this IEnumerable parentNodes, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string docTypeAlias, string? culture = null) { IPublishedContent[] parentNodesAsArray = parentNodes as IPublishedContent[] ?? parentNodes.ToArray(); return parentNodesAsArray.DescendantsOrSelfOfType( GetNavigationQueryService(parentNodesAsArray.First()), GetPublishedStatusFilteringService(parentNodesAsArray.First()), docTypeAlias, culture); } [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelfOfType( this IEnumerable parentNodes, IVariationContextAccessor variationContextAccessor, string docTypeAlias, string? culture = null) { IPublishedContent[] parentNodesAsArray = parentNodes as IPublishedContent[] ?? parentNodes.ToArray(); return parentNodesAsArray.DescendantsOrSelfOfType( GetNavigationQueryService(parentNodesAsArray.First()), GetPublishedStatusFilteringService(parentNodesAsArray.First()), docTypeAlias, culture); } public static IEnumerable DescendantsOrSelf( this IEnumerable parentNodes, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string? culture = null) where T : class, IPublishedContent => parentNodes.SelectMany(x => x.DescendantsOrSelf( navigationQueryService, publishedStatusFilteringService, culture)); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IEnumerable parentNodes, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent { IPublishedContent[] parentNodesAsArray = parentNodes as IPublishedContent[] ?? parentNodes.ToArray(); return parentNodesAsArray.DescendantsOrSelf( GetNavigationQueryService(parentNodesAsArray.First()), GetPublishedStatusFilteringService(parentNodesAsArray.First()), culture); } [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IEnumerable parentNodes, IVariationContextAccessor variationContextAccessor, string? culture = null) where T : class, IPublishedContent { IPublishedContent[] parentNodesAsArray = parentNodes as IPublishedContent[] ?? parentNodes.ToArray(); return parentNodesAsArray.DescendantsOrSelf( GetNavigationQueryService(parentNodesAsArray.First()), GetPublishedStatusFilteringService(parentNodesAsArray.First()), culture); } [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string? culture = null) => content.Descendants(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null) => content.Descendants(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, int level, string? culture = null) => content.Descendants(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string? culture = null) => content.Descendants(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable DescendantsOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias, string? culture = null) => content.DescendantsOfType(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable DescendantsOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string? culture = null) => content.DescendantsOfType(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent => content.Descendants(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null) where T : class, IPublishedContent => content.Descendants(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, int level, string? culture = null) where T : class, IPublishedContent => content.Descendants(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Descendants( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string? culture = null) where T : class, IPublishedContent => content.Descendants(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string? culture = null) => content.DescendantsOrSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null) => content.DescendantsOrSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, int level, string? culture = null) => content.DescendantsOrSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string? culture = null) => content.DescendantsOrSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelfOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias, string? culture = null) => content.DescendantsOrSelfOfType(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelfOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string? culture = null) => content.DescendantsOrSelfOfType(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent => content.DescendantsOrSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null) where T : class, IPublishedContent => content.DescendantsOrSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, int level, string? culture = null) where T : class, IPublishedContent => content.DescendantsOrSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable DescendantsOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string? culture = null) where T : class, IPublishedContent => content.DescendantsOrSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? Descendant( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string? culture = null) => content.Descendant(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? Descendant( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null) => content.Descendant(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? Descendant( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, int level, string? culture = null) => content.Descendant(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? Descendant( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string? culture = null) => content.Descendant(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? DescendantOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias, string? culture = null) => content.DescendantOfType(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? DescendantOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string? culture = null) => content.DescendantOfType(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static T? Descendant( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent => content.Descendant(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static T? Descendant( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null) where T : class, IPublishedContent => content.Descendant(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static T? Descendant( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, int level, string? culture = null) where T : class, IPublishedContent => content.Descendant(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, 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(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? DescendantOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, int level, string? culture = null) => content.DescendantOrSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? DescendantOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string? culture = null) => content.DescendantOrSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? DescendantOrSelfOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias, string? culture = null) => content.DescendantOrSelfOfType(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? DescendantOrSelfOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string? culture = null) => content.DescendantOrSelfOfType(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static T? DescendantOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent => content.DescendantOrSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static T? DescendantOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null) where T : class, IPublishedContent => content.DescendantOrSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static T? DescendantOrSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, int level, string? culture = null) where T : class, IPublishedContent => content.DescendantOrSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, 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(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), level, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string? culture = null) => content.FirstChild(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null) => content.FirstChild(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? FirstChildOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string contentTypeAlias, string? culture = null) => content.FirstChildOfType(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? FirstChildOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string? culture = null) => content.FirstChildOfType(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, Func predicate, string? culture = null) => content.FirstChild(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), predicate, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, Func predicate, string? culture = null) => content.FirstChild(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), predicate, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, Guid uniqueId, string? culture = null) => content.FirstChild(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), uniqueId, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IPublishedContent? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, Guid uniqueId, string? culture = null) => content.FirstChild(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), uniqueId, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static T? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent => content.FirstChild(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static T? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null) where T : class, IPublishedContent => content.FirstChild(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static T? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, Func predicate, string? culture = null) where T : class, IPublishedContent => content.FirstChild(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), predicate, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static T? FirstChild( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, Func predicate, string? culture = null) where T : class, IPublishedContent => content.FirstChild(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), predicate, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Siblings( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null) => content.Siblings(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable SiblingsOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string? culture = null) => content.SiblingsOfType(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable Siblings( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null) where T : class, IPublishedContent => content.Siblings(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable? SiblingsAndSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null) => content.SiblingsAndSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable SiblingsAndSelfOfType( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string? culture = null) => content.SiblingsAndSelfOfType(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), contentTypeAlias, culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable SiblingsAndSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, string? culture = null) where T : class, IPublishedContent => content.SiblingsAndSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); [Obsolete("Use the overload with INavigationQueryService and IPublishedStatusFilteringService, scheduled for removal in v17")] public static IEnumerable SiblingsAndSelf( this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null) where T : class, IPublishedContent => content.SiblingsAndSelf(GetNavigationQueryService(content), GetPublishedStatusFilteringService(content), culture); private static INavigationQueryService GetNavigationQueryService(IPublishedContent content) { switch (content.ItemType) { case PublishedItemType.Content: return StaticServiceProvider.Instance.GetRequiredService(); case PublishedItemType.Media: return StaticServiceProvider.Instance.GetRequiredService(); default: throw new NotSupportedException("Unsupported content type."); } } private static IPublishedStatusFilteringService GetPublishedStatusFilteringService(IPublishedContent content) { switch (content.ItemType) { case PublishedItemType.Content: return StaticServiceProvider.Instance.GetRequiredService(); case PublishedItemType.Media: return StaticServiceProvider.Instance.GetRequiredService(); default: throw new NotSupportedException("Unsupported content type."); } } private static IEnumerable GetChildren( INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, Guid parentKey, string? contentTypeAlias = null, string? culture = null) { var nodeExists = contentTypeAlias is null ? navigationQueryService.TryGetChildrenKeys(parentKey, out IEnumerable childrenKeys) : navigationQueryService.TryGetChildrenKeysOfType(parentKey, contentTypeAlias, out childrenKeys); if (nodeExists is false) { 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. return publishedStatusFilteringService .FilterAvailable(childrenKeys, culture) .OrderBy(x => x.SortOrder); } private static IEnumerable EnumerateDescendantsOrSelfInternal( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string? culture, bool orSelf, string? contentTypeAlias = null) { if (orSelf) { if (contentTypeAlias is null || content.ContentType.Alias == contentTypeAlias) { yield return content; } } var nodeExists = contentTypeAlias is null ? navigationQueryService.TryGetDescendantsKeys(content.Key, out IEnumerable descendantsKeys) : navigationQueryService.TryGetDescendantsKeysOfType(content.Key, contentTypeAlias, out descendantsKeys); if (nodeExists is false) { yield break; } IEnumerable descendants = publishedStatusFilteringService .FilterAvailable(descendantsKeys, culture); foreach (IPublishedContent descendant in descendants) { yield return descendant; } } private static IEnumerable EnumerateAncestorsOrSelfInternal( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, bool orSelf, string? contentTypeAlias = null, string? culture = null) { if (orSelf) { if (contentTypeAlias is null || content.ContentType.Alias == contentTypeAlias) { yield return content; } } var nodeExists = contentTypeAlias is null ? navigationQueryService.TryGetAncestorsKeys(content.Key, out IEnumerable ancestorsKeys) : navigationQueryService.TryGetAncestorsKeysOfType(content.Key, contentTypeAlias, out ancestorsKeys); if (nodeExists is false) { yield break; } IEnumerable ancestors = publishedStatusFilteringService.FilterAvailable(ancestorsKeys, culture); foreach (IPublishedContent ancestor in ancestors) { yield return ancestor; } } private static IEnumerable SiblingsAndSelfInternal( this IPublishedContent content, INavigationQueryService navigationQueryService, IPublishedStatusFilteringService publishedStatusFilteringService, string? contentTypeAlias, string? culture) { if (navigationQueryService.TryGetParentKey(content.Key, out Guid? parentKey) is false) { return []; } if (parentKey.HasValue) { var foundChildrenKeys = contentTypeAlias is null ? navigationQueryService.TryGetChildrenKeys(parentKey.Value, out IEnumerable childrenKeys) : navigationQueryService.TryGetChildrenKeysOfType(parentKey.Value, contentTypeAlias, out childrenKeys); return foundChildrenKeys ? publishedStatusFilteringService.FilterAvailable(childrenKeys, culture) : []; } var foundRootKeys = contentTypeAlias is null ? navigationQueryService.TryGetRootKeys(out IEnumerable rootKeys) : navigationQueryService.TryGetRootKeysOfType(contentTypeAlias, out rootKeys); return foundRootKeys ? publishedStatusFilteringService.FilterAvailable(rootKeys, culture) : []; } }