Publish invariant properties (#12386)
* Publish invariants from non default * Add culture impact service * Use the new culture impact service instead of newing up culture impacts * Only publish invariant properties on non-defaults with invariant culture Essentially we want to be able to fall back to the default culture for the variant properties if a document type is made invariant, not whatever culture was published last. * Move creation logic into the service * Make creation method names consistent * Fix tests We compare the cultures directly, so they have to be the same object instance unfortunately * Add test for the new setting * Add new config to server variables * Fix test setup * Apply suggestions from code review Co-authored-by: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com> Co-authored-by: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com>
This commit is contained in:
@@ -235,51 +235,67 @@ namespace Umbraco.Extensions
|
||||
/// culture(s). The method may fail if required names are not set, but it does NOT validate property data</returns>
|
||||
public static bool PublishCulture(this IContent content, CultureImpact? impact)
|
||||
{
|
||||
if (impact == null) throw new ArgumentNullException(nameof(impact));
|
||||
if (impact == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(impact));
|
||||
}
|
||||
|
||||
// the variation should be supported by the content type properties
|
||||
// if the content type is invariant, only '*' and 'null' is ok
|
||||
// if the content type varies, everything is ok because some properties may be invariant
|
||||
if (!content.ContentType.SupportsPropertyVariation(impact.Culture, "*", true))
|
||||
{
|
||||
throw new NotSupportedException($"Culture \"{impact.Culture}\" is not supported by content type \"{content.ContentType.Alias}\" with variation \"{content.ContentType.Variations}\".");
|
||||
}
|
||||
|
||||
// set names
|
||||
if (impact.ImpactsAllCultures)
|
||||
{
|
||||
foreach (var c in content.AvailableCultures) // does NOT contain the invariant culture
|
||||
foreach (var culture in content.AvailableCultures) // does NOT contain the invariant culture
|
||||
{
|
||||
var name = content.GetCultureName(c);
|
||||
var name = content.GetCultureName(culture);
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
return false;
|
||||
content.SetPublishInfo(c, name, DateTime.Now);
|
||||
}
|
||||
|
||||
content.SetPublishInfo(culture, name, DateTime.Now);
|
||||
}
|
||||
}
|
||||
else if (impact.ImpactsOnlyInvariantCulture)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(content.Name))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// PublishName set by repository - nothing to do here
|
||||
}
|
||||
else if (impact.ImpactsExplicitCulture)
|
||||
{
|
||||
var name = content.GetCultureName(impact.Culture);
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
content.SetPublishInfo(impact.Culture, name, DateTime.Now);
|
||||
}
|
||||
|
||||
// set values
|
||||
// property.PublishValues only publishes what is valid, variation-wise,
|
||||
// but accepts any culture arg: null, all, specific
|
||||
foreach (var property in content.Properties)
|
||||
foreach (IProperty property in content.Properties)
|
||||
{
|
||||
// for the specified culture (null or all or specific)
|
||||
property.PublishValues(impact.Culture);
|
||||
|
||||
// maybe the specified culture did not impact the invariant culture, so PublishValues
|
||||
// above would skip it, yet it *also* impacts invariant properties
|
||||
if (impact.ImpactsAlsoInvariantProperties)
|
||||
if (impact.ImpactsAlsoInvariantProperties &&
|
||||
(property.PropertyType.VariesByCulture() is false || impact.ImpactsOnlyDefaultCulture))
|
||||
{
|
||||
property.PublishValues(null);
|
||||
}
|
||||
}
|
||||
|
||||
content.PublishedState = PublishedState.Publishing;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Umbraco.Extensions;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Core.Models
|
||||
{
|
||||
@@ -21,6 +19,7 @@ namespace Umbraco.Cms.Core.Models
|
||||
/// <param name="savingCultures"></param>
|
||||
/// <param name="defaultCulture"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Use CultureImpactService instead, scheduled for removal in v12")]
|
||||
public static string? GetCultureForInvariantErrors(IContent? content, string?[] savingCultures, string? defaultCulture)
|
||||
{
|
||||
if (content == null) throw new ArgumentNullException(nameof(content));
|
||||
@@ -42,17 +41,24 @@ namespace Umbraco.Cms.Core.Models
|
||||
/// </summary>
|
||||
/// <param name="culture">The culture code.</param>
|
||||
/// <param name="isDefault">A value indicating whether the culture is the default culture.</param>
|
||||
private CultureImpact(string? culture, bool isDefault = false)
|
||||
/// <param name="allowEditInvariantFromNonDefault">A value indicating if publishing invariant properties from non-default language.</param>
|
||||
internal CultureImpact(string? culture, bool isDefault = false, bool allowEditInvariantFromNonDefault = false)
|
||||
{
|
||||
if (culture != null && culture.IsNullOrWhiteSpace())
|
||||
{
|
||||
throw new ArgumentException("Culture \"\" is not valid here.");
|
||||
}
|
||||
|
||||
Culture = culture;
|
||||
|
||||
if ((culture == null || culture == "*") && isDefault)
|
||||
{
|
||||
throw new ArgumentException("The invariant or 'all' culture can not be the default culture.");
|
||||
}
|
||||
|
||||
ImpactsOnlyDefaultCulture = isDefault;
|
||||
|
||||
AllowEditInvariantFromNonDefault = allowEditInvariantFromNonDefault;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -70,14 +76,24 @@ namespace Umbraco.Cms.Core.Models
|
||||
/// </summary>
|
||||
/// <param name="culture">The culture code.</param>
|
||||
/// <param name="isDefault">A value indicating whether the culture is the default culture.</param>
|
||||
/// <param name="allowEditInvariantFromNonDefault">A value indicating if publishing invariant properties from non-default language.</param>
|
||||
[Obsolete("Use ICultureImpactService instead.")]
|
||||
public static CultureImpact Explicit(string? culture, bool isDefault)
|
||||
{
|
||||
if (culture == null)
|
||||
{
|
||||
throw new ArgumentException("Culture <null> is not explicit.");
|
||||
}
|
||||
|
||||
if (culture.IsNullOrWhiteSpace())
|
||||
{
|
||||
throw new ArgumentException("Culture \"\" is not explicit.");
|
||||
}
|
||||
|
||||
if (culture == "*")
|
||||
{
|
||||
throw new ArgumentException("Culture \"*\" is not explicit.");
|
||||
}
|
||||
|
||||
return new CultureImpact(culture, isDefault);
|
||||
}
|
||||
@@ -89,13 +105,15 @@ namespace Umbraco.Cms.Core.Models
|
||||
/// <param name="culture">The culture code.</param>
|
||||
/// <param name="isDefault">A value indicating whether the culture is the default culture.</param>
|
||||
/// <param name="content">The content item.</param>
|
||||
/// <param name="allowEditInvariantFromNonDefault">A value indicating if publishing invariant properties from non-default language.</param>
|
||||
/// <remarks>
|
||||
/// <para>Validates that the culture is compatible with the variation.</para>
|
||||
/// </remarks>
|
||||
[Obsolete("Use ICultureImpactService instead, scheduled for removal in V12")]
|
||||
public static CultureImpact? Create(string culture, bool isDefault, IContent content)
|
||||
{
|
||||
// throws if not successful
|
||||
TryCreate(culture, isDefault, content.ContentType.Variations, true, out var impact);
|
||||
TryCreate(culture, isDefault, content.ContentType.Variations, true, false, out CultureImpact? impact);
|
||||
return impact;
|
||||
}
|
||||
|
||||
@@ -107,12 +125,14 @@ namespace Umbraco.Cms.Core.Models
|
||||
/// <param name="isDefault">A value indicating whether the culture is the default culture.</param>
|
||||
/// <param name="variation">A content variation.</param>
|
||||
/// <param name="throwOnFail">A value indicating whether to throw if the impact cannot be created.</param>
|
||||
/// <param name="editInvariantFromNonDefault">A value indicating if publishing invariant properties from non-default language.</param>
|
||||
/// <param name="impact">The impact if it could be created, otherwise null.</param>
|
||||
/// <returns>A value indicating whether the impact could be created.</returns>
|
||||
/// <remarks>
|
||||
/// <para>Validates that the culture is compatible with the variation.</para>
|
||||
/// </remarks>
|
||||
internal static bool TryCreate(string culture, bool isDefault, ContentVariation variation, bool throwOnFail, out CultureImpact? impact)
|
||||
// TODO: Remove this once Create() can be removed (V12), this already lives in CultureImpactService
|
||||
internal static bool TryCreate(string culture, bool isDefault, ContentVariation variation, bool throwOnFail, bool editInvariantFromNonDefault, out CultureImpact? impact)
|
||||
{
|
||||
impact = null;
|
||||
|
||||
@@ -172,7 +192,7 @@ namespace Umbraco.Cms.Core.Models
|
||||
}
|
||||
|
||||
// return specific impact
|
||||
impact = new CultureImpact(culture, isDefault);
|
||||
impact = new CultureImpact(culture, isDefault, editInvariantFromNonDefault);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -184,6 +204,8 @@ namespace Umbraco.Cms.Core.Models
|
||||
/// </remarks>
|
||||
public string? Culture { get; }
|
||||
|
||||
public bool AllowEditInvariantFromNonDefault { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this impact impacts all cultures, including,
|
||||
/// indirectly, the invariant culture.
|
||||
@@ -222,7 +244,7 @@ namespace Umbraco.Cms.Core.Models
|
||||
/// </summary>
|
||||
public bool ImpactsAlsoInvariantProperties => !ImpactsOnlyInvariantCulture &&
|
||||
!ImpactsAllCultures &&
|
||||
ImpactsOnlyDefaultCulture;
|
||||
(ImpactsOnlyDefaultCulture || AllowEditInvariantFromNonDefault);
|
||||
|
||||
public Behavior CultureBehavior
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user