diff --git a/src/Umbraco.Core/PropertyEditors/DefaultPropertyIndexValueFactory.cs b/src/Umbraco.Core/PropertyEditors/DefaultPropertyIndexValueFactory.cs index 0193f45778..e0ec2c4ccf 100644 --- a/src/Umbraco.Core/PropertyEditors/DefaultPropertyIndexValueFactory.cs +++ b/src/Umbraco.Core/PropertyEditors/DefaultPropertyIndexValueFactory.cs @@ -9,15 +9,22 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class DefaultPropertyIndexValueFactory : IPropertyIndexValueFactory { - /// - public IEnumerable>> GetIndexValues(IProperty property, string? culture, string? segment, bool published, IEnumerable availableCultures) + public IEnumerable>> GetIndexValues(IProperty property, string? culture, string? segment, bool published, + IEnumerable availableCultures, IDictionary contentTypeDictionary) { yield return new KeyValuePair>( property.Alias, property.GetValue(culture, segment, published).Yield()); } - [Obsolete("Use the overload with the availableCultures parameter instead, scheduled for removal in v14")] + /// + [Obsolete("Use the non-obsolete overload, scheduled for removal in v14")] + public IEnumerable>> GetIndexValues(IProperty property, string? culture, + string? segment, bool published, IEnumerable availableCultures) + => GetIndexValues(property, culture, segment, published, availableCultures, + new Dictionary()); + + [Obsolete("Use the non-obsolete overload, scheduled for removal in v14")] public IEnumerable>> GetIndexValues(IProperty property, string? culture, string? segment, bool published) - => GetIndexValues(property, culture, segment, published, Enumerable.Empty()); + => GetIndexValues(property, culture, segment, published, Enumerable.Empty(), new Dictionary()); } diff --git a/src/Umbraco.Core/PropertyEditors/IPropertyIndexValueFactory.cs b/src/Umbraco.Core/PropertyEditors/IPropertyIndexValueFactory.cs index 732644b288..8f8b64a9eb 100644 --- a/src/Umbraco.Core/PropertyEditors/IPropertyIndexValueFactory.cs +++ b/src/Umbraco.Core/PropertyEditors/IPropertyIndexValueFactory.cs @@ -22,9 +22,14 @@ public interface IPropertyIndexValueFactory /// more than one value for a given field. /// /// + IEnumerable>> GetIndexValues(IProperty property, string? culture, + string? segment, bool published, IEnumerable availableCultures, + IDictionary contentTypeDictionary) => GetIndexValues(property, culture, segment, published); + + [Obsolete("Use non-obsolete overload, scheduled for removal in v14")] IEnumerable>> GetIndexValues(IProperty property, string? culture, string? segment, bool published, IEnumerable 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>> GetIndexValues(IProperty property, string? culture, string? segment, bool published); } diff --git a/src/Umbraco.Core/PropertyEditors/JsonPropertyIndexValueFactoryBase.cs b/src/Umbraco.Core/PropertyEditors/JsonPropertyIndexValueFactoryBase.cs index bf549e2d2e..973ee3d40c 100644 --- a/src/Umbraco.Core/PropertyEditors/JsonPropertyIndexValueFactoryBase.cs +++ b/src/Umbraco.Core/PropertyEditors/JsonPropertyIndexValueFactoryBase.cs @@ -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 : IProperty } - /// public IEnumerable>> GetIndexValues( IProperty property, string? culture, string? segment, bool published, - IEnumerable availableCultures) + IEnumerable availableCultures, + IDictionary contentTypeDictionary) { var result = new List>>(); @@ -63,7 +64,7 @@ public abstract class JsonPropertyIndexValueFactoryBase : 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 : IProperty return summary; } + /// + [Obsolete("Use non-obsolete constructor. This will be removed in Umbraco 14.")] + public IEnumerable>> GetIndexValues( + IProperty property, + string? culture, + string? segment, + bool published, + IEnumerable availableCultures) + => GetIndexValues( + property, + culture, + segment, + published, + Enumerable.Empty(), + StaticServiceProvider.Instance.GetRequiredService().GetAll().ToDictionary(x=>x.Key)); + [Obsolete("Use method overload that has availableCultures, scheduled for removal in v14")] public IEnumerable>> GetIndexValues(IProperty property, string? culture, string? segment, bool published) - => GetIndexValues(property, culture, segment, published, Enumerable.Empty()); + => GetIndexValues( + property, + culture, + segment, + published, + Enumerable.Empty(), + StaticServiceProvider.Instance.GetRequiredService().GetAll().ToDictionary(x=>x.Key)); /// /// 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 : IProperty /// /// Method that handle the deserialized object. /// - [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>> Handle( TSerialized deserializedPropertyValue, IProperty property, @@ -112,6 +135,15 @@ public abstract class JsonPropertyIndexValueFactoryBase : IProperty string? segment, bool published); + [Obsolete("Use the non-obsolete overload instead, scheduled for removal in v14")] + protected virtual IEnumerable>> Handle( + TSerialized deserializedPropertyValue, + IProperty property, + string? culture, + string? segment, + bool published, + IEnumerable availableCultures) => Handle(deserializedPropertyValue, property, culture, segment, published); + /// /// Method that handle the deserialized object. /// @@ -121,6 +153,7 @@ public abstract class JsonPropertyIndexValueFactoryBase : IProperty string? culture, string? segment, bool published, - IEnumerable availableCultures) => - Handle(deserializedPropertyValue, property, culture, segment, published); + IEnumerable availableCultures, + IDictionary contentTypeDictionary) + => Handle(deserializedPropertyValue, property, culture, segment, published, availableCultures); } diff --git a/src/Umbraco.Core/PropertyEditors/NoopPropertyIndexValueFactory.cs b/src/Umbraco.Core/PropertyEditors/NoopPropertyIndexValueFactory.cs index 223f8632ff..004138e370 100644 --- a/src/Umbraco.Core/PropertyEditors/NoopPropertyIndexValueFactory.cs +++ b/src/Umbraco.Core/PropertyEditors/NoopPropertyIndexValueFactory.cs @@ -8,6 +8,12 @@ namespace Umbraco.Cms.Core.PropertyEditors; public class NoopPropertyIndexValueFactory : IPropertyIndexValueFactory { /// + public IEnumerable>> GetIndexValues(IProperty property, string? culture, string? segment, bool published, + IEnumerable availableCultures, IDictionary contentTypeDictionary) + => Array.Empty>>(); + + + [Obsolete("Use the overload with the availableCultures parameter instead, scheduled for removal in v14")] public IEnumerable>> GetIndexValues(IProperty property, string? culture, string? segment, bool published, IEnumerable availableCultures) => Array.Empty>>(); [Obsolete("Use the overload with the availableCultures parameter instead, scheduled for removal in v14")] diff --git a/src/Umbraco.Infrastructure/Examine/BaseValueSetBuilder.cs b/src/Umbraco.Infrastructure/Examine/BaseValueSetBuilder.cs index 3574c3077f..83ecd85da4 100644 --- a/src/Umbraco.Infrastructure/Examine/BaseValueSetBuilder.cs +++ b/src/Umbraco.Infrastructure/Examine/BaseValueSetBuilder.cs @@ -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 : IValueSetBuilder [Obsolete("Use the overload that specifies availableCultures, scheduled for removal in v14")] protected void AddPropertyValue(IProperty property, string? culture, string? segment, IDictionary>? values) - => AddPropertyValue(property, culture, segment, values, Enumerable.Empty()); + => AddPropertyValue( + property, + culture, + segment, + values, + Enumerable.Empty(), + StaticServiceProvider.Instance.GetRequiredService().GetAll().ToDictionary(x=>x.Key)); - protected void AddPropertyValue(IProperty property, string? culture, string? segment, IDictionary>? values, IEnumerable availableCultures) + [Obsolete("Use the overload that specifies availableCultures, scheduled for removal in v14")] + protected void AddPropertyValue(IProperty property, string? culture, string? segment, + IDictionary>? values, IEnumerable availableCultures) + => AddPropertyValue( + property, + culture, + segment, + values, + Enumerable.Empty(), + StaticServiceProvider.Instance.GetRequiredService().GetAll().ToDictionary(x=>x.Key)); + + protected void AddPropertyValue(IProperty property, string? culture, string? segment, IDictionary>? values, IEnumerable availableCultures, IDictionary contentTypeDictionary) { IDataEditor? editor = _propertyEditors[property.PropertyType.PropertyEditorAlias]; if (editor == null) @@ -35,7 +55,7 @@ public abstract class BaseValueSetBuilder : IValueSetBuilder } IEnumerable>> indexVals = - editor.PropertyIndexValueFactory.GetIndexValues(property, culture, segment, PublishedValuesOnly, availableCultures); + editor.PropertyIndexValueFactory.GetIndexValues(property, culture, segment, PublishedValuesOnly, availableCultures, contentTypeDictionary); foreach (KeyValuePair> keyVal in indexVals) { if (keyVal.Key.IsNullOrWhiteSpace()) diff --git a/src/Umbraco.Infrastructure/Examine/ContentValueSetBuilder.cs b/src/Umbraco.Infrastructure/Examine/ContentValueSetBuilder.cs index 228610879d..2d59e0ebe3 100644 --- a/src/Umbraco.Infrastructure/Examine/ContentValueSetBuilder.cs +++ b/src/Umbraco.Infrastructure/Examine/ContentValueSetBuilder.cs @@ -21,13 +21,34 @@ public class ContentValueSetBuilder : BaseValueSetBuilder, 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, IContentVal IScopeProvider scopeProvider, bool publishedValuesOnly, ILocalizationService localizationService) - : base(propertyEditors, publishedValuesOnly) + : this( + propertyEditors, + urlSegmentProviders, + userService, + shortStringHelper, + scopeProvider, + publishedValuesOnly, + localizationService, + StaticServiceProvider.Instance.GetRequiredService()) { - _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, IContentVal shortStringHelper, scopeProvider, publishedValuesOnly, - StaticServiceProvider.Instance.GetRequiredService()) + StaticServiceProvider.Instance.GetRequiredService(), + StaticServiceProvider.Instance.GetRequiredService()) { } @@ -72,7 +98,7 @@ public class ContentValueSetBuilder : BaseValueSetBuilder, 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, IContentVal private IEnumerable GetValueSetsEnumerable(IContent[] content, Dictionary creatorIds, Dictionary writerIds) { + IDictionary 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, 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); } } } diff --git a/src/Umbraco.Infrastructure/Examine/MediaValueSetBuilder.cs b/src/Umbraco.Infrastructure/Examine/MediaValueSetBuilder.cs index fa7d6509cd..d2da36b347 100644 --- a/src/Umbraco.Infrastructure/Examine/MediaValueSetBuilder.cs +++ b/src/Umbraco.Infrastructure/Examine/MediaValueSetBuilder.cs @@ -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 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 MediaUrlGeneratorCollection mediaUrlGenerators, IUserService userService, IShortStringHelper shortStringHelper, - IOptions contentSettings) + IOptions 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) + : this(propertyEditors, + urlSegmentProviders, + mediaUrlGenerators, + userService, + shortStringHelper, + contentSettings, + StaticServiceProvider.Instance.GetRequiredService()) + { + + } /// public override IEnumerable GetValueSets(params IMedia[] media) { + IDictionary 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 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); diff --git a/src/Umbraco.Infrastructure/Examine/MemberValueSetBuilder.cs b/src/Umbraco.Infrastructure/Examine/MemberValueSetBuilder.cs index 1b0bf7219f..8fe2a56856 100644 --- a/src/Umbraco.Infrastructure/Examine/MemberValueSetBuilder.cs +++ b/src/Umbraco.Infrastructure/Examine/MemberValueSetBuilder.cs @@ -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 { - 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()) { } /// public override IEnumerable GetValueSets(params IMember[] members) { + IDictionary contentTypeDictionary = _contentTypeService.GetAll().ToDictionary(x => x.Key); + foreach (IMember m in members) { var values = new Dictionary> @@ -37,7 +51,7 @@ public class MemberValueSetBuilder : BaseValueSetBuilder 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); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/BlockValuePropertyIndexValueFactory.cs b/src/Umbraco.Infrastructure/PropertyEditors/BlockValuePropertyIndexValueFactory.cs index adace6126e..95185a3f30 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/BlockValuePropertyIndexValueFactory.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/BlockValuePropertyIndexValueFactory.cs @@ -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 contentTypeDictionary) + => contentTypeDictionary.TryGetValue(input.ContentTypeKey, out var result) ? result : null; + protected override IDictionary GetRawProperty(BlockItemData blockItemData) => blockItemData.RawPropertyValues; diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerValueEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerValueEditor.cs index 9a7fa4b3bb..1b76cd89a5 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerValueEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerValueEditor.cs @@ -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 _logger; - private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor; private readonly IPublishedUrlProvider _publishedUrlProvider; + private readonly IContentService _contentService; + private readonly IMediaService _mediaService; + public MultiUrlPickerValueEditor( + ILogger 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 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(), + StaticServiceProvider.Instance.GetRequiredService()) { - _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 GetReferences(object? value) @@ -86,26 +138,6 @@ public class MultiUrlPickerValueEditor : DataValueEditor, IDataValueReference { List? links = JsonConvert.DeserializeObject>(value); - List? documentLinks = links?.FindAll(link => - link.Udi != null && link.Udi.EntityType == Constants.UdiEntityType.Document); - List? mediaLinks = links?.FindAll(link => - link.Udi != null && link.Udi.EntityType == Constants.UdiEntityType.Media); - - var entities = new List(); - 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(); 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; + } } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyIndexValueFactory.cs b/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyIndexValueFactory.cs index 121a40bec9..693c21060b 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyIndexValueFactory.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyIndexValueFactory.cs @@ -39,6 +39,11 @@ internal sealed class NestedContentPropertyIndexValueFactory _contentTypeService = contentTypeService; } + protected override IContentType? GetContentTypeOfNestedItem( + NestedContentPropertyEditor.NestedContentValues.NestedContentRowValue input, IDictionary 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); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/NestedPropertyIndexValueFactoryBase.cs b/src/Umbraco.Infrastructure/PropertyEditors/NestedPropertyIndexValueFactoryBase.cs index 94ed0a3e15..a675b38b2c 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/NestedPropertyIndexValueFactoryBase.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/NestedPropertyIndexValueFactoryBase.cs @@ -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 bool published) => Handle(deserializedPropertyValue, property, culture, segment, published, Enumerable.Empty()); + [Obsolete("Use the overload that specifies availableCultures, scheduled for removal in v14")] protected override IEnumerable>> Handle( TSerialized deserializedPropertyValue, IProperty property, string? culture, string? segment, bool published, - IEnumerable availableCultures) + IEnumerable availableCultures) => + Handle( + deserializedPropertyValue, + property, + culture, + segment, + published, + Enumerable.Empty(), + StaticServiceProvider.Instance.GetRequiredService().GetAll().ToDictionary(x=>x.Key)); + + + protected override IEnumerable>> Handle( + TSerialized deserializedPropertyValue, + IProperty property, + string? culture, + string? segment, + bool published, + IEnumerable availableCultures, + IDictionary contentTypeDictionary) { var result = new List>>(); 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 /// /// Gets the content type using the nested item. /// + protected abstract IContentType? GetContentTypeOfNestedItem(TItem nestedItem, IDictionary contentTypeDictionary); + + [Obsolete("Use non-obsolete overload. Scheduled for removal in Umbraco 14.")] protected abstract IContentType? GetContentTypeOfNestedItem(TItem nestedItem); ///