Add DefaultLanguage fallback policy for published values (#13814)

* Add DefaultLanguage fallback

* Implement DefaultLanguage fallback

* Add DefaultLanguage fallback test
This commit is contained in:
Ronald Barendse
2023-02-13 14:50:41 +01:00
committed by GitHub
parent bbc8ade227
commit 7348171c01
3 changed files with 105 additions and 11 deletions

View File

@@ -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 />

View File

@@ -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;
}
}

View File

@@ -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()
{