Merge branch 'v13/dev' into v14/dev
# Conflicts: # Directory.Packages.props # src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs # src/Umbraco.Core/Models/Mapping/ContentPropertyDisplayMapper.cs # src/Umbraco.Core/Services/DataTypeService.cs # src/Umbraco.Infrastructure/PropertyEditors/BlockEditorPropertyValueEditor.cs # src/Umbraco.Infrastructure/PropertyEditors/BlockValuePropertyValueEditorBase.cs # src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyValueEditor.cs # src/Umbraco.Infrastructure/PropertyEditors/MediaPicker3PropertyEditor.cs # src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyEditor.cs # src/Umbraco.Infrastructure/PropertyEditors/RichTextPropertyEditor.cs
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
|
||||
|
||||
51
src/Umbraco.Core/Cache/DataTypeConfigurationCache.cs
Normal file
51
src/Umbraco.Core/Cache/DataTypeConfigurationCache.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Core.Cache;
|
||||
|
||||
/// <summary>
|
||||
/// This cache is a temporary measure to reduce the amount of computational power required to deserialize and initialize <see cref="IDataType" /> when fetched from the main cache/database,
|
||||
/// because datatypes are fetched multiple times troughout a (backoffice content) request with a lot of content (or nested content) and each of these fetches initializes certain fields on the datatypes.
|
||||
/// </summary>
|
||||
internal sealed class DataTypeConfigurationCache : IDataTypeConfigurationCache
|
||||
{
|
||||
private readonly IDataTypeService _dataTypeService;
|
||||
private readonly IMemoryCache _memoryCache;
|
||||
|
||||
public DataTypeConfigurationCache(IDataTypeService dataTypeService, IMemoryCache memoryCache, IIdKeyMap idKeyMap)
|
||||
{
|
||||
_dataTypeService = dataTypeService;
|
||||
_memoryCache = memoryCache;
|
||||
}
|
||||
|
||||
public T? GetConfigurationAs<T>(Guid key)
|
||||
where T : class
|
||||
{
|
||||
var cacheKey = GetCacheKey(key);
|
||||
if (_memoryCache.TryGetValue(cacheKey, out T? configuration) is false)
|
||||
{
|
||||
IDataType? dataType = _dataTypeService.GetDataType(key);
|
||||
configuration = dataType?.ConfigurationAs<T>();
|
||||
|
||||
// Only cache if data type was found (but still cache null configurations)
|
||||
if (dataType is not null)
|
||||
{
|
||||
_memoryCache.Set(cacheKey, configuration);
|
||||
}
|
||||
}
|
||||
|
||||
return configuration;
|
||||
}
|
||||
|
||||
public void ClearCache(IEnumerable<Guid> keys)
|
||||
{
|
||||
foreach (Guid key in keys)
|
||||
{
|
||||
_memoryCache.Remove(GetCacheKey(key));
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetCacheKey(Guid key) => $"DataTypeConfigurationCache_{key}";
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using Umbraco.Cms.Core.Events;
|
||||
using Umbraco.Cms.Core.Notifications;
|
||||
|
||||
namespace Umbraco.Cms.Core.Cache;
|
||||
|
||||
internal sealed class DataTypeConfigurationCacheRefresher : INotificationHandler<DataTypeCacheRefresherNotification>
|
||||
{
|
||||
private readonly IDataTypeConfigurationCache _dataTypeConfigurationCache;
|
||||
|
||||
public DataTypeConfigurationCacheRefresher(IDataTypeConfigurationCache dataTypeConfigurationCache)
|
||||
=> _dataTypeConfigurationCache = dataTypeConfigurationCache;
|
||||
|
||||
public void Handle(DataTypeCacheRefresherNotification notification)
|
||||
=> _dataTypeConfigurationCache.ClearCache(((DataTypeCacheRefresher.JsonPayload[])notification.MessageObject).Select(x => x.Key));
|
||||
}
|
||||
33
src/Umbraco.Core/Cache/IDataTypeConfigurationCache.cs
Normal file
33
src/Umbraco.Core/Cache/IDataTypeConfigurationCache.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
namespace Umbraco.Cms.Core.Cache;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a cache for <see cref="Umbraco.Cms.Core.Models.IDataType" /> configuration.
|
||||
/// </summary>
|
||||
public interface IDataTypeConfigurationCache
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the data type configuration.
|
||||
/// </summary>
|
||||
/// <param name="key">The data type key.</param>
|
||||
/// <returns>
|
||||
/// The data type configuration.
|
||||
/// </returns>
|
||||
object? GetConfiguration(Guid key) => GetConfigurationAs<object>(key);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data type configuration as <typeparamref name="T" />.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data type configuration type.</typeparam>
|
||||
/// <param name="key">The data type key.</param>
|
||||
/// <returns>
|
||||
/// The data type configuration as <typeparamref name="T" />.
|
||||
/// </returns>
|
||||
T? GetConfigurationAs<T>(Guid key)
|
||||
where T : class;
|
||||
|
||||
/// <summary>
|
||||
/// Clears the cache for the specified keys.
|
||||
/// </summary>
|
||||
/// <param name="keys">The keys.</param>
|
||||
void ClearCache(IEnumerable<Guid> keys);
|
||||
}
|
||||
@@ -371,6 +371,10 @@ namespace Umbraco.Cms.Core.DependencyInjection
|
||||
Services.AddUnique<IWebhookLogService, WebhookLogService>();
|
||||
Services.AddUnique<IWebhookLogFactory, WebhookLogFactory>();
|
||||
Services.AddUnique<IWebhookRequestService, WebhookRequestService>();
|
||||
|
||||
// Data type configuration cache
|
||||
Services.AddUnique<IDataTypeConfigurationCache, DataTypeConfigurationCache>();
|
||||
Services.AddNotificationHandler<DataTypeCacheRefresherNotification, DataTypeConfigurationCacheRefresher>();
|
||||
|
||||
//Two factor providers
|
||||
Services.AddUnique<ITwoFactorLoginService, TwoFactorLoginService>();
|
||||
|
||||
@@ -36,6 +36,8 @@ internal class ContentPropertyDisplayMapper : ContentPropertyBasicMapper<Content
|
||||
{
|
||||
base.Map(originalProp, dest, context);
|
||||
|
||||
// v13 to v14 merge note: because of changes in the IDataType we can not use the optimized IDataTypeConfigurationCache here
|
||||
// todo: make sure this (possible) performance degradation isn't serious
|
||||
IDataType? dataType = DataTypeService.GetDataType(originalProp.PropertyType.DataTypeId);
|
||||
|
||||
// TODO: IDataValueEditor configuration - general issue
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Cms.Core.Cache;
|
||||
using Umbraco.Cms.Core.DependencyInjection;
|
||||
using Umbraco.Cms.Core.Dictionary;
|
||||
using Umbraco.Cms.Core.Mapping;
|
||||
using Umbraco.Cms.Core.Models.ContentEditing;
|
||||
@@ -24,7 +27,8 @@ public class ContentPropertyMapDefinition : IMapDefinition
|
||||
IEntityService entityService,
|
||||
ILocalizedTextService textService,
|
||||
ILoggerFactory loggerFactory,
|
||||
PropertyEditorCollection propertyEditors)
|
||||
PropertyEditorCollection propertyEditors,
|
||||
IDataTypeConfigurationCache dataTypeConfigurationCache)
|
||||
{
|
||||
_contentPropertyBasicConverter = new ContentPropertyBasicMapper<ContentPropertyBasic>(
|
||||
dataTypeService,
|
||||
@@ -42,9 +46,28 @@ public class ContentPropertyMapDefinition : IMapDefinition
|
||||
entityService,
|
||||
textService,
|
||||
loggerFactory.CreateLogger<ContentPropertyDisplayMapper>(),
|
||||
propertyEditors);
|
||||
propertyEditors,
|
||||
dataTypeConfigurationCache);
|
||||
}
|
||||
|
||||
[Obsolete("Please use constructor that takes an IDataTypeConfigurationCache. Will be removed in V14.")]
|
||||
public ContentPropertyMapDefinition(
|
||||
ICultureDictionary cultureDictionary,
|
||||
IDataTypeService dataTypeService,
|
||||
IEntityService entityService,
|
||||
ILocalizedTextService textService,
|
||||
ILoggerFactory loggerFactory,
|
||||
PropertyEditorCollection propertyEditors)
|
||||
: this(
|
||||
cultureDictionary,
|
||||
dataTypeService,
|
||||
entityService,
|
||||
textService,
|
||||
loggerFactory,
|
||||
propertyEditors,
|
||||
StaticServiceProvider.Instance.GetRequiredService<IDataTypeConfigurationCache>())
|
||||
{ }
|
||||
|
||||
public void DefineMaps(IUmbracoMapper mapper)
|
||||
{
|
||||
mapper.Define<PropertyGroup, Tab<ContentPropertyDisplay>>(
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace Umbraco.Cms.Core.Services.Implement
|
||||
private readonly IIOHelper _ioHelper;
|
||||
private readonly IDataTypeContainerService _dataTypeContainerService;
|
||||
private readonly IUserIdKeyResolver _userIdKeyResolver;
|
||||
private readonly Lazy<IIdKeyMap> _idKeyMap;
|
||||
|
||||
public DataTypeService(
|
||||
ICoreScopeProvider provider,
|
||||
@@ -38,7 +39,8 @@ namespace Umbraco.Cms.Core.Services.Implement
|
||||
IDataValueEditorFactory dataValueEditorFactory,
|
||||
IAuditRepository auditRepository,
|
||||
IContentTypeRepository contentTypeRepository,
|
||||
IIOHelper ioHelper)
|
||||
IIOHelper ioHelper,
|
||||
Lazy<IIdKeyMap> idKeyMap)
|
||||
: base(provider, loggerFactory, eventMessagesFactory)
|
||||
{
|
||||
_dataValueEditorFactory = dataValueEditorFactory;
|
||||
@@ -46,6 +48,7 @@ namespace Umbraco.Cms.Core.Services.Implement
|
||||
_auditRepository = auditRepository;
|
||||
_contentTypeRepository = contentTypeRepository;
|
||||
_ioHelper = ioHelper;
|
||||
_idKeyMap = idKeyMap;
|
||||
|
||||
// resolve dependencies for obsolete methods through the static service provider, so they don't pollute the constructor signature
|
||||
_dataTypeContainerService = StaticServiceProvider.Instance.GetRequiredService<IDataTypeContainerService>();
|
||||
@@ -743,11 +746,11 @@ namespace Umbraco.Cms.Core.Services.Implement
|
||||
}
|
||||
|
||||
private IDataType? GetDataTypeFromRepository(Guid id)
|
||||
=> _idKeyMap.Value.GetIdForKey(id, UmbracoObjectTypes.DataType) switch
|
||||
{
|
||||
IQuery<IDataType> query = Query<IDataType>().Where(x => x.Key == id);
|
||||
IDataType? dataType = _dataTypeRepository.Get(query).FirstOrDefault();
|
||||
return dataType;
|
||||
}
|
||||
{ Success: false } => null,
|
||||
{ Result: var intId } => _dataTypeRepository.Get(intId),
|
||||
};
|
||||
|
||||
private void Audit(AuditType type, int userId, int objectId)
|
||||
=> _auditRepository.Save(new AuditItem(objectId, type, userId, ObjectTypes.GetName(UmbracoObjectTypes.DataType)));
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" />
|
||||
<PackageReference Include="Microsoft.Extensions.FileProviders.Physical" />
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// See LICENSE for more details.
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Cms.Core.Cache;
|
||||
using Umbraco.Cms.Core.IO;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Blocks;
|
||||
@@ -18,7 +19,7 @@ internal abstract class BlockEditorPropertyValueEditor<TValue, TLayout> : BlockV
|
||||
{
|
||||
private readonly IJsonSerializer _jsonSerializer;
|
||||
private BlockEditorValues<TValue, TLayout>? _blockEditorValues;
|
||||
private readonly IDataTypeService _dataTypeService;
|
||||
private readonly IDataTypeConfigurationCache _dataTypeConfigurationCache;
|
||||
private readonly PropertyEditorCollection _propertyEditors;
|
||||
private readonly DataValueReferenceFactoryCollection _dataValueReferenceFactories;
|
||||
|
||||
@@ -26,17 +27,17 @@ internal abstract class BlockEditorPropertyValueEditor<TValue, TLayout> : BlockV
|
||||
DataEditorAttribute attribute,
|
||||
PropertyEditorCollection propertyEditors,
|
||||
DataValueReferenceFactoryCollection dataValueReferenceFactories,
|
||||
IDataTypeService dataTypeService,
|
||||
IDataTypeConfigurationCache dataTypeConfigurationCache,
|
||||
ILocalizedTextService textService,
|
||||
ILogger<BlockEditorPropertyValueEditor<TValue, TLayout>> logger,
|
||||
IShortStringHelper shortStringHelper,
|
||||
IJsonSerializer jsonSerializer,
|
||||
IIOHelper ioHelper)
|
||||
: base(attribute, propertyEditors, dataTypeService, textService, logger, shortStringHelper, jsonSerializer, ioHelper, dataValueReferenceFactories)
|
||||
: base(attribute, propertyEditors, dataTypeConfigurationCache, textService, logger, shortStringHelper, jsonSerializer, ioHelper, dataValueReferenceFactories)
|
||||
{
|
||||
_propertyEditors = propertyEditors;
|
||||
_dataValueReferenceFactories = dataValueReferenceFactories;
|
||||
_dataTypeService = dataTypeService;
|
||||
_dataTypeConfigurationCache = dataTypeConfigurationCache;
|
||||
_jsonSerializer = jsonSerializer;
|
||||
}
|
||||
|
||||
@@ -76,7 +77,7 @@ internal abstract class BlockEditorPropertyValueEditor<TValue, TLayout> : BlockV
|
||||
continue;
|
||||
}
|
||||
|
||||
object? configuration = _dataTypeService.GetDataType(propertyValue.PropertyType.DataTypeKey)?.ConfigurationObject;
|
||||
object? configuration = _dataTypeConfigurationCache.GetConfiguration(propertyValue.PropertyType.DataTypeKey);
|
||||
foreach (ITag tag in dataValueTags.GetTags(propertyValue.Value, configuration, languageId))
|
||||
{
|
||||
yield return tag;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Cms.Core.Cache;
|
||||
using Umbraco.Cms.Core.IO;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Blocks;
|
||||
@@ -51,7 +52,7 @@ public abstract class BlockGridPropertyEditorBase : DataEditor
|
||||
DataEditorAttribute attribute,
|
||||
PropertyEditorCollection propertyEditors,
|
||||
DataValueReferenceFactoryCollection dataValueReferenceFactories,
|
||||
IDataTypeService dataTypeService,
|
||||
IDataTypeConfigurationCache dataTypeConfigurationCache,
|
||||
ILocalizedTextService textService,
|
||||
ILogger<BlockGridEditorPropertyValueEditor> logger,
|
||||
IShortStringHelper shortStringHelper,
|
||||
@@ -59,7 +60,7 @@ public abstract class BlockGridPropertyEditorBase : DataEditor
|
||||
IIOHelper ioHelper,
|
||||
IContentTypeService contentTypeService,
|
||||
IPropertyValidationService propertyValidationService)
|
||||
: base(attribute, propertyEditors, dataValueReferenceFactories, dataTypeService, textService, logger, shortStringHelper, jsonSerializer, ioHelper)
|
||||
: base(attribute, propertyEditors, dataValueReferenceFactories, dataTypeConfigurationCache, textService, logger, shortStringHelper, jsonSerializer, ioHelper)
|
||||
{
|
||||
BlockEditorValues = new BlockEditorValues<BlockGridValue, BlockGridLayoutItem>(new BlockGridEditorDataConverter(jsonSerializer), contentTypeService, logger);
|
||||
Validators.Add(new BlockEditorValidator<BlockGridValue, BlockGridLayoutItem>(propertyValidationService, BlockEditorValues, contentTypeService));
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Cms.Core.Cache;
|
||||
using Umbraco.Cms.Core.IO;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Blocks;
|
||||
@@ -58,7 +59,7 @@ public abstract class BlockListPropertyEditorBase : DataEditor
|
||||
BlockEditorDataConverter<BlockListValue, BlockListLayoutItem> blockEditorDataConverter,
|
||||
PropertyEditorCollection propertyEditors,
|
||||
DataValueReferenceFactoryCollection dataValueReferenceFactories,
|
||||
IDataTypeService dataTypeService,
|
||||
IDataTypeConfigurationCache dataTypeConfigurationCache,
|
||||
IContentTypeService contentTypeService,
|
||||
ILocalizedTextService textService,
|
||||
ILogger<BlockListEditorPropertyValueEditor> logger,
|
||||
@@ -66,7 +67,7 @@ public abstract class BlockListPropertyEditorBase : DataEditor
|
||||
IJsonSerializer jsonSerializer,
|
||||
IIOHelper ioHelper,
|
||||
IPropertyValidationService propertyValidationService) :
|
||||
base(attribute, propertyEditors, dataValueReferenceFactories,dataTypeService, textService, logger, shortStringHelper, jsonSerializer, ioHelper)
|
||||
base(attribute, propertyEditors, dataValueReferenceFactories, dataTypeConfigurationCache, textService, logger, shortStringHelper, jsonSerializer, ioHelper)
|
||||
{
|
||||
BlockEditorValues = new BlockEditorValues<BlockListValue, BlockListLayoutItem>(blockEditorDataConverter, contentTypeService, logger);
|
||||
Validators.Add(new BlockEditorValidator<BlockListValue, BlockListLayoutItem>(propertyValidationService, BlockEditorValues, contentTypeService));
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Cms.Core.Cache;
|
||||
using Umbraco.Cms.Core.IO;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Blocks;
|
||||
@@ -13,7 +14,7 @@ internal abstract class BlockValuePropertyValueEditorBase<TValue, TLayout> : Dat
|
||||
where TValue : BlockValue<TLayout>, new()
|
||||
where TLayout : class, IBlockLayoutItem, new()
|
||||
{
|
||||
private readonly IDataTypeService _dataTypeService;
|
||||
private readonly IDataTypeConfigurationCache _dataTypeConfigurationCache;
|
||||
private readonly PropertyEditorCollection _propertyEditors;
|
||||
private readonly ILogger _logger;
|
||||
private readonly DataValueReferenceFactoryCollection _dataValueReferenceFactoryCollection;
|
||||
@@ -21,7 +22,7 @@ internal abstract class BlockValuePropertyValueEditorBase<TValue, TLayout> : Dat
|
||||
protected BlockValuePropertyValueEditorBase(
|
||||
DataEditorAttribute attribute,
|
||||
PropertyEditorCollection propertyEditors,
|
||||
IDataTypeService dataTypeService,
|
||||
IDataTypeConfigurationCache dataTypeConfigurationCache,
|
||||
ILocalizedTextService textService,
|
||||
ILogger logger,
|
||||
IShortStringHelper shortStringHelper,
|
||||
@@ -31,7 +32,7 @@ internal abstract class BlockValuePropertyValueEditorBase<TValue, TLayout> : Dat
|
||||
: base(textService, shortStringHelper, jsonSerializer, ioHelper, attribute)
|
||||
{
|
||||
_propertyEditors = propertyEditors;
|
||||
_dataTypeService = dataTypeService;
|
||||
_dataTypeConfigurationCache = dataTypeConfigurationCache;
|
||||
_logger = logger;
|
||||
_dataValueReferenceFactoryCollection = dataValueReferenceFactoryCollection;
|
||||
}
|
||||
@@ -78,6 +79,7 @@ internal abstract class BlockValuePropertyValueEditorBase<TValue, TLayout> : Dat
|
||||
protected IEnumerable<ITag> GetBlockValueTags(TValue blockValue, int? languageId)
|
||||
{
|
||||
var result = new List<ITag>();
|
||||
|
||||
// loop through all content and settings data
|
||||
foreach (BlockItemData row in blockValue.ContentData.Concat(blockValue.SettingsData))
|
||||
{
|
||||
@@ -91,7 +93,7 @@ internal abstract class BlockValuePropertyValueEditorBase<TValue, TLayout> : Dat
|
||||
continue;
|
||||
}
|
||||
|
||||
object? configuration = _dataTypeService.GetDataType(prop.Value.PropertyType.DataTypeKey)?.ConfigurationObject;
|
||||
object? configuration = _dataTypeConfigurationCache.GetConfiguration(prop.Value.PropertyType.DataTypeKey);
|
||||
|
||||
result.AddRange(tagsProvider.GetTags(prop.Value.Value, configuration, languageId));
|
||||
}
|
||||
@@ -114,7 +116,7 @@ internal abstract class BlockValuePropertyValueEditorBase<TValue, TLayout> : Dat
|
||||
|
||||
private void MapBlockItemDataToEditor(IProperty property, List<BlockItemData> items)
|
||||
{
|
||||
var valEditors = new Dictionary<int, IDataValueEditor>();
|
||||
var valEditors = new Dictionary<Guid, IDataValueEditor>();
|
||||
|
||||
foreach (BlockItemData row in items)
|
||||
{
|
||||
@@ -136,25 +138,13 @@ internal abstract class BlockValuePropertyValueEditorBase<TValue, TLayout> : Dat
|
||||
continue;
|
||||
}
|
||||
|
||||
IDataType? dataType = _dataTypeService.GetDataType(prop.Value.PropertyType.DataTypeId);
|
||||
if (dataType == null)
|
||||
Guid dataTypeKey = prop.Value.PropertyType.DataTypeKey;
|
||||
if (!valEditors.TryGetValue(dataTypeKey, out IDataValueEditor? valEditor))
|
||||
{
|
||||
// deal with weird situations by ignoring them (no comment)
|
||||
row.PropertyValues.Remove(prop.Key);
|
||||
_logger.LogWarning(
|
||||
"ToEditor removed property value {PropertyKey} in row {RowId} for property type {PropertyTypeAlias}",
|
||||
prop.Key,
|
||||
row.Key,
|
||||
property.PropertyType.Alias);
|
||||
continue;
|
||||
}
|
||||
var configuration = _dataTypeConfigurationCache.GetConfiguration(dataTypeKey);
|
||||
valEditor = propEditor.GetValueEditor(configuration);
|
||||
|
||||
if (!valEditors.TryGetValue(dataType.Id, out IDataValueEditor? valEditor))
|
||||
{
|
||||
var tempConfig = dataType.ConfigurationObject;
|
||||
valEditor = propEditor.GetValueEditor(tempConfig);
|
||||
|
||||
valEditors.Add(dataType.Id, valEditor);
|
||||
valEditors.Add(dataTypeKey, valEditor);
|
||||
}
|
||||
|
||||
var convValue = valEditor.ToEditor(tempProp);
|
||||
@@ -172,7 +162,7 @@ internal abstract class BlockValuePropertyValueEditorBase<TValue, TLayout> : Dat
|
||||
foreach (KeyValuePair<string, BlockItemData.BlockPropertyValue> prop in row.PropertyValues)
|
||||
{
|
||||
// Fetch the property types prevalue
|
||||
var propConfiguration = _dataTypeService.GetDataType(prop.Value.PropertyType.DataTypeId)?.ConfigurationObject;
|
||||
var configuration = _dataTypeConfigurationCache.GetConfiguration(prop.Value.PropertyType.DataTypeKey);
|
||||
|
||||
// Lookup the property editor
|
||||
IDataEditor? propEditor = _propertyEditors[prop.Value.PropertyType.PropertyEditorAlias];
|
||||
@@ -182,7 +172,7 @@ internal abstract class BlockValuePropertyValueEditorBase<TValue, TLayout> : Dat
|
||||
}
|
||||
|
||||
// Create a fake content property data object
|
||||
var contentPropData = new ContentPropertyData(prop.Value.Value, propConfiguration);
|
||||
var contentPropData = new ContentPropertyData(prop.Value.Value, configuration);
|
||||
|
||||
// Get the property editor to do it's conversion
|
||||
var newValue = propEditor.GetValueEditor().FromEditor(contentPropData, prop.Value.Value);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core.Cache;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.IO;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
@@ -24,7 +25,7 @@ namespace Umbraco.Cms.Core.PropertyEditors;
|
||||
/// </summary>
|
||||
internal class ImageCropperPropertyValueEditor : DataValueEditor // TODO: core vs web?
|
||||
{
|
||||
private readonly IDataTypeService _dataTypeService;
|
||||
private readonly IDataTypeConfigurationCache _dataTypeConfigurationCache;
|
||||
private readonly IFileStreamSecurityValidator _fileStreamSecurityValidator;
|
||||
private readonly ILogger<ImageCropperPropertyValueEditor> _logger;
|
||||
private readonly MediaFileManager _mediaFileManager;
|
||||
@@ -42,20 +43,20 @@ internal class ImageCropperPropertyValueEditor : DataValueEditor // TODO: core v
|
||||
IOptionsMonitor<ContentSettings> contentSettings,
|
||||
IJsonSerializer jsonSerializer,
|
||||
IIOHelper ioHelper,
|
||||
IDataTypeService dataTypeService,
|
||||
ITemporaryFileService temporaryFileService,
|
||||
IScopeProvider scopeProvider,
|
||||
IFileStreamSecurityValidator fileStreamSecurityValidator)
|
||||
IFileStreamSecurityValidator fileStreamSecurityValidator,
|
||||
IDataTypeConfigurationCache dataTypeConfigurationCache)
|
||||
: base(localizedTextService, shortStringHelper, jsonSerializer, ioHelper, attribute)
|
||||
{
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_mediaFileManager = mediaFileSystem ?? throw new ArgumentNullException(nameof(mediaFileSystem));
|
||||
_jsonSerializer = jsonSerializer;
|
||||
_contentSettings = contentSettings.CurrentValue;
|
||||
_dataTypeService = dataTypeService;
|
||||
_temporaryFileService = temporaryFileService;
|
||||
_scopeProvider = scopeProvider;
|
||||
_fileStreamSecurityValidator = fileStreamSecurityValidator;
|
||||
_dataTypeConfigurationCache = dataTypeConfigurationCache;
|
||||
contentSettings.OnChange(x => _contentSettings = x);
|
||||
|
||||
Validators.Add(new TemporaryFileUploadValidator(() => _contentSettings, TryParseTemporaryFileKey, TryGetTemporaryFile));
|
||||
@@ -83,10 +84,10 @@ internal class ImageCropperPropertyValueEditor : DataValueEditor // TODO: core v
|
||||
value = new ImageCropperValue { Src = val.ToString() };
|
||||
}
|
||||
|
||||
IDataType? dataType = _dataTypeService.GetDataType(property.PropertyType.DataTypeId);
|
||||
if (dataType?.ConfigurationObject != null)
|
||||
var configuration = _dataTypeConfigurationCache.GetConfigurationAs<ImageCropperConfiguration>(property.PropertyType.DataTypeKey);
|
||||
if (configuration is not null)
|
||||
{
|
||||
value?.ApplyConfiguration(dataType.ConfigurationAs<ImageCropperConfiguration>());
|
||||
value?.ApplyConfiguration(configuration);
|
||||
}
|
||||
|
||||
return value;
|
||||
@@ -213,8 +214,7 @@ internal class ImageCropperPropertyValueEditor : DataValueEditor // TODO: core v
|
||||
}
|
||||
|
||||
// more magic here ;-(
|
||||
ImageCropperConfiguration? configuration = _dataTypeService.GetDataType(propertyType.DataTypeId)
|
||||
?.ConfigurationAs<ImageCropperConfiguration>();
|
||||
ImageCropperConfiguration? configuration = _dataTypeConfigurationCache.GetConfigurationAs<ImageCropperConfiguration>(propertyType.DataTypeKey);
|
||||
ImageCropperConfiguration.Crop[] crops = configuration?.Crops ?? Array.Empty<ImageCropperConfiguration.Crop>();
|
||||
|
||||
return _jsonSerializer.Serialize(new { src = val, crops });
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Umbraco.Cms.Core.Cache;
|
||||
using Umbraco.Cms.Core.IO;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Editors;
|
||||
@@ -48,7 +49,7 @@ public class MediaPicker3PropertyEditor : DataEditor
|
||||
|
||||
internal class MediaPicker3PropertyValueEditor : DataValueEditor, IDataValueReference
|
||||
{
|
||||
private readonly IDataTypeService _dataTypeService;
|
||||
private readonly IDataTypeConfigurationCache _dataTypeReadCache;
|
||||
private readonly IJsonSerializer _jsonSerializer;
|
||||
private readonly IMediaImportService _mediaImportService;
|
||||
private readonly IMediaService _mediaService;
|
||||
@@ -61,21 +62,21 @@ public class MediaPicker3PropertyEditor : DataEditor
|
||||
IJsonSerializer jsonSerializer,
|
||||
IIOHelper ioHelper,
|
||||
DataEditorAttribute attribute,
|
||||
IDataTypeService dataTypeService,
|
||||
IMediaImportService mediaImportService,
|
||||
IMediaService mediaService,
|
||||
ITemporaryFileService temporaryFileService,
|
||||
IScopeProvider scopeProvider,
|
||||
IBackOfficeSecurityAccessor backOfficeSecurityAccessor)
|
||||
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
|
||||
IDataTypeConfigurationCache dataTypeReadCache)
|
||||
: base(shortStringHelper, jsonSerializer, ioHelper, attribute)
|
||||
{
|
||||
_jsonSerializer = jsonSerializer;
|
||||
_dataTypeService = dataTypeService;
|
||||
_mediaImportService = mediaImportService;
|
||||
_mediaService = mediaService;
|
||||
_temporaryFileService = temporaryFileService;
|
||||
_scopeProvider = scopeProvider;
|
||||
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
|
||||
_dataTypeReadCache = dataTypeReadCache;
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
@@ -97,11 +98,9 @@ public class MediaPicker3PropertyEditor : DataEditor
|
||||
var dtos = Deserialize(_jsonSerializer, value).ToList();
|
||||
dtos = UpdateMediaTypeAliases(dtos);
|
||||
|
||||
IDataType? dataType = _dataTypeService.GetDataType(property.PropertyType.DataTypeId);
|
||||
if (dataType?.ConfigurationObject != null)
|
||||
var configuration = _dataTypeReadCache.GetConfigurationAs<MediaPicker3Configuration>(property.PropertyType.DataTypeKey);
|
||||
if (configuration is not null)
|
||||
{
|
||||
MediaPicker3Configuration? configuration = dataType.ConfigurationAs<MediaPicker3Configuration>();
|
||||
|
||||
foreach (MediaWithCropsDto dto in dtos)
|
||||
{
|
||||
dto.ApplyConfiguration(configuration);
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Cms.Core.Cache;
|
||||
using Umbraco.Cms.Core.DependencyInjection;
|
||||
using Umbraco.Cms.Core.IO;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Blocks;
|
||||
@@ -73,7 +75,7 @@ public class RichTextPropertyEditor : DataEditor
|
||||
public RichTextPropertyValueEditor(
|
||||
DataEditorAttribute attribute,
|
||||
PropertyEditorCollection propertyEditors,
|
||||
IDataTypeService dataTypeService,
|
||||
IDataTypeConfigurationCache dataTypeReadCache,
|
||||
ILogger<RichTextPropertyValueEditor> logger,
|
||||
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
|
||||
ILocalizedTextService localizedTextService,
|
||||
@@ -87,7 +89,7 @@ public class RichTextPropertyEditor : DataEditor
|
||||
IContentTypeService contentTypeService,
|
||||
IPropertyValidationService propertyValidationService,
|
||||
DataValueReferenceFactoryCollection dataValueReferenceFactoryCollection)
|
||||
: base(attribute, propertyEditors, dataTypeService, localizedTextService, logger, shortStringHelper, jsonSerializer, ioHelper, dataValueReferenceFactoryCollection)
|
||||
: base(attribute, propertyEditors, dataTypeReadCache, localizedTextService, logger, shortStringHelper, jsonSerializer, ioHelper, dataValueReferenceFactoryCollection)
|
||||
{
|
||||
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
|
||||
_imageSourceParser = imageSourceParser;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core.Cache;
|
||||
using Umbraco.Cms.Core.IO;
|
||||
using Umbraco.Cms.Core.Models.Blocks;
|
||||
using Umbraco.Cms.Core.PropertyEditors;
|
||||
@@ -41,7 +42,7 @@ public class DataValueEditorReuseTests
|
||||
new BlockListEditorDataConverter(Mock.Of<IJsonSerializer>()),
|
||||
_propertyEditorCollection,
|
||||
_dataValueReferenceFactories,
|
||||
Mock.Of<IDataTypeService>(),
|
||||
Mock.Of<IDataTypeConfigurationCache>(),
|
||||
Mock.Of<IContentTypeService>(),
|
||||
Mock.Of<ILocalizedTextService>(),
|
||||
Mock.Of<ILogger<BlockListPropertyEditorBase.BlockListEditorPropertyValueEditor>>(),
|
||||
|
||||
Reference in New Issue
Block a user