using System; using System.Collections.Generic; using System.Linq; using Umbraco.Core.Composing; using Umbraco.Core.Models.PublishedContent; namespace Umbraco.Core { public static class PublishedContentExtensions { private static IVariationContextAccessor VariationContextAccessor => Current.VariationContextAccessor; /// /// Determines whether the content has a culture. /// /// Culture is case-insensitive. public static bool HasCulture(this IPublishedContent content, string culture) => 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 ?? ""); /// /// Filters a sequence of to return invariant items, and items that are published for the specified culture. /// /// The content items. /// The specific culture to filter for. If null is used the current culture is used. (Default is null). internal static IEnumerable WhereIsInvariantOrHasCulture(this IEnumerable contents, string culture = null) where T : class, IPublishedContent { if (contents == null) throw new ArgumentNullException(nameof(contents)); culture = culture ?? Current.VariationContextAccessor.VariationContext?.Culture ?? ""; // either does not vary by culture, or has the specified culture return contents.Where(x => !x.ContentType.VariesByCulture() || HasCulture(x, culture)); } /// /// 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, string culture = null) { // invariant has invariant value (whatever the requested culture) if (!content.ContentType.VariesByCulture()) return content.Cultures.TryGetValue("", out var invariantInfos) ? invariantInfos.Name : null; // handle context culture for variant if (culture == null) culture = VariationContextAccessor?.VariationContext?.Culture ?? ""; // get return culture != "" && content.Cultures.TryGetValue(culture, out var infos) ? infos.Name : null; } /// /// 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). public static string UrlSegment(this IPublishedContent content, string culture = null) { // invariant has invariant value (whatever the requested culture) if (!content.ContentType.VariesByCulture()) return content.Cultures.TryGetValue("", out var invariantInfos) ? invariantInfos.UrlSegment : null; // handle context culture for variant if (culture == null) culture = VariationContextAccessor?.VariationContext?.Culture ?? ""; // get return culture != "" && content.Cultures.TryGetValue(culture, out var infos) ? infos.UrlSegment : null; } /// /// 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, 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 ?? ""; // get return culture != "" && content.Cultures.TryGetValue(culture, out var infos) ? infos.Date : DateTime.MinValue; } /// /// 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, string culture = null) { // handle context culture for variant if (culture == null) culture = VariationContextAccessor?.VariationContext?.Culture ?? ""; var children = content.ChildrenForAllCultures; return culture == "*" ? children : children.Where(x => x.IsInvariantOrHasCulture(culture)); } } }