Performance optimisations related to blocks (and multi url picker) (#15184)
* Added content types to property index value factory, because the deep cloning is too expensive to execute often * Do not use entityservice in ToEditor, as it goes to the database. We need to use something that is cached. * Small performance optimization for nested content too * A little formatting and an obsoletion message --------- Co-authored-by: kjac <kja@umbraco.dk>
This commit is contained in:
@@ -9,15 +9,22 @@ namespace Umbraco.Cms.Core.PropertyEditors;
|
||||
/// </summary>
|
||||
public class DefaultPropertyIndexValueFactory : IPropertyIndexValueFactory
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published, IEnumerable<string> availableCultures)
|
||||
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> 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());
|
||||
}
|
||||
|
||||
[Obsolete("Use the overload with the availableCultures parameter instead, scheduled for removal in v14")]
|
||||
/// <inheritdoc />
|
||||
[Obsolete("Use the non-obsolete overload, scheduled for removal in v14")]
|
||||
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture,
|
||||
string? segment, bool published, IEnumerable<string> availableCultures)
|
||||
=> GetIndexValues(property, culture, segment, published, availableCultures,
|
||||
new Dictionary<Guid, IContentType>());
|
||||
|
||||
[Obsolete("Use the non-obsolete overload, scheduled for removal in v14")]
|
||||
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published)
|
||||
=> GetIndexValues(property, culture, segment, published, Enumerable.Empty<string>());
|
||||
=> GetIndexValues(property, culture, segment, published, Enumerable.Empty<string>(), new Dictionary<Guid, IContentType>());
|
||||
}
|
||||
|
||||
@@ -22,9 +22,14 @@ public interface IPropertyIndexValueFactory
|
||||
/// more than one value for a given field.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture,
|
||||
string? segment, bool published, IEnumerable<string> availableCultures,
|
||||
IDictionary<Guid, IContentType> contentTypeDictionary) => GetIndexValues(property, culture, segment, published);
|
||||
|
||||
[Obsolete("Use non-obsolete overload, scheduled for removal in v14")]
|
||||
IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published, IEnumerable<string> availableCultures)
|
||||
=> GetIndexValues(property, culture, segment, published);
|
||||
|
||||
[Obsolete("Use the overload with the availableCultures parameter instead, scheduled for removal in v14")]
|
||||
[Obsolete("Use non-obsolete overload, scheduled for removal in v14")]
|
||||
IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Serialization;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Web.Common.DependencyInjection;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
@@ -39,13 +40,13 @@ public abstract class JsonPropertyIndexValueFactoryBase<TSerialized> : IProperty
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(
|
||||
IProperty property,
|
||||
string? culture,
|
||||
string? segment,
|
||||
bool published,
|
||||
IEnumerable<string> availableCultures)
|
||||
IEnumerable<string> availableCultures,
|
||||
IDictionary<Guid, IContentType> contentTypeDictionary)
|
||||
{
|
||||
var result = new List<KeyValuePair<string, IEnumerable<object?>>>();
|
||||
|
||||
@@ -63,7 +64,7 @@ public abstract class JsonPropertyIndexValueFactoryBase<TSerialized> : IProperty
|
||||
return result;
|
||||
}
|
||||
|
||||
result.AddRange(Handle(deserializedPropertyValue, property, culture, segment, published, availableCultures));
|
||||
result.AddRange(Handle(deserializedPropertyValue, property, culture, segment, published, availableCultures, contentTypeDictionary));
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
@@ -87,9 +88,31 @@ public abstract class JsonPropertyIndexValueFactoryBase<TSerialized> : IProperty
|
||||
return summary;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Obsolete("Use non-obsolete constructor. This will be removed in Umbraco 14.")]
|
||||
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(
|
||||
IProperty property,
|
||||
string? culture,
|
||||
string? segment,
|
||||
bool published,
|
||||
IEnumerable<string> availableCultures)
|
||||
=> GetIndexValues(
|
||||
property,
|
||||
culture,
|
||||
segment,
|
||||
published,
|
||||
Enumerable.Empty<string>(),
|
||||
StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>().GetAll().ToDictionary(x=>x.Key));
|
||||
|
||||
[Obsolete("Use method overload that has availableCultures, scheduled for removal in v14")]
|
||||
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published)
|
||||
=> GetIndexValues(property, culture, segment, published, Enumerable.Empty<string>());
|
||||
=> GetIndexValues(
|
||||
property,
|
||||
culture,
|
||||
segment,
|
||||
published,
|
||||
Enumerable.Empty<string>(),
|
||||
StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>().GetAll().ToDictionary(x=>x.Key));
|
||||
|
||||
/// <summary>
|
||||
/// Method to return a list of summary of the content. By default this returns an empty list
|
||||
@@ -104,7 +127,7 @@ public abstract class JsonPropertyIndexValueFactoryBase<TSerialized> : IProperty
|
||||
/// <summary>
|
||||
/// Method that handle the deserialized object.
|
||||
/// </summary>
|
||||
[Obsolete("Use the overload with the availableCultures parameter instead, scheduled for removal in v14")]
|
||||
[Obsolete("Use the non-obsolete overload instead, scheduled for removal in v14")]
|
||||
protected abstract IEnumerable<KeyValuePair<string, IEnumerable<object?>>> Handle(
|
||||
TSerialized deserializedPropertyValue,
|
||||
IProperty property,
|
||||
@@ -112,6 +135,15 @@ public abstract class JsonPropertyIndexValueFactoryBase<TSerialized> : IProperty
|
||||
string? segment,
|
||||
bool published);
|
||||
|
||||
[Obsolete("Use the non-obsolete overload instead, scheduled for removal in v14")]
|
||||
protected virtual IEnumerable<KeyValuePair<string, IEnumerable<object?>>> Handle(
|
||||
TSerialized deserializedPropertyValue,
|
||||
IProperty property,
|
||||
string? culture,
|
||||
string? segment,
|
||||
bool published,
|
||||
IEnumerable<string> availableCultures) => Handle(deserializedPropertyValue, property, culture, segment, published);
|
||||
|
||||
/// <summary>
|
||||
/// Method that handle the deserialized object.
|
||||
/// </summary>
|
||||
@@ -121,6 +153,7 @@ public abstract class JsonPropertyIndexValueFactoryBase<TSerialized> : IProperty
|
||||
string? culture,
|
||||
string? segment,
|
||||
bool published,
|
||||
IEnumerable<string> availableCultures) =>
|
||||
Handle(deserializedPropertyValue, property, culture, segment, published);
|
||||
IEnumerable<string> availableCultures,
|
||||
IDictionary<Guid, IContentType> contentTypeDictionary)
|
||||
=> Handle(deserializedPropertyValue, property, culture, segment, published, availableCultures);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,12 @@ 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,
|
||||
IEnumerable<string> availableCultures, IDictionary<Guid, IContentType> contentTypeDictionary)
|
||||
=> Array.Empty<KeyValuePair<string, IEnumerable<object?>>>();
|
||||
|
||||
|
||||
[Obsolete("Use the overload with the availableCultures parameter instead, scheduled for removal in v14")]
|
||||
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published, IEnumerable<string> availableCultures) => Array.Empty<KeyValuePair<string, IEnumerable<object?>>>();
|
||||
|
||||
[Obsolete("Use the overload with the availableCultures parameter instead, scheduled for removal in v14")]
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using Examine;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.PropertyEditors;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Web.Common.DependencyInjection;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Examine;
|
||||
@@ -24,9 +27,26 @@ public abstract class BaseValueSetBuilder<TContent> : IValueSetBuilder<TContent>
|
||||
|
||||
[Obsolete("Use the overload that specifies availableCultures, scheduled for removal in v14")]
|
||||
protected void AddPropertyValue(IProperty property, string? culture, string? segment, IDictionary<string, IEnumerable<object?>>? values)
|
||||
=> AddPropertyValue(property, culture, segment, values, Enumerable.Empty<string>());
|
||||
=> AddPropertyValue(
|
||||
property,
|
||||
culture,
|
||||
segment,
|
||||
values,
|
||||
Enumerable.Empty<string>(),
|
||||
StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>().GetAll().ToDictionary(x=>x.Key));
|
||||
|
||||
protected void AddPropertyValue(IProperty property, string? culture, string? segment, IDictionary<string, IEnumerable<object?>>? values, IEnumerable<string> availableCultures)
|
||||
[Obsolete("Use the overload that specifies availableCultures, scheduled for removal in v14")]
|
||||
protected void AddPropertyValue(IProperty property, string? culture, string? segment,
|
||||
IDictionary<string, IEnumerable<object?>>? values, IEnumerable<string> availableCultures)
|
||||
=> AddPropertyValue(
|
||||
property,
|
||||
culture,
|
||||
segment,
|
||||
values,
|
||||
Enumerable.Empty<string>(),
|
||||
StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>().GetAll().ToDictionary(x=>x.Key));
|
||||
|
||||
protected void AddPropertyValue(IProperty property, string? culture, string? segment, IDictionary<string, IEnumerable<object?>>? values, IEnumerable<string> availableCultures, IDictionary<Guid, IContentType> contentTypeDictionary)
|
||||
{
|
||||
IDataEditor? editor = _propertyEditors[property.PropertyType.PropertyEditorAlias];
|
||||
if (editor == null)
|
||||
@@ -35,7 +55,7 @@ public abstract class BaseValueSetBuilder<TContent> : IValueSetBuilder<TContent>
|
||||
}
|
||||
|
||||
IEnumerable<KeyValuePair<string, IEnumerable<object?>>> indexVals =
|
||||
editor.PropertyIndexValueFactory.GetIndexValues(property, culture, segment, PublishedValuesOnly, availableCultures);
|
||||
editor.PropertyIndexValueFactory.GetIndexValues(property, culture, segment, PublishedValuesOnly, availableCultures, contentTypeDictionary);
|
||||
foreach (KeyValuePair<string, IEnumerable<object?>> keyVal in indexVals)
|
||||
{
|
||||
if (keyVal.Key.IsNullOrWhiteSpace())
|
||||
|
||||
@@ -21,13 +21,34 @@ public class ContentValueSetBuilder : BaseValueSetBuilder<IContent>, IContentVal
|
||||
private static readonly object[] NoValue = new[] { "n" };
|
||||
private static readonly object[] YesValue = new[] { "y" };
|
||||
|
||||
private readonly IScopeProvider _scopeProvider;
|
||||
private readonly ICoreScopeProvider _scopeProvider;
|
||||
|
||||
private readonly IShortStringHelper _shortStringHelper;
|
||||
private readonly UrlSegmentProviderCollection _urlSegmentProviders;
|
||||
private readonly IUserService _userService;
|
||||
private readonly ILocalizationService _localizationService;
|
||||
private readonly IContentTypeService _contentTypeService;
|
||||
|
||||
public ContentValueSetBuilder(
|
||||
PropertyEditorCollection propertyEditors,
|
||||
UrlSegmentProviderCollection urlSegmentProviders,
|
||||
IUserService userService,
|
||||
IShortStringHelper shortStringHelper,
|
||||
ICoreScopeProvider scopeProvider,
|
||||
bool publishedValuesOnly,
|
||||
ILocalizationService localizationService,
|
||||
IContentTypeService contentTypeService)
|
||||
: base(propertyEditors, publishedValuesOnly)
|
||||
{
|
||||
_urlSegmentProviders = urlSegmentProviders;
|
||||
_userService = userService;
|
||||
_shortStringHelper = shortStringHelper;
|
||||
_scopeProvider = scopeProvider;
|
||||
_localizationService = localizationService;
|
||||
_contentTypeService = contentTypeService;
|
||||
}
|
||||
|
||||
[Obsolete("Use non-obsolete ctor, scheduled for removal in v14")]
|
||||
public ContentValueSetBuilder(
|
||||
PropertyEditorCollection propertyEditors,
|
||||
UrlSegmentProviderCollection urlSegmentProviders,
|
||||
@@ -36,16 +57,20 @@ public class ContentValueSetBuilder : BaseValueSetBuilder<IContent>, IContentVal
|
||||
IScopeProvider scopeProvider,
|
||||
bool publishedValuesOnly,
|
||||
ILocalizationService localizationService)
|
||||
: base(propertyEditors, publishedValuesOnly)
|
||||
: this(
|
||||
propertyEditors,
|
||||
urlSegmentProviders,
|
||||
userService,
|
||||
shortStringHelper,
|
||||
scopeProvider,
|
||||
publishedValuesOnly,
|
||||
localizationService,
|
||||
StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>())
|
||||
{
|
||||
_urlSegmentProviders = urlSegmentProviders;
|
||||
_userService = userService;
|
||||
_shortStringHelper = shortStringHelper;
|
||||
_scopeProvider = scopeProvider;
|
||||
_localizationService = localizationService;
|
||||
|
||||
}
|
||||
|
||||
[Obsolete("Use the constructor that takes an ILocalizationService, scheduled for removal in v14")]
|
||||
[Obsolete("Use non-obsolete ctor, scheduled for removal in v14")]
|
||||
public ContentValueSetBuilder(
|
||||
PropertyEditorCollection propertyEditors,
|
||||
UrlSegmentProviderCollection urlSegmentProviders,
|
||||
@@ -60,7 +85,8 @@ public class ContentValueSetBuilder : BaseValueSetBuilder<IContent>, IContentVal
|
||||
shortStringHelper,
|
||||
scopeProvider,
|
||||
publishedValuesOnly,
|
||||
StaticServiceProvider.Instance.GetRequiredService<ILocalizationService>())
|
||||
StaticServiceProvider.Instance.GetRequiredService<ILocalizationService>(),
|
||||
StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -72,7 +98,7 @@ public class ContentValueSetBuilder : BaseValueSetBuilder<IContent>, IContentVal
|
||||
|
||||
// We can lookup all of the creator/writer names at once which can save some
|
||||
// processing below instead of one by one.
|
||||
using (IScope scope = _scopeProvider.CreateScope())
|
||||
using (ICoreScope scope = _scopeProvider.CreateCoreScope())
|
||||
{
|
||||
creatorIds = _userService.GetProfilesById(content.Select(x => x.CreatorId).ToArray())
|
||||
.ToDictionary(x => x.Id, x => x);
|
||||
@@ -86,6 +112,8 @@ public class ContentValueSetBuilder : BaseValueSetBuilder<IContent>, IContentVal
|
||||
|
||||
private IEnumerable<ValueSet> GetValueSetsEnumerable(IContent[] content, Dictionary<int, IProfile> creatorIds, Dictionary<int, IProfile> writerIds)
|
||||
{
|
||||
IDictionary<Guid, IContentType> contentTypeDictionary = _contentTypeService.GetAll().ToDictionary(x => x.Key);
|
||||
|
||||
// TODO: There is a lot of boxing going on here and ultimately all values will be boxed by Lucene anyways
|
||||
// but I wonder if there's a way to reduce the boxing that we have to do or if it will matter in the end since
|
||||
// Lucene will do it no matter what? One idea was to create a `FieldValue` struct which would contain `object`, `object[]`, `ValueType` and `ValueType[]`
|
||||
@@ -162,13 +190,13 @@ public class ContentValueSetBuilder : BaseValueSetBuilder<IContent>, IContentVal
|
||||
{
|
||||
if (!property.PropertyType.VariesByCulture())
|
||||
{
|
||||
AddPropertyValue(property, null, null, values, availableCultures);
|
||||
AddPropertyValue(property, null, null, values, availableCultures, contentTypeDictionary);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var culture in c.AvailableCultures)
|
||||
{
|
||||
AddPropertyValue(property, culture.ToLowerInvariant(), null, values, availableCultures);
|
||||
AddPropertyValue(property, culture.ToLowerInvariant(), null, values, availableCultures, contentTypeDictionary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
using Examine;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.PropertyEditors;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Strings;
|
||||
using Umbraco.Cms.Web.Common.DependencyInjection;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Examine;
|
||||
@@ -14,6 +16,7 @@ public class MediaValueSetBuilder : BaseValueSetBuilder<IMedia>
|
||||
private readonly ContentSettings _contentSettings;
|
||||
private readonly MediaUrlGeneratorCollection _mediaUrlGenerators;
|
||||
private readonly IShortStringHelper _shortStringHelper;
|
||||
private readonly IContentTypeService _contentTypeService;
|
||||
private readonly UrlSegmentProviderCollection _urlSegmentProviders;
|
||||
private readonly IUserService _userService;
|
||||
|
||||
@@ -23,19 +26,41 @@ public class MediaValueSetBuilder : BaseValueSetBuilder<IMedia>
|
||||
MediaUrlGeneratorCollection mediaUrlGenerators,
|
||||
IUserService userService,
|
||||
IShortStringHelper shortStringHelper,
|
||||
IOptions<ContentSettings> contentSettings)
|
||||
IOptions<ContentSettings> contentSettings,
|
||||
IContentTypeService contentTypeService)
|
||||
: base(propertyEditors, false)
|
||||
{
|
||||
_urlSegmentProviders = urlSegmentProviders;
|
||||
_mediaUrlGenerators = mediaUrlGenerators;
|
||||
_userService = userService;
|
||||
_shortStringHelper = shortStringHelper;
|
||||
_contentTypeService = contentTypeService;
|
||||
_contentSettings = contentSettings.Value;
|
||||
}
|
||||
|
||||
[Obsolete("Use non-obsolete ctor, scheduled for removal in v14")]
|
||||
public MediaValueSetBuilder(
|
||||
PropertyEditorCollection propertyEditors,
|
||||
UrlSegmentProviderCollection urlSegmentProviders,
|
||||
MediaUrlGeneratorCollection mediaUrlGenerators,
|
||||
IUserService userService,
|
||||
IShortStringHelper shortStringHelper,
|
||||
IOptions<ContentSettings> contentSettings)
|
||||
: this(propertyEditors,
|
||||
urlSegmentProviders,
|
||||
mediaUrlGenerators,
|
||||
userService,
|
||||
shortStringHelper,
|
||||
contentSettings,
|
||||
StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>())
|
||||
{
|
||||
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public override IEnumerable<ValueSet> GetValueSets(params IMedia[] media)
|
||||
{
|
||||
IDictionary<Guid, IContentType> contentTypeDictionary = _contentTypeService.GetAll().ToDictionary(x => x.Key);
|
||||
|
||||
foreach (IMedia m in media)
|
||||
{
|
||||
var urlValue = m.GetUrlSegment(_shortStringHelper, _urlSegmentProviders);
|
||||
@@ -65,7 +90,7 @@ public class MediaValueSetBuilder : BaseValueSetBuilder<IMedia>
|
||||
|
||||
foreach (IProperty property in m.Properties)
|
||||
{
|
||||
AddPropertyValue(property, null, null, values, m.AvailableCultures);
|
||||
AddPropertyValue(property, null, null, values, m.AvailableCultures, contentTypeDictionary);
|
||||
}
|
||||
|
||||
var vs = new ValueSet(m.Id.ToInvariantString(), IndexTypes.Media, m.ContentType.Alias, values);
|
||||
|
||||
@@ -1,20 +1,34 @@
|
||||
using Examine;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.PropertyEditors;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Web.Common.DependencyInjection;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Examine;
|
||||
|
||||
public class MemberValueSetBuilder : BaseValueSetBuilder<IMember>
|
||||
{
|
||||
public MemberValueSetBuilder(PropertyEditorCollection propertyEditors)
|
||||
private readonly IContentTypeService _contentTypeService;
|
||||
|
||||
public MemberValueSetBuilder(PropertyEditorCollection propertyEditors, IContentTypeService contentTypeService)
|
||||
: base(propertyEditors, false)
|
||||
{
|
||||
_contentTypeService = contentTypeService;
|
||||
}
|
||||
|
||||
[Obsolete("Use non-obsolete ctor, scheduled for removal in v14")]
|
||||
public MemberValueSetBuilder(PropertyEditorCollection propertyEditors)
|
||||
: this(propertyEditors, StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>())
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEnumerable<ValueSet> GetValueSets(params IMember[] members)
|
||||
{
|
||||
IDictionary<Guid, IContentType> contentTypeDictionary = _contentTypeService.GetAll().ToDictionary(x => x.Key);
|
||||
|
||||
foreach (IMember m in members)
|
||||
{
|
||||
var values = new Dictionary<string, IEnumerable<object?>>
|
||||
@@ -37,7 +51,7 @@ public class MemberValueSetBuilder : BaseValueSetBuilder<IMember>
|
||||
|
||||
foreach (IProperty property in m.Properties)
|
||||
{
|
||||
AddPropertyValue(property, null, null, values, m.AvailableCultures);
|
||||
AddPropertyValue(property, null, null, values, m.AvailableCultures, contentTypeDictionary);
|
||||
}
|
||||
|
||||
var vs = new ValueSet(m.Id.ToInvariantString(), IndexTypes.Member, m.ContentType.Alias, values);
|
||||
|
||||
@@ -38,10 +38,13 @@ internal sealed class BlockValuePropertyIndexValueFactory :
|
||||
_contentTypeService = contentTypeService;
|
||||
}
|
||||
|
||||
|
||||
[Obsolete("Use non-obsolete overload, scheduled for removal in v14")]
|
||||
protected override IContentType? GetContentTypeOfNestedItem(BlockItemData input) =>
|
||||
_contentTypeService.Get(input.ContentTypeKey);
|
||||
|
||||
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.RawPropertyValues;
|
||||
|
||||
|
||||
@@ -2,19 +2,20 @@
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Runtime.Serialization;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Cms.Core.IO;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.ContentEditing;
|
||||
using Umbraco.Cms.Core.Models.Editors;
|
||||
using Umbraco.Cms.Core.Models.Entities;
|
||||
using Umbraco.Cms.Core.Models.PublishedContent;
|
||||
using Umbraco.Cms.Core.PublishedCache;
|
||||
using Umbraco.Cms.Core.Routing;
|
||||
using Umbraco.Cms.Core.Serialization;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Strings;
|
||||
using Umbraco.Extensions;
|
||||
using Umbraco.Cms.Web.Common.DependencyInjection;
|
||||
|
||||
namespace Umbraco.Cms.Core.PropertyEditors;
|
||||
|
||||
@@ -26,11 +27,57 @@ public class MultiUrlPickerValueEditor : DataValueEditor, IDataValueReference
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
};
|
||||
|
||||
private readonly IEntityService _entityService;
|
||||
private readonly ILogger<MultiUrlPickerValueEditor> _logger;
|
||||
private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
|
||||
private readonly IPublishedUrlProvider _publishedUrlProvider;
|
||||
private readonly IContentService _contentService;
|
||||
private readonly IMediaService _mediaService;
|
||||
|
||||
public MultiUrlPickerValueEditor(
|
||||
ILogger<MultiUrlPickerValueEditor> logger,
|
||||
ILocalizedTextService localizedTextService,
|
||||
IShortStringHelper shortStringHelper,
|
||||
DataEditorAttribute attribute,
|
||||
IPublishedUrlProvider publishedUrlProvider,
|
||||
IJsonSerializer jsonSerializer,
|
||||
IIOHelper ioHelper,
|
||||
IContentService contentService,
|
||||
IMediaService mediaService)
|
||||
: base(localizedTextService, shortStringHelper, jsonSerializer, ioHelper, attribute)
|
||||
{
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_publishedUrlProvider = publishedUrlProvider;
|
||||
_contentService = contentService;
|
||||
_mediaService = mediaService;
|
||||
}
|
||||
|
||||
[Obsolete("Use non-obsolete constructor. Scheduled for removal in Umbraco 14.")]
|
||||
public MultiUrlPickerValueEditor(
|
||||
IEntityService entityService,
|
||||
IPublishedSnapshotAccessor publishedSnapshotAccessor,
|
||||
ILogger<MultiUrlPickerValueEditor> logger,
|
||||
ILocalizedTextService localizedTextService,
|
||||
IShortStringHelper shortStringHelper,
|
||||
DataEditorAttribute attribute,
|
||||
IPublishedUrlProvider publishedUrlProvider,
|
||||
IJsonSerializer jsonSerializer,
|
||||
IIOHelper ioHelper,
|
||||
IContentService contentService,
|
||||
IMediaService mediaService)
|
||||
:this(
|
||||
logger,
|
||||
localizedTextService,
|
||||
shortStringHelper,
|
||||
attribute,
|
||||
publishedUrlProvider,
|
||||
jsonSerializer,
|
||||
ioHelper,
|
||||
contentService,
|
||||
mediaService)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[Obsolete("Use non-obsolete constructor. Scheduled for removal in Umbraco 14.")]
|
||||
public MultiUrlPickerValueEditor(
|
||||
IEntityService entityService,
|
||||
IPublishedSnapshotAccessor publishedSnapshotAccessor,
|
||||
@@ -41,13 +88,18 @@ public class MultiUrlPickerValueEditor : DataValueEditor, IDataValueReference
|
||||
IPublishedUrlProvider publishedUrlProvider,
|
||||
IJsonSerializer jsonSerializer,
|
||||
IIOHelper ioHelper)
|
||||
: base(localizedTextService, shortStringHelper, jsonSerializer, ioHelper, attribute)
|
||||
: this(
|
||||
logger,
|
||||
localizedTextService,
|
||||
shortStringHelper,
|
||||
attribute,
|
||||
publishedUrlProvider,
|
||||
jsonSerializer,
|
||||
ioHelper,
|
||||
StaticServiceProvider.Instance.GetRequiredService<IContentService>(),
|
||||
StaticServiceProvider.Instance.GetRequiredService<IMediaService>())
|
||||
{
|
||||
_entityService = entityService ?? throw new ArgumentNullException(nameof(entityService));
|
||||
_publishedSnapshotAccessor = publishedSnapshotAccessor ??
|
||||
throw new ArgumentNullException(nameof(publishedSnapshotAccessor));
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_publishedUrlProvider = publishedUrlProvider;
|
||||
|
||||
}
|
||||
|
||||
public IEnumerable<UmbracoEntityReference> GetReferences(object? value)
|
||||
@@ -86,26 +138,6 @@ public class MultiUrlPickerValueEditor : DataValueEditor, IDataValueReference
|
||||
{
|
||||
List<LinkDto>? links = JsonConvert.DeserializeObject<List<LinkDto>>(value);
|
||||
|
||||
List<LinkDto>? documentLinks = links?.FindAll(link =>
|
||||
link.Udi != null && link.Udi.EntityType == Constants.UdiEntityType.Document);
|
||||
List<LinkDto>? mediaLinks = links?.FindAll(link =>
|
||||
link.Udi != null && link.Udi.EntityType == Constants.UdiEntityType.Media);
|
||||
|
||||
var entities = new List<IEntitySlim>();
|
||||
if (documentLinks?.Count > 0)
|
||||
{
|
||||
entities.AddRange(
|
||||
_entityService.GetAll(
|
||||
UmbracoObjectTypes.Document,
|
||||
documentLinks.Select(link => link.Udi!.Guid).ToArray()));
|
||||
}
|
||||
|
||||
if (mediaLinks?.Count > 0)
|
||||
{
|
||||
entities.AddRange(
|
||||
_entityService.GetAll(UmbracoObjectTypes.Media, mediaLinks.Select(link => link.Udi!.Guid).ToArray()));
|
||||
}
|
||||
|
||||
var result = new List<LinkDisplay>();
|
||||
if (links is null)
|
||||
{
|
||||
@@ -114,7 +146,7 @@ public class MultiUrlPickerValueEditor : DataValueEditor, IDataValueReference
|
||||
|
||||
foreach (LinkDto dto in links)
|
||||
{
|
||||
GuidUdi? udi = null;
|
||||
GuidUdi? udi = dto.Udi;
|
||||
var icon = "icon-link";
|
||||
var published = true;
|
||||
var trashed = false;
|
||||
@@ -122,35 +154,30 @@ public class MultiUrlPickerValueEditor : DataValueEditor, IDataValueReference
|
||||
|
||||
if (dto.Udi != null)
|
||||
{
|
||||
IUmbracoEntity? entity = entities.Find(e => e.Key == dto.Udi.Guid);
|
||||
if (entity == null)
|
||||
if (dto.Udi.EntityType == Constants.UdiEntityType.Document)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
url = _publishedUrlProvider.GetUrl(dto.Udi.Guid, UrlMode.Relative, culture);
|
||||
IContent? c = _contentService.GetById(dto.Udi.Guid);
|
||||
|
||||
IPublishedSnapshot publishedSnapshot = _publishedSnapshotAccessor.GetRequiredPublishedSnapshot();
|
||||
if (entity is IDocumentEntitySlim documentEntity)
|
||||
{
|
||||
icon = documentEntity.ContentTypeIcon;
|
||||
published = culture == null
|
||||
? documentEntity.Published
|
||||
: documentEntity.PublishedCultures.Contains(culture);
|
||||
udi = new GuidUdi(Constants.UdiEntityType.Document, documentEntity.Key);
|
||||
url = publishedSnapshot.Content?.GetById(entity.Key)?.Url(_publishedUrlProvider) ?? "#";
|
||||
trashed = documentEntity.Trashed;
|
||||
if (c is not null)
|
||||
{
|
||||
published = culture == null
|
||||
? c.Published
|
||||
: c.PublishedCultures.Contains(culture);
|
||||
icon = c.ContentType.Icon;
|
||||
trashed = c.Trashed;
|
||||
}
|
||||
}
|
||||
else if (entity is IContentEntitySlim contentEntity)
|
||||
else if (dto.Udi.EntityType == Constants.UdiEntityType.Media)
|
||||
{
|
||||
icon = contentEntity.ContentTypeIcon;
|
||||
published = !contentEntity.Trashed;
|
||||
udi = new GuidUdi(Constants.UdiEntityType.Media, contentEntity.Key);
|
||||
url = publishedSnapshot.Media?.GetById(entity.Key)?.Url(_publishedUrlProvider) ?? "#";
|
||||
trashed = contentEntity.Trashed;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not supported
|
||||
continue;
|
||||
url = _publishedUrlProvider.GetMediaUrl(dto.Udi.Guid, UrlMode.Relative, culture);
|
||||
IMedia? m = _mediaService.GetById(dto.Udi.Guid);
|
||||
if (m is not null)
|
||||
{
|
||||
published = m.Trashed is false;
|
||||
icon = m.ContentType.Icon;
|
||||
trashed = m.Trashed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,11 @@ internal sealed class NestedContentPropertyIndexValueFactory
|
||||
_contentTypeService = contentTypeService;
|
||||
}
|
||||
|
||||
protected override IContentType? GetContentTypeOfNestedItem(
|
||||
NestedContentPropertyEditor.NestedContentValues.NestedContentRowValue input, IDictionary<Guid, IContentType> contentTypeDictionary)
|
||||
=> contentTypeDictionary.Values.FirstOrDefault(x=>x.Alias.Equals(input.ContentTypeAlias));
|
||||
|
||||
[Obsolete("Use non-obsolete overload, scheduled for removal in v14")]
|
||||
protected override IContentType? GetContentTypeOfNestedItem(
|
||||
NestedContentPropertyEditor.NestedContentValues.NestedContentRowValue input)
|
||||
=> _contentTypeService.Get(input.ContentTypeAlias);
|
||||
|
||||
@@ -4,6 +4,7 @@ using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Serialization;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Infrastructure.Examine;
|
||||
using Umbraco.Cms.Web.Common.DependencyInjection;
|
||||
using Umbraco.Extensions;
|
||||
@@ -42,20 +43,39 @@ internal abstract class NestedPropertyIndexValueFactoryBase<TSerialized, TItem>
|
||||
bool published) =>
|
||||
Handle(deserializedPropertyValue, property, culture, segment, published, Enumerable.Empty<string>());
|
||||
|
||||
[Obsolete("Use the overload that specifies availableCultures, scheduled for removal in v14")]
|
||||
protected override IEnumerable<KeyValuePair<string, IEnumerable<object?>>> Handle(
|
||||
TSerialized deserializedPropertyValue,
|
||||
IProperty property,
|
||||
string? culture,
|
||||
string? segment,
|
||||
bool published,
|
||||
IEnumerable<string> availableCultures)
|
||||
IEnumerable<string> availableCultures) =>
|
||||
Handle(
|
||||
deserializedPropertyValue,
|
||||
property,
|
||||
culture,
|
||||
segment,
|
||||
published,
|
||||
Enumerable.Empty<string>(),
|
||||
StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>().GetAll().ToDictionary(x=>x.Key));
|
||||
|
||||
|
||||
protected override IEnumerable<KeyValuePair<string, IEnumerable<object?>>> Handle(
|
||||
TSerialized deserializedPropertyValue,
|
||||
IProperty property,
|
||||
string? culture,
|
||||
string? segment,
|
||||
bool published,
|
||||
IEnumerable<string> availableCultures,
|
||||
IDictionary<Guid, IContentType> contentTypeDictionary)
|
||||
{
|
||||
var result = new List<KeyValuePair<string, IEnumerable<object?>>>();
|
||||
|
||||
var index = 0;
|
||||
foreach (TItem nestedContentRowValue in GetDataItems(deserializedPropertyValue))
|
||||
{
|
||||
IContentType? contentType = GetContentTypeOfNestedItem(nestedContentRowValue);
|
||||
IContentType? contentType = GetContentTypeOfNestedItem(nestedContentRowValue, contentTypeDictionary);
|
||||
|
||||
if (contentType is null)
|
||||
{
|
||||
@@ -125,6 +145,9 @@ internal abstract class NestedPropertyIndexValueFactoryBase<TSerialized, TItem>
|
||||
/// <summary>
|
||||
/// Gets the content type using the nested item.
|
||||
/// </summary>
|
||||
protected abstract IContentType? GetContentTypeOfNestedItem(TItem nestedItem, IDictionary<Guid, IContentType> contentTypeDictionary);
|
||||
|
||||
[Obsolete("Use non-obsolete overload. Scheduled for removal in Umbraco 14.")]
|
||||
protected abstract IContentType? GetContentTypeOfNestedItem(TItem nestedItem);
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user