Add DefaultLanguage fallback policy for published values (#13814)
* Add DefaultLanguage fallback * Implement DefaultLanguage fallback * Add DefaultLanguage fallback test
This commit is contained in:
@@ -3,56 +3,82 @@ using System.Collections;
|
||||
namespace Umbraco.Cms.Core.Models.PublishedContent;
|
||||
|
||||
/// <summary>
|
||||
/// Manages the built-in fallback policies.
|
||||
/// Manages the built-in fallback policies.
|
||||
/// </summary>
|
||||
public struct Fallback : IEnumerable<int>
|
||||
{
|
||||
/// <summary>
|
||||
/// Do not fallback.
|
||||
/// Do not fallback.
|
||||
/// </summary>
|
||||
public const int None = 0;
|
||||
|
||||
private readonly int[] _values;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Fallback" /> struct with values.
|
||||
/// Initializes a new instance of the <see cref="Fallback" /> struct with values.
|
||||
/// </summary>
|
||||
/// <param name="values">The values.</param>
|
||||
private Fallback(int[] values) => _values = values;
|
||||
|
||||
/// <summary>
|
||||
/// Gets an ordered set of fallback policies.
|
||||
/// Gets an ordered set of fallback policies.
|
||||
/// </summary>
|
||||
/// <param name="values"></param>
|
||||
/// <param name="values">The values.</param>
|
||||
/// <returns>
|
||||
/// The fallback policy.
|
||||
/// </returns>
|
||||
public static Fallback To(params int[] values) => new(values);
|
||||
|
||||
/// <summary>
|
||||
/// Fallback to default value.
|
||||
/// Fallback to the default value.
|
||||
/// </summary>
|
||||
public const int DefaultValue = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Fallback to other languages.
|
||||
/// Fallback to other languages.
|
||||
/// </summary>
|
||||
public const int Language = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Fallback to tree ancestors.
|
||||
/// Fallback to tree ancestors.
|
||||
/// </summary>
|
||||
public const int Ancestors = 3;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the fallback to default value policy.
|
||||
/// Fallback to the default language.
|
||||
/// </summary>
|
||||
public const int DefaultLanguage = 4;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the fallback to the default language policy.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default language fallback policy.
|
||||
/// </value>
|
||||
public static Fallback ToDefaultLanguage => new Fallback(new[] { DefaultLanguage });
|
||||
|
||||
/// <summary>
|
||||
/// Gets the fallback to the default value policy.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default value fallback policy.
|
||||
/// </value>
|
||||
public static Fallback ToDefaultValue => new(new[] { DefaultValue });
|
||||
|
||||
/// <summary>
|
||||
/// Gets the fallback to language policy.
|
||||
/// Gets the fallback to language policy.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The language fallback policy.
|
||||
/// </value>
|
||||
public static Fallback ToLanguage => new(new[] { Language });
|
||||
|
||||
/// <summary>
|
||||
/// Gets the fallback to tree ancestors policy.
|
||||
/// Gets the fallback to tree ancestors policy.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The tree ancestors fallback policy.
|
||||
/// </value>
|
||||
public static Fallback ToAncestors => new(new[] { Ancestors });
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -44,6 +44,13 @@ public class PublishedValueFallback : IPublishedValueFallback
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
case Fallback.DefaultLanguage:
|
||||
if (TryGetValueWithDefaultLanguageFallback(property, culture, segment, out value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
throw NotSupportedFallbackMethod(f, "property");
|
||||
@@ -85,6 +92,13 @@ public class PublishedValueFallback : IPublishedValueFallback
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
case Fallback.DefaultLanguage:
|
||||
if (TryGetValueWithDefaultLanguageFallback(content, alias, culture, segment, out value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
throw NotSupportedFallbackMethod(f, "element");
|
||||
@@ -141,6 +155,13 @@ public class PublishedValueFallback : IPublishedValueFallback
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
case Fallback.DefaultLanguage:
|
||||
if (TryGetValueWithDefaultLanguageFallback(content, alias, culture, segment, out value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
throw NotSupportedFallbackMethod(f, "content");
|
||||
@@ -347,4 +368,42 @@ public class PublishedValueFallback : IPublishedValueFallback
|
||||
language = language2;
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryGetValueWithDefaultLanguageFallback<T>(IPublishedProperty property, string? culture, string? segment, out T? value)
|
||||
{
|
||||
value = default;
|
||||
|
||||
if (culture.IsNullOrWhiteSpace())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string? defaultCulture = _localizationService?.GetDefaultLanguageIsoCode();
|
||||
if (culture.InvariantEquals(defaultCulture) == false && property.HasValue(defaultCulture, segment))
|
||||
{
|
||||
value = property.Value<T>(this, defaultCulture, segment);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryGetValueWithDefaultLanguageFallback<T>(IPublishedElement element, string alias, string? culture, string? segment, out T? value)
|
||||
{
|
||||
value = default;
|
||||
|
||||
if (culture.IsNullOrWhiteSpace())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string? defaultCulture = _localizationService?.GetDefaultLanguageIsoCode();
|
||||
if (culture.InvariantEquals(defaultCulture) == false && element.HasValue(alias, defaultCulture, segment))
|
||||
{
|
||||
value = element.Value<T>(this, alias, defaultCulture, segment);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,6 +242,15 @@ public class PublishedContentLanguageVariantTests : PublishedSnapshotServiceTest
|
||||
Assert.IsNull(value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Get_Content_For_Unpopulated_Requested_DefaultLanguage_With_Fallback()
|
||||
{
|
||||
var snapshot = GetPublishedSnapshot();
|
||||
var content = snapshot.Content.GetAtRoot().First();
|
||||
var value = content.Value(PublishedValueFallback, "welcomeText", "fr", fallback: Fallback.ToDefaultLanguage);
|
||||
Assert.AreEqual("Welcome", value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Do_Not_Get_Content_Recursively_Unless_Requested()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user