diff --git a/src/Umbraco.Core/PropertyEditors/IBlockValuePropertyIndexValueFactory.cs b/src/Umbraco.Core/PropertyEditors/IBlockValuePropertyIndexValueFactory.cs
new file mode 100644
index 0000000000..8556b993f0
--- /dev/null
+++ b/src/Umbraco.Core/PropertyEditors/IBlockValuePropertyIndexValueFactory.cs
@@ -0,0 +1,5 @@
+namespace Umbraco.Cms.Core.PropertyEditors;
+
+public interface IBlockValuePropertyIndexValueFactory : IPropertyIndexValueFactory
+{
+}
diff --git a/src/Umbraco.Core/PropertyEditors/INestedContentPropertyIndexValueFactory.cs b/src/Umbraco.Core/PropertyEditors/INestedContentPropertyIndexValueFactory.cs
new file mode 100644
index 0000000000..eb87a390d2
--- /dev/null
+++ b/src/Umbraco.Core/PropertyEditors/INestedContentPropertyIndexValueFactory.cs
@@ -0,0 +1,5 @@
+namespace Umbraco.Cms.Core.PropertyEditors;
+
+public interface INestedContentPropertyIndexValueFactory : IPropertyIndexValueFactory
+{
+}
diff --git a/src/Umbraco.Core/PropertyEditors/ITagPropertyIndexValueFactory.cs b/src/Umbraco.Core/PropertyEditors/ITagPropertyIndexValueFactory.cs
new file mode 100644
index 0000000000..33eabb314c
--- /dev/null
+++ b/src/Umbraco.Core/PropertyEditors/ITagPropertyIndexValueFactory.cs
@@ -0,0 +1,5 @@
+namespace Umbraco.Cms.Core.PropertyEditors;
+
+public interface ITagPropertyIndexValueFactory : IPropertyIndexValueFactory
+{
+}
diff --git a/src/Umbraco.Core/PropertyEditors/JsonPropertyIndexValueFactoryBase.cs b/src/Umbraco.Core/PropertyEditors/JsonPropertyIndexValueFactoryBase.cs
new file mode 100644
index 0000000000..e639ff7ca8
--- /dev/null
+++ b/src/Umbraco.Core/PropertyEditors/JsonPropertyIndexValueFactoryBase.cs
@@ -0,0 +1,84 @@
+using Umbraco.Cms.Core.Models;
+using Umbraco.Cms.Core.Serialization;
+using Umbraco.Extensions;
+
+namespace Umbraco.Cms.Core.PropertyEditors;
+
+///
+/// Abstract base for property index value factories where the value is json.
+///
+/// The type to deserialize the json to.
+public abstract class JsonPropertyIndexValueFactoryBase : IPropertyIndexValueFactory
+{
+ private readonly IJsonSerializer _jsonSerializer;
+
+ ///
+ /// Constructor for the JsonPropertyIndexValueFactoryBase.
+ ///
+ protected JsonPropertyIndexValueFactoryBase(IJsonSerializer jsonSerializer)
+ {
+ _jsonSerializer = jsonSerializer;
+ }
+
+ ///
+ public IEnumerable>> GetIndexValues(
+ IProperty property,
+ string? culture,
+ string? segment,
+ bool published)
+ {
+ var result = new List>>();
+
+ var propertyValue = property.GetValue(culture, segment, published);
+
+ // If there is a value, it's a string and it's detected as json.
+ if (propertyValue is string rawValue && rawValue.DetectIsJson())
+ {
+ try
+ {
+ TSerialized? deserializedPropertyValue = _jsonSerializer.Deserialize(rawValue);
+
+ if (deserializedPropertyValue is null)
+ {
+ return result;
+ }
+
+ result.AddRange(Handle(deserializedPropertyValue, property, culture, segment, published));
+ }
+ catch (InvalidCastException)
+ {
+ // Swallow...on purpose, there's a chance that this isn't the json format we are looking for
+ // and we don't want that to affect the website.
+ }
+ catch (ArgumentException)
+ {
+ // Swallow on purpose to prevent this error:
+ // Can not add Newtonsoft.Json.Linq.JValue to Newtonsoft.Json.Linq.JObject.
+ }
+ }
+
+ result.AddRange(HandleResume(result, property, culture, segment, published));
+
+ return result;
+ }
+
+ ///
+ /// Method to return a list of resume of the content. By default this returns an empty list
+ ///
+ protected virtual IEnumerable>> HandleResume(
+ List>> result,
+ IProperty property,
+ string? culture,
+ string? segment,
+ bool published) => Array.Empty>>();
+
+ ///
+ /// Method that handle the deserialized object.
+ ///
+ protected abstract IEnumerable>> Handle(
+ TSerialized deserializedPropertyValue,
+ IProperty property,
+ string? culture,
+ string? segment,
+ bool published);
+}
diff --git a/src/Umbraco.Core/PropertyEditors/NoopPropertyIndexValueFactory.cs b/src/Umbraco.Core/PropertyEditors/NoopPropertyIndexValueFactory.cs
new file mode 100644
index 0000000000..7e64b368c4
--- /dev/null
+++ b/src/Umbraco.Core/PropertyEditors/NoopPropertyIndexValueFactory.cs
@@ -0,0 +1,12 @@
+using Umbraco.Cms.Core.Models;
+
+namespace Umbraco.Cms.Core.PropertyEditors;
+
+///
+/// Property Index Valye Factory that do not index anything.
+///
+public class NoopPropertyIndexValueFactory : IPropertyIndexValueFactory
+{
+ ///
+ public IEnumerable>> GetIndexValues(IProperty property, string? culture, string? segment, bool published) => Array.Empty>>();
+}
diff --git a/src/Umbraco.Core/PropertyEditors/TagPropertyIndexValueFactory.cs b/src/Umbraco.Core/PropertyEditors/TagPropertyIndexValueFactory.cs
new file mode 100644
index 0000000000..83a327e0ef
--- /dev/null
+++ b/src/Umbraco.Core/PropertyEditors/TagPropertyIndexValueFactory.cs
@@ -0,0 +1,21 @@
+using Umbraco.Cms.Core.Models;
+using Umbraco.Cms.Core.Serialization;
+
+namespace Umbraco.Cms.Core.PropertyEditors;
+
+public class TagPropertyIndexValueFactory : JsonPropertyIndexValueFactoryBase, ITagPropertyIndexValueFactory
+{
+ public TagPropertyIndexValueFactory(IJsonSerializer jsonSerializer) : base(jsonSerializer)
+ {
+ }
+
+ protected override IEnumerable>> Handle(
+ string[] deserializedPropertyValue,
+ IProperty property,
+ string? culture,
+ string? segment,
+ bool published)
+ {
+ yield return new KeyValuePair>(property.Alias, deserializedPropertyValue);
+ }
+}
diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs
index e529902487..c65e50024c 100644
--- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs
+++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs
@@ -222,6 +222,19 @@ public static partial class UmbracoBuilderExtensions
builder.Services.AddSingleton();
builder.Services.AddTransient();
+
+
+ builder.AddPropertyIndexValueFactories();
+
+ return builder;
+ }
+
+ public static IUmbracoBuilder AddPropertyIndexValueFactories(this IUmbracoBuilder builder)
+ {
+ builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
+
return builder;
}
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/BlockEditorPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/BlockEditorPropertyEditor.cs
index b939a8c06e..acfe6659c5 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/BlockEditorPropertyEditor.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/BlockEditorPropertyEditor.cs
@@ -1,6 +1,9 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
+using Microsoft.Extensions.DependencyInjection;
+using Umbraco.Cms.Web.Common.DependencyInjection;
+
namespace Umbraco.Cms.Core.PropertyEditors;
// Scheduled for removal in v12
@@ -11,11 +14,26 @@ public abstract class BlockEditorPropertyEditor : BlockListPropertyEditorBase
public const string ContentTypeKeyPropertyKey = "contentTypeKey";
public const string UdiPropertyKey = "udi";
+ [Obsolete("Use non-obsoleted ctor. This will be removed in Umbraco 13.")]
protected BlockEditorPropertyEditor(
IDataValueEditorFactory dataValueEditorFactory,
PropertyEditorCollection propertyEditors)
- : base(dataValueEditorFactory) =>
+ : this(
+ dataValueEditorFactory,
+ propertyEditors,
+ StaticServiceProvider.Instance.GetRequiredService())
+ {
+
+ }
+
+ protected BlockEditorPropertyEditor(
+ IDataValueEditorFactory dataValueEditorFactory,
+ PropertyEditorCollection propertyEditors,
+ IBlockValuePropertyIndexValueFactory blockValuePropertyIndexValueFactory)
+ : base(dataValueEditorFactory, blockValuePropertyIndexValueFactory)
+ {
PropertyEditors = propertyEditors;
+ }
private PropertyEditorCollection PropertyEditors { get; }
}
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/BlockGridPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/BlockGridPropertyEditor.cs
index 8881ce82a9..361b8c86f0 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/BlockGridPropertyEditor.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/BlockGridPropertyEditor.cs
@@ -1,7 +1,9 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
+using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.IO;
+using Umbraco.Cms.Web.Common.DependencyInjection;
namespace Umbraco.Cms.Core.PropertyEditors;
@@ -19,11 +21,25 @@ public class BlockGridPropertyEditor : BlockGridPropertyEditorBase
{
private readonly IIOHelper _ioHelper;
+ [Obsolete("Use non-obsoleted ctor. This will be removed in Umbraco 13.")]
public BlockGridPropertyEditor(
IDataValueEditorFactory dataValueEditorFactory,
IIOHelper ioHelper)
- : base(dataValueEditorFactory) =>
+ : this(dataValueEditorFactory, ioHelper, StaticServiceProvider.Instance.GetRequiredService())
+ {
+
+ }
+
+
+ public BlockGridPropertyEditor(
+ IDataValueEditorFactory dataValueEditorFactory,
+ IIOHelper ioHelper,
+ IBlockValuePropertyIndexValueFactory blockValuePropertyIndexValueFactory)
+ : base(dataValueEditorFactory, blockValuePropertyIndexValueFactory)
+ {
_ioHelper = ioHelper;
+ }
+
#region Pre Value Editor
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/BlockGridPropertyEditorBase.cs b/src/Umbraco.Infrastructure/PropertyEditors/BlockGridPropertyEditorBase.cs
index 42a5931a2b..73b767bd4f 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/BlockGridPropertyEditorBase.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/BlockGridPropertyEditorBase.cs
@@ -2,6 +2,7 @@
// See LICENSE for more details.
using System.ComponentModel.DataAnnotations;
+using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Umbraco.Cms.Core.IO;
using Umbraco.Cms.Core.Models;
@@ -9,6 +10,7 @@ using Umbraco.Cms.Core.Models.Blocks;
using Umbraco.Cms.Core.Serialization;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Strings;
+using Umbraco.Cms.Web.Common.DependencyInjection;
using Umbraco.Extensions;
using BlockGridAreaConfiguration = Umbraco.Cms.Core.PropertyEditors.BlockGridConfiguration.BlockGridAreaConfiguration;
@@ -19,9 +21,24 @@ namespace Umbraco.Cms.Core.PropertyEditors;
///
public abstract class BlockGridPropertyEditorBase : DataEditor
{
+ private readonly IBlockValuePropertyIndexValueFactory _blockValuePropertyIndexValueFactory;
+
+ [Obsolete("Use non-obsoleted ctor. This will be removed in Umbraco 13.")]
protected BlockGridPropertyEditorBase(IDataValueEditorFactory dataValueEditorFactory)
- : base(dataValueEditorFactory) =>
+ : this(dataValueEditorFactory, StaticServiceProvider.Instance.GetRequiredService())
+ {
+
+ }
+
+ protected BlockGridPropertyEditorBase(IDataValueEditorFactory dataValueEditorFactory, IBlockValuePropertyIndexValueFactory blockValuePropertyIndexValueFactory)
+ : base(dataValueEditorFactory)
+ {
+ _blockValuePropertyIndexValueFactory = blockValuePropertyIndexValueFactory;
SupportsReadOnly = true;
+ }
+
+ public override IPropertyIndexValueFactory PropertyIndexValueFactory => _blockValuePropertyIndexValueFactory;
+
#region Value Editor
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/BlockListPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/BlockListPropertyEditor.cs
index f36d7b67ff..2f5147cf1a 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/BlockListPropertyEditor.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/BlockListPropertyEditor.cs
@@ -25,7 +25,7 @@ public class BlockListPropertyEditor : BlockEditorPropertyEditor
private readonly IIOHelper _ioHelper;
// Scheduled for removal in v12
- [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")]
+ [Obsolete("Use non-obsoleted ctor. This will be removed in Umbraco 13.")]
public BlockListPropertyEditor(
IDataValueEditorFactory dataValueEditorFactory,
PropertyEditorCollection propertyEditors,
@@ -34,12 +34,29 @@ public class BlockListPropertyEditor : BlockEditorPropertyEditor
{
}
+ [Obsolete("Use non-obsoleted ctor. This will be removed in Umbraco 13.")]
public BlockListPropertyEditor(
IDataValueEditorFactory dataValueEditorFactory,
PropertyEditorCollection propertyEditors,
IIOHelper ioHelper,
IEditorConfigurationParser editorConfigurationParser)
- : base(dataValueEditorFactory, propertyEditors)
+ : this(
+ dataValueEditorFactory,
+ propertyEditors,
+ ioHelper,
+ editorConfigurationParser,
+ StaticServiceProvider.Instance.GetRequiredService())
+ {
+
+ }
+
+ public BlockListPropertyEditor(
+ IDataValueEditorFactory dataValueEditorFactory,
+ PropertyEditorCollection propertyEditors,
+ IIOHelper ioHelper,
+ IEditorConfigurationParser editorConfigurationParser,
+ IBlockValuePropertyIndexValueFactory blockValuePropertyIndexValueFactory)
+ : base(dataValueEditorFactory, propertyEditors, blockValuePropertyIndexValueFactory)
{
_ioHelper = ioHelper;
_editorConfigurationParser = editorConfigurationParser;
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/BlockListPropertyEditorBase.cs b/src/Umbraco.Infrastructure/PropertyEditors/BlockListPropertyEditorBase.cs
index eb09f405a0..194383560e 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/BlockListPropertyEditorBase.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/BlockListPropertyEditorBase.cs
@@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations;
+using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Umbraco.Cms.Core.IO;
using Umbraco.Cms.Core.Models;
@@ -6,6 +7,7 @@ using Umbraco.Cms.Core.Models.Blocks;
using Umbraco.Cms.Core.Serialization;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Strings;
+using Umbraco.Cms.Web.Common.DependencyInjection;
namespace Umbraco.Cms.Core.PropertyEditors;
@@ -14,9 +16,25 @@ namespace Umbraco.Cms.Core.PropertyEditors;
///
public abstract class BlockListPropertyEditorBase : DataEditor
{
+
+ private readonly IBlockValuePropertyIndexValueFactory _blockValuePropertyIndexValueFactory;
+
+ [Obsolete("Use non-obsoleted ctor. This will be removed in Umbraco 13.")]
protected BlockListPropertyEditorBase(IDataValueEditorFactory dataValueEditorFactory)
- : base(dataValueEditorFactory) =>
+ : this(dataValueEditorFactory, StaticServiceProvider.Instance.GetRequiredService())
+ {
+
+ }
+
+ protected BlockListPropertyEditorBase(IDataValueEditorFactory dataValueEditorFactory, IBlockValuePropertyIndexValueFactory blockValuePropertyIndexValueFactory)
+ : base(dataValueEditorFactory)
+ {
+ _blockValuePropertyIndexValueFactory = blockValuePropertyIndexValueFactory;
SupportsReadOnly = true;
+ }
+
+ public override IPropertyIndexValueFactory PropertyIndexValueFactory => _blockValuePropertyIndexValueFactory;
+
#region Value Editor
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/BlockValuePropertyIndexValueFactory.cs b/src/Umbraco.Infrastructure/PropertyEditors/BlockValuePropertyIndexValueFactory.cs
new file mode 100644
index 0000000000..dfedeedc3f
--- /dev/null
+++ b/src/Umbraco.Infrastructure/PropertyEditors/BlockValuePropertyIndexValueFactory.cs
@@ -0,0 +1,35 @@
+// Copyright (c) Umbraco.
+// See LICENSE for more details.
+
+using Umbraco.Cms.Core.Models;
+using Umbraco.Cms.Core.Models.Blocks;
+using Umbraco.Cms.Core.Serialization;
+using Umbraco.Cms.Core.Services;
+
+namespace Umbraco.Cms.Core.PropertyEditors;
+
+internal sealed class BlockValuePropertyIndexValueFactory :
+ NestedPropertyIndexValueFactoryBase,
+ IBlockValuePropertyIndexValueFactory
+{
+ private readonly IContentTypeService _contentTypeService;
+
+
+ public BlockValuePropertyIndexValueFactory(
+ PropertyEditorCollection propertyEditorCollection,
+ IContentTypeService contentTypeService,
+ IJsonSerializer jsonSerializer)
+ : base(propertyEditorCollection, jsonSerializer)
+ {
+ _contentTypeService = contentTypeService;
+ }
+
+
+ protected override IContentType? GetContentTypeOfNestedItem(BlockItemData input) =>
+ _contentTypeService.Get(input.ContentTypeKey);
+
+ protected override IDictionary GetRawProperty(BlockItemData blockItemData) =>
+ blockItemData.RawPropertyValues;
+
+ protected override IEnumerable GetDataItems(BlockValue input) => input.ContentData;
+}
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ColorPickerPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/ColorPickerPropertyEditor.cs
index 1ce8ae4930..00d432070f 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/ColorPickerPropertyEditor.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/ColorPickerPropertyEditor.cs
@@ -45,6 +45,9 @@ public class ColorPickerPropertyEditor : DataEditor
SupportsReadOnly = true;
}
+ public override IPropertyIndexValueFactory PropertyIndexValueFactory { get; } = new NoopPropertyIndexValueFactory();
+
+
///
protected override IConfigurationEditor CreateConfigurationEditor() =>
new ColorPickerConfigurationEditor(_ioHelper, _jsonSerializer, _editorConfigurationParser);
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs
index c3390b3fc5..ab1e3f976e 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs
@@ -97,6 +97,8 @@ public class ImageCropperPropertyEditor : DataEditor, IMediaUrlGenerator,
SupportsReadOnly = true;
}
+ public override IPropertyIndexValueFactory PropertyIndexValueFactory { get; } = new NoopPropertyIndexValueFactory();
+
public bool TryGetMediaPath(string? propertyEditorAlias, object? value, out string? mediaPath)
{
if (propertyEditorAlias == Alias &&
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MediaPicker3PropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/MediaPicker3PropertyEditor.cs
index 09eb6a1f47..f67273a041 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/MediaPicker3PropertyEditor.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/MediaPicker3PropertyEditor.cs
@@ -59,6 +59,8 @@ public class MediaPicker3PropertyEditor : DataEditor
SupportsReadOnly = true;
}
+ public override IPropertyIndexValueFactory PropertyIndexValueFactory { get; } = new NoopPropertyIndexValueFactory();
+
///
protected override IConfigurationEditor CreateConfigurationEditor() =>
new MediaPicker3ConfigurationEditor(_ioHelper, _editorConfigurationParser);
@@ -67,6 +69,8 @@ public class MediaPicker3PropertyEditor : DataEditor
protected override IDataValueEditor CreateValueEditor() =>
DataValueEditorFactory.Create(Attribute!);
+
+
internal class MediaPicker3PropertyValueEditor : DataValueEditor, IDataValueReference
{
private readonly IDataTypeService _dataTypeService;
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyEditor.cs
index f38c88c4bc..d64df34aa4 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyEditor.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyEditor.cs
@@ -32,9 +32,9 @@ public class NestedContentPropertyEditor : DataEditor
public const string ContentTypeAliasPropertyKey = "ncContentTypeAlias";
private readonly IEditorConfigurationParser _editorConfigurationParser;
private readonly IIOHelper _ioHelper;
+ private readonly INestedContentPropertyIndexValueFactory _nestedContentPropertyIndexValueFactory;
- // Scheduled for removal in v12
- [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")]
+ [Obsolete("Use non-obsoleted ctor. This will be removed in Umbraco 12.")]
public NestedContentPropertyEditor(
IDataValueEditorFactory dataValueEditorFactory,
IIOHelper ioHelper)
@@ -42,17 +42,35 @@ public class NestedContentPropertyEditor : DataEditor
{
}
+ [Obsolete("Use non-obsoleted ctor. This will be removed in Umbraco 13.")]
public NestedContentPropertyEditor(
IDataValueEditorFactory dataValueEditorFactory,
IIOHelper ioHelper,
IEditorConfigurationParser editorConfigurationParser)
+ : this(
+ dataValueEditorFactory,
+ ioHelper,
+ editorConfigurationParser,
+ StaticServiceProvider.Instance.GetRequiredService())
+ {
+
+ }
+
+ public NestedContentPropertyEditor(
+ IDataValueEditorFactory dataValueEditorFactory,
+ IIOHelper ioHelper,
+ IEditorConfigurationParser editorConfigurationParser,
+ INestedContentPropertyIndexValueFactory nestedContentPropertyIndexValueFactory)
: base(dataValueEditorFactory)
{
_ioHelper = ioHelper;
_editorConfigurationParser = editorConfigurationParser;
+ _nestedContentPropertyIndexValueFactory = nestedContentPropertyIndexValueFactory;
SupportsReadOnly = true;
}
+ public override IPropertyIndexValueFactory PropertyIndexValueFactory => _nestedContentPropertyIndexValueFactory;
+
#region Pre Value Editor
protected override IConfigurationEditor CreateConfigurationEditor() =>
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyIndexValueFactory.cs b/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyIndexValueFactory.cs
new file mode 100644
index 0000000000..445e1cc361
--- /dev/null
+++ b/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyIndexValueFactory.cs
@@ -0,0 +1,37 @@
+// Copyright (c) Umbraco.
+// See LICENSE for more details.
+
+using Umbraco.Cms.Core.Models;
+using Umbraco.Cms.Core.Serialization;
+using Umbraco.Cms.Core.Services;
+
+namespace Umbraco.Cms.Core.PropertyEditors;
+
+internal sealed class NestedContentPropertyIndexValueFactory
+ : NestedPropertyIndexValueFactoryBase<
+ NestedContentPropertyEditor.NestedContentValues.NestedContentRowValue[],
+ NestedContentPropertyEditor.NestedContentValues.NestedContentRowValue>,
+ INestedContentPropertyIndexValueFactory
+{
+ private readonly IContentTypeService _contentTypeService;
+
+
+ public NestedContentPropertyIndexValueFactory(
+ PropertyEditorCollection propertyEditorCollection,
+ IContentTypeService contentTypeService,
+ IJsonSerializer jsonSerializer) : base(propertyEditorCollection, jsonSerializer)
+ {
+ _contentTypeService = contentTypeService;
+ }
+
+ protected override IContentType? GetContentTypeOfNestedItem(
+ NestedContentPropertyEditor.NestedContentValues.NestedContentRowValue input)
+ => _contentTypeService.Get(input.ContentTypeAlias);
+
+ protected override IDictionary GetRawProperty(
+ NestedContentPropertyEditor.NestedContentValues.NestedContentRowValue nestedContentRowValue) =>
+ nestedContentRowValue.RawPropertyValues;
+
+ protected override IEnumerable GetDataItems(
+ NestedContentPropertyEditor.NestedContentValues.NestedContentRowValue[] input) => input;
+}
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/NestedPropertyIndexValueFactoryBase.cs b/src/Umbraco.Infrastructure/PropertyEditors/NestedPropertyIndexValueFactoryBase.cs
new file mode 100644
index 0000000000..cc2f8143b8
--- /dev/null
+++ b/src/Umbraco.Infrastructure/PropertyEditors/NestedPropertyIndexValueFactoryBase.cs
@@ -0,0 +1,181 @@
+using System.Text;
+using Umbraco.Cms.Core.Models;
+using Umbraco.Cms.Core.Serialization;
+using Umbraco.Cms.Infrastructure.Examine;
+using Umbraco.Extensions;
+
+namespace Umbraco.Cms.Core.PropertyEditors;
+
+internal abstract class NestedPropertyIndexValueFactoryBase : JsonPropertyIndexValueFactoryBase
+{
+ private readonly PropertyEditorCollection _propertyEditorCollection;
+
+ protected NestedPropertyIndexValueFactoryBase(
+ PropertyEditorCollection propertyEditorCollection,
+ IJsonSerializer jsonSerializer)
+ : base(jsonSerializer)
+ {
+ _propertyEditorCollection = propertyEditorCollection;
+ }
+
+ protected override IEnumerable>> Handle(
+ TSerialized deserializedPropertyValue,
+ IProperty property,
+ string? culture,
+ string? segment,
+ bool published)
+ {
+ var result = new List>>();
+
+ foreach (TItem nestedContentRowValue in GetDataItems(deserializedPropertyValue))
+ {
+ IContentType? contentType = GetContentTypeOfNestedItem(nestedContentRowValue);
+
+ if (contentType is null)
+ {
+ continue;
+ }
+
+ var propertyTypeDictionary =
+ contentType
+ .PropertyGroups
+ .SelectMany(x => x.PropertyTypes!)
+ .ToDictionary(x => x.Alias);
+
+ result.AddRange(GetNestedResults(
+ property.Alias,
+ culture,
+ segment,
+ published,
+ propertyTypeDictionary,
+ nestedContentRowValue));
+ }
+
+ return RenameKeysToEnsureRawSegmentsIsAPrefix(result);
+ }
+
+ ///
+ /// Rename keys that count the RAW-constant, to ensure the RAW-constant is a prefix.
+ ///
+ private IEnumerable>> RenameKeysToEnsureRawSegmentsIsAPrefix(
+ List>> indexContent)
+ {
+ foreach (KeyValuePair> indexedKeyValuePair in indexContent)
+ {
+ // Tests if key includes the RawFieldPrefix and it is not in the start
+ if (indexedKeyValuePair.Key.Substring(1).Contains(UmbracoExamineFieldNames.RawFieldPrefix))
+ {
+ var newKey = UmbracoExamineFieldNames.RawFieldPrefix +
+ indexedKeyValuePair.Key.Replace(UmbracoExamineFieldNames.RawFieldPrefix, string.Empty);
+ yield return new KeyValuePair>(newKey, indexedKeyValuePair.Value);
+ }
+ else
+ {
+ yield return indexedKeyValuePair;
+ }
+ }
+ }
+
+ ///
+ /// Gets the content type using the nested item.
+ ///
+ protected abstract IContentType? GetContentTypeOfNestedItem(TItem nestedItem);
+
+ ///
+ /// Gets the raw data from a nested item.
+ ///
+ protected abstract IDictionary GetRawProperty(TItem nestedItem);
+
+ ///
+ /// Get the data times of a parent item. E.g. block list have contentData.
+ ///
+ protected abstract IEnumerable GetDataItems(TSerialized input);
+
+ ///
+ /// Index a key with the name of the property, using the relevant content of all the children.
+ ///
+ protected override IEnumerable>> HandleResume(
+ List>> indexedContent,
+ IProperty property,
+ string? culture,
+ string? segment,
+ bool published)
+ {
+ yield return new KeyValuePair>(
+ property.Alias,
+ GetResumeFromAllContent(indexedContent).Yield());
+ }
+
+ ///
+ /// Gets a resume as string of all the content in this nested type.
+ ///
+ /// All the indexed content for this property.
+ /// the string with all relevant content from
+ private static string GetResumeFromAllContent(List>> indexedContent)
+ {
+ var stringBuilder = new StringBuilder();
+ foreach ((var indexKey, IEnumerable