Files
Umbraco-CMS/src/Umbraco.Infrastructure/Compose/NestedContentPropertyComponent.cs
Mole bf41c2eeaa Netcore: Align namespaces (#9801)
* Rename Umbraco.Core namespace to Umbraco.Cms.Core

* Move extension methods in core project to Umbraco.Extensions

* Move extension methods in core project to Umbraco.Extensions

* Rename Umbraco.Examine namespace to Umbraco.Cms.Examine

* Move examine extensions to Umbraco.Extensions namespace

* Reflect changed namespaces in Builder and fix unit tests

* Adjust namespace in Umbraco.ModelsBuilder.Embedded

* Adjust namespace in Umbraco.Persistence.SqlCe

* Adjust namespace in Umbraco.PublishedCache.NuCache

* Align namespaces in Umbraco.Web.BackOffice

* Align namespaces in Umbraco.Web.Common

* Ensure that SqlCeSupport is still enabled after changing the namespace

* Align namespaces in Umbraco.Web.Website

* Align namespaces in Umbraco.Web.UI.NetCore

* Align namespaces in Umbraco.Tests.Common

* Align namespaces in Umbraco.Tests.UnitTests

* Align namespaces in Umbraco.Tests.Integration

* Fix errors caused by changed namespaces

* Fix integration tests

* Undo the Umbraco.Examine.Lucene namespace change

This breaks integration tests on linux, since the namespace wont exists there because it's only used on windows.

* Fix merge

* Fix Merge
2021-02-18 11:06:02 +01:00

84 lines
3.3 KiB
C#

using System;
using System.Linq;
using Newtonsoft.Json.Linq;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.PropertyEditors;
using Umbraco.Extensions;
namespace Umbraco.Cms.Core.Compose
{
/// <summary>
/// A component for NestedContent used to bind to events
/// </summary>
public class NestedContentPropertyComponent : IComponent
{
private ComplexPropertyEditorContentEventHandler _handler;
public void Initialize()
{
_handler = new ComplexPropertyEditorContentEventHandler(
Constants.PropertyEditors.Aliases.NestedContent,
CreateNestedContentKeys);
}
public void Terminate() => _handler?.Dispose();
private string CreateNestedContentKeys(string rawJson, bool onlyMissingKeys) => CreateNestedContentKeys(rawJson, onlyMissingKeys, null);
// internal for tests
internal string CreateNestedContentKeys(string rawJson, bool onlyMissingKeys, Func<Guid> createGuid = null)
{
// used so we can test nicely
if (createGuid == null)
createGuid = () => Guid.NewGuid();
if (string.IsNullOrWhiteSpace(rawJson) || !rawJson.DetectIsJson())
return rawJson;
// Parse JSON
var complexEditorValue = JToken.Parse(rawJson);
UpdateNestedContentKeysRecursively(complexEditorValue, onlyMissingKeys, createGuid);
return complexEditorValue.ToString();
}
private void UpdateNestedContentKeysRecursively(JToken json, bool onlyMissingKeys, Func<Guid> createGuid)
{
// check if this is NC
var isNestedContent = json.SelectTokens($"$..['{NestedContentPropertyEditor.ContentTypeAliasPropertyKey}']", false).Any();
// select all values (flatten)
var allProperties = json.SelectTokens("$..*").OfType<JValue>().Select(x => x.Parent as JProperty).WhereNotNull().ToList();
foreach (var prop in allProperties)
{
if (prop.Name == NestedContentPropertyEditor.ContentTypeAliasPropertyKey)
{
// get it's sibling 'key' property
var ncKeyVal = prop.Parent["key"] as JValue;
if ((onlyMissingKeys && ncKeyVal == null) || (!onlyMissingKeys && ncKeyVal != null))
{
// create or replace
prop.Parent["key"] = createGuid().ToString();
}
}
else if (!isNestedContent || prop.Name != "key")
{
// this is an arbitrary property that could contain a nested complex editor
var propVal = prop.Value?.ToString();
// check if this might contain a nested NC
if (!propVal.IsNullOrWhiteSpace() && propVal.DetectIsJson() && propVal.InvariantContains(NestedContentPropertyEditor.ContentTypeAliasPropertyKey))
{
// recurse
var parsed = JToken.Parse(propVal);
UpdateNestedContentKeysRecursively(parsed, onlyMissingKeys, createGuid);
// set the value to the updated one
prop.Value = parsed.ToString();
}
}
}
}
}
}