Merge remote-tracking branch 'origin/v10/dev' into v11/dev

This commit is contained in:
Bjarke Berg
2023-11-14 09:29:59 +01:00
13 changed files with 294 additions and 98 deletions

View File

@@ -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>());
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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")]

View File

@@ -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())

View File

@@ -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);
}
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;
}
}
}

View File

@@ -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);

View File

@@ -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>

View File

@@ -224,7 +224,7 @@ AND cmsContentNu.nodeId IS NULL
IContentCacheDataSerializer serializer =
_contentCacheDataSerializerFactory.Create(ContentCacheDataSerializerEntityType.Document);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql, Constants.ObjectTypes.Document);
foreach (ContentSourceDto row in dtos)
{
@@ -242,7 +242,7 @@ AND cmsContentNu.nodeId IS NULL
IContentCacheDataSerializer serializer =
_contentCacheDataSerializerFactory.Create(ContentCacheDataSerializerEntityType.Document);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql, Constants.ObjectTypes.Document);
foreach (ContentSourceDto row in dtos)
{
@@ -265,7 +265,7 @@ AND cmsContentNu.nodeId IS NULL
IContentCacheDataSerializer serializer =
_contentCacheDataSerializerFactory.Create(ContentCacheDataSerializerEntityType.Document);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql, Constants.ObjectTypes.Document);
foreach (ContentSourceDto row in dtos)
{
@@ -301,7 +301,7 @@ AND cmsContentNu.nodeId IS NULL
IContentCacheDataSerializer serializer =
_contentCacheDataSerializerFactory.Create(ContentCacheDataSerializerEntityType.Media);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql, Constants.ObjectTypes.Media);
foreach (ContentSourceDto row in dtos)
{
@@ -319,7 +319,7 @@ AND cmsContentNu.nodeId IS NULL
IContentCacheDataSerializer serializer =
_contentCacheDataSerializerFactory.Create(ContentCacheDataSerializerEntityType.Media);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql, Constants.ObjectTypes.Media);
foreach (ContentSourceDto row in dtos)
{
@@ -342,7 +342,7 @@ AND cmsContentNu.nodeId IS NULL
IContentCacheDataSerializer serializer =
_contentCacheDataSerializerFactory.Create(ContentCacheDataSerializerEntityType.Media);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql);
IEnumerable<ContentSourceDto> dtos = GetContentNodeDtos(sql, Constants.ObjectTypes.Media);
foreach (ContentSourceDto row in dtos)
{
@@ -990,7 +990,7 @@ WHERE cmsContentNu.nodeId IN (
return s;
}
private IEnumerable<ContentSourceDto> GetContentNodeDtos(Sql<ISqlContext> sql)
private IEnumerable<ContentSourceDto> GetContentNodeDtos(Sql<ISqlContext> sql, Guid nodeObjectType)
{
// We need to page here. We don't want to iterate over every single row in one connection cuz this can cause an SQL Timeout.
// We also want to read with a db reader and not load everything into memory, QueryPaged lets us do that.
@@ -1000,7 +1000,7 @@ WHERE cmsContentNu.nodeId IN (
{
// Use a more efficient COUNT query
Sql<ISqlContext>? sqlCountQuery = SqlContentSourcesCount()
.Append(SqlObjectTypeNotTrashed(SqlContext, Constants.ObjectTypes.Document));
.Append(SqlObjectTypeNotTrashed(SqlContext, nodeObjectType));
Sql<ISqlContext>? sqlCount =
SqlContext.Sql("SELECT COUNT(*) FROM (").Append(sqlCountQuery).Append(") npoco_tbl");