Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Block level variants - search indexing #17239

Merged
merged 6 commits into from
Oct 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Umbraco.Cms.Core.Models;
using Umbraco.Extensions;

namespace Umbraco.Cms.Core.PropertyEditors;

Expand All @@ -9,11 +8,15 @@ namespace Umbraco.Cms.Core.PropertyEditors;
/// </summary>
public class DefaultPropertyIndexValueFactory : IPropertyIndexValueFactory
{
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published,
public IEnumerable<IndexValue> GetIndexValues(IProperty property, string? culture, string? segment, bool published,
IEnumerable<string> availableCultures, IDictionary<Guid, IContentType> contentTypeDictionary)
{
yield return new KeyValuePair<string, IEnumerable<object?>>(
property.Alias,
property.GetValue(culture, segment, published).Yield());
}
=>
[
new IndexValue
{
Culture = culture,
FieldName = property.Alias,
Values = [property.GetValue(culture, segment, published)]
}
];
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ public interface IPropertyIndexValueFactory
/// </summary>
/// <remarks>
/// <para>
/// Returns key-value pairs, where keys are indexed field names. By default, that would be the property alias,
/// and there would be only one pair, but some implementations (see for instance the grid one) may return more than
/// one pair, with different indexed field names.
/// Returns index values for a given property. By default, a property uses its alias as index field name,
/// and there would be only one index value, but some implementations (see for instance the grid one) may return more than
/// one value, with different indexed field names.
/// </para>
/// <para>
/// And then, values are an enumerable of objects, because each indexed field can in turn have multiple
/// values. By default, there would be only one object: the property value. But some implementations may return
/// more than one value for a given field.
/// </para>
/// </remarks>
IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(
IEnumerable<IndexValue> GetIndexValues(
IProperty property,
string? culture,
string? segment,
Expand Down
10 changes: 10 additions & 0 deletions src/Umbraco.Core/PropertyEditors/IndexValue.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Umbraco.Cms.Core.PropertyEditors;

public sealed class IndexValue
{
public required string? Culture { get; set; }

public required string FieldName { get; set; }

public required IEnumerable<object?> Values { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ protected JsonPropertyIndexValueFactoryBase(IJsonSerializer jsonSerializer, IOpt
indexingSettings.OnChange(newValue => _indexingSettings = newValue);
}

public virtual IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(
public virtual IEnumerable<IndexValue> GetIndexValues(
IProperty property,
string? culture,
string? segment,
bool published,
IEnumerable<string> availableCultures,
IDictionary<Guid, IContentType> contentTypeDictionary)
{
var result = new List<KeyValuePair<string, IEnumerable<object?>>>();
var result = new List<IndexValue>();

var propertyValue = property.GetValue(culture, segment, published);

Expand Down Expand Up @@ -65,7 +65,7 @@ protected JsonPropertyIndexValueFactoryBase(IJsonSerializer jsonSerializer, IOpt
}
}

IEnumerable<KeyValuePair<string, IEnumerable<object?>>> summary = HandleResume(result, property, culture, segment, published);
IEnumerable<IndexValue> summary = HandleResume(result, property, culture, segment, published);
if (_indexingSettings.ExplicitlyIndexEachNestedProperty || ForceExplicitlyIndexEachNestedProperty)
{
result.AddRange(summary);
Expand All @@ -78,17 +78,17 @@ protected JsonPropertyIndexValueFactoryBase(IJsonSerializer jsonSerializer, IOpt
/// <summary>
/// Method to return a list of summary of the content. By default this returns an empty list
/// </summary>
protected virtual IEnumerable<KeyValuePair<string, IEnumerable<object?>>> HandleResume(
List<KeyValuePair<string, IEnumerable<object?>>> result,
protected virtual IEnumerable<IndexValue> HandleResume(
List<IndexValue> result,
IProperty property,
string? culture,
string? segment,
bool published) => Array.Empty<KeyValuePair<string, IEnumerable<object?>>>();
bool published) => Array.Empty<IndexValue>();

/// <summary>
/// Method that handle the deserialized object.
/// </summary>
protected abstract IEnumerable<KeyValuePair<string, IEnumerable<object?>>> Handle(
protected abstract IEnumerable<IndexValue> Handle(
TSerialized deserializedPropertyValue,
IProperty property,
string? culture,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Umbraco.Cms.Core.PropertyEditors;
public class NoopPropertyIndexValueFactory : IPropertyIndexValueFactory
{
/// <inheritdoc />
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published,
public IEnumerable<IndexValue> GetIndexValues(IProperty property, string? culture, string? segment, bool published,
IEnumerable<string> availableCultures, IDictionary<Guid, IContentType> contentTypeDictionary)
=> Array.Empty<KeyValuePair<string, IEnumerable<object?>>>();
=> [];
}
32 changes: 14 additions & 18 deletions src/Umbraco.Core/PropertyEditors/TagPropertyIndexValueFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,43 +19,39 @@
indexingSettings.OnChange(newValue => _indexingSettings = newValue);
}

[Obsolete("Use the overload with the 'contentTypeDictionary' parameter instead, scheduled for removal in v15")]
protected IEnumerable<KeyValuePair<string, IEnumerable<object?>>> Handle(
string[] deserializedPropertyValue,
IProperty property,
string? culture,
string? segment,
bool published,
IEnumerable<string> availableCultures)
=> Handle(deserializedPropertyValue, property, culture, segment, published, availableCultures, new Dictionary<Guid, IContentType>());

protected override IEnumerable<KeyValuePair<string, IEnumerable<object?>>> Handle(
protected override IEnumerable<IndexValue> Handle(
string[] deserializedPropertyValue,
IProperty property,
string? culture,
string? segment,
bool published,
IEnumerable<string> availableCultures,
IDictionary<Guid, IContentType> contentTypeDictionary)
{
yield return new KeyValuePair<string, IEnumerable<object?>>(property.Alias, deserializedPropertyValue);
}
=>
[
new IndexValue
{
Culture = culture,
FieldName = property.Alias,
Values = deserializedPropertyValue
}
];

Check notice on line 38 in src/Umbraco.Core/PropertyEditors/TagPropertyIndexValueFactory.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (release/15.0)

ℹ Getting worse: Excess Number of Function Arguments

Handle increases from 6 to 7 arguments, threshold = 4. This function has too many arguments, indicating a lack of encapsulation. Avoid adding more arguments.

Check notice on line 38 in src/Umbraco.Core/PropertyEditors/TagPropertyIndexValueFactory.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (release/15.0)

✅ No longer an issue: Excess Number of Function Arguments

Handle is no longer above the threshold for number of arguments. This function has too many arguments, indicating a lack of encapsulation. Avoid adding more arguments.

public override IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(
public override IEnumerable<IndexValue> GetIndexValues(
IProperty property,
string? culture,
string? segment,
bool published,
IEnumerable<string> availableCultures,
IDictionary<Guid, IContentType> contentTypeDictionary)
{
IEnumerable<KeyValuePair<string, IEnumerable<object?>>> jsonValues = base.GetIndexValues(property, culture, segment, published, availableCultures, contentTypeDictionary);
IEnumerable<IndexValue> jsonValues = base.GetIndexValues(property, culture, segment, published, availableCultures, contentTypeDictionary);
if (jsonValues?.Any() is true)
{
return jsonValues;
}

var result = new List<KeyValuePair<string, IEnumerable<object?>>>();
var result = new List<IndexValue>();

var propertyValue = property.GetValue(culture, segment, published);

Expand All @@ -67,7 +63,7 @@
result.AddRange(Handle(values, property, culture, segment, published, availableCultures, contentTypeDictionary));
}

IEnumerable<KeyValuePair<string, IEnumerable<object?>>> summary = HandleResume(result, property, culture, segment, published);
IEnumerable<IndexValue> summary = HandleResume(result, property, culture, segment, published);
if (_indexingSettings.ExplicitlyIndexEachNestedProperty || ForceExplicitlyIndexEachNestedProperty)
{
result.AddRange(summary);
Expand Down
19 changes: 10 additions & 9 deletions src/Umbraco.Infrastructure/Examine/BaseValueSetBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,53 +30,54 @@
return;
}

IEnumerable<KeyValuePair<string, IEnumerable<object?>>> indexVals =
IEnumerable<IndexValue> indexVals =
editor.PropertyIndexValueFactory.GetIndexValues(property, culture, segment, PublishedValuesOnly, availableCultures, contentTypeDictionary);
foreach (KeyValuePair<string, IEnumerable<object?>> keyVal in indexVals)
foreach (IndexValue indexValue in indexVals)
{
if (keyVal.Key.IsNullOrWhiteSpace())
if (indexValue.FieldName.IsNullOrWhiteSpace())
{
continue;
}

var cultureSuffix = culture == null ? string.Empty : "_" + culture;
var indexValueCulture = indexValue.Culture ?? culture;
var cultureSuffix = indexValueCulture == null ? string.Empty : "_" + indexValueCulture.ToLowerInvariant();

foreach (var val in keyVal.Value)
foreach (var val in indexValue.Values)
{
switch (val)
{
// only add the value if its not null or empty (we'll check for string explicitly here too)
case null:
continue;
case string strVal:
{
if (strVal.IsNullOrWhiteSpace())
{
continue;
}

var key = $"{keyVal.Key}{cultureSuffix}";
var key = $"{indexValue.FieldName}{cultureSuffix}";
if (values?.TryGetValue(key, out IEnumerable<object?>? v) ?? false)
{
values[key] = new List<object?>(v) { val }.ToArray();
}
else
{
values?.Add($"{keyVal.Key}{cultureSuffix}", val.Yield());
values?.Add($"{indexValue.FieldName}{cultureSuffix}", val.Yield());
}
}

break;
default:
{
var key = $"{keyVal.Key}{cultureSuffix}";
var key = $"{indexValue.FieldName}{cultureSuffix}";
if (values?.TryGetValue(key, out IEnumerable<object?>? v) ?? false)
{
values[key] = new List<object?>(v) { val }.ToArray();
}
else
{
values?.Add($"{keyVal.Key}{cultureSuffix}", val.Yield());
values?.Add($"{indexValue.FieldName}{cultureSuffix}", val.Yield());

Check warning on line 80 in src/Umbraco.Infrastructure/Examine/BaseValueSetBuilder.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (release/15.0)

❌ Getting worse: Complex Method

AddPropertyValue increases in cyclomatic complexity from 17 to 18, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@

using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Blocks;
using Umbraco.Cms.Core.Serialization;

namespace Umbraco.Cms.Core.PropertyEditors;

internal sealed class BlockValuePropertyIndexValueFactory :
NestedPropertyIndexValueFactoryBase<BlockValuePropertyIndexValueFactory.IndexValueFactoryBlockValue, BlockItemData>,
internal class BlockValuePropertyIndexValueFactory :
BlockValuePropertyIndexValueFactoryBase<BlockValuePropertyIndexValueFactory.IndexValueFactoryBlockValue>,
IBlockValuePropertyIndexValueFactory
{
public BlockValuePropertyIndexValueFactory(
Expand All @@ -21,19 +20,14 @@ public BlockValuePropertyIndexValueFactory(
{
}

protected override IContentType? GetContentTypeOfNestedItem(BlockItemData input, IDictionary<Guid, IContentType> contentTypeDictionary)
=> contentTypeDictionary.TryGetValue(input.ContentTypeKey, out var result) ? result : null;

protected override IDictionary<string, object?> GetRawProperty(BlockItemData blockItemData)
=> blockItemData.Values
.Where(p => p.Culture is null && p.Segment is null)
.ToDictionary(p => p.Alias, p => p.Value);

protected override IEnumerable<BlockItemData> GetDataItems(IndexValueFactoryBlockValue input) => input.ContentData;
protected override IEnumerable<RawDataItem> GetDataItems(IndexValueFactoryBlockValue input, bool published)
=> GetDataItems(input.ContentData, input.Expose, published);

// we only care about the content data when extracting values for indexing - not the layouts nor the settings
internal class IndexValueFactoryBlockValue
{
public List<BlockItemData> ContentData { get; set; } = new();

public List<BlockItemVariation> Expose { get; set; } = new();
}
}
Loading
Loading