From f5546ca87020977290f548bfbaa0988faf092cce Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 29 Jan 2018 19:23:25 +0100 Subject: [PATCH] DataType refactoring - troubleshooting and fixing tests --- src/Umbraco.Core/Models/DataType.cs | 36 +++--- src/Umbraco.Core/Models/DataTypeExtensions.cs | 3 + .../Persistence/Dtos/DataTypeDto.cs | 4 +- .../Persistence/Factories/DataTypeFactory.cs | 7 +- .../Implement/DataTypeRepository.cs | 2 + .../PropertyEditors/ConfigurationEditor.cs | 11 +- .../ConfigurationEditorOfTConfiguration.cs | 2 +- .../PropertyEditors/PropertyEditor.cs | 40 ++++++- .../ValueConverters/ImageCropperValue.cs | 76 ++++++++----- .../ImageCropperValueTypeConverter.cs} | 17 ++- .../PropertyEditors/ValueTypes.cs | 2 +- src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../Persistence/Mappers/DataTypeMapperTest.cs | 4 +- .../Mappers/PropertyTypeMapperTest.cs | 8 +- .../ContentTypeRepositorySqlClausesTest.cs | 4 +- .../Querying/ContentTypeSqlMappingTests.cs | 2 - ...aTypeDefinitionRepositorySqlClausesTest.cs | 4 +- .../DataTypeDefinitionRepositoryTest.cs | 104 +++++------------- .../PropertyEditors/ImageCropperTest.cs | 38 +++---- .../MultiValuePropertyEditorTests.cs | 17 ++- .../PropertyEditorValueEditorTests.cs | 3 +- .../Published/NestedContentTests.cs | 2 +- .../Services/CachedDataTypeServiceTests.cs | 3 +- .../Services/DataTypeServiceTests.cs | 2 +- .../Entities/MockedContentTypes.cs | 2 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 1 + src/Umbraco.Web/Editors/DataTypeController.cs | 17 ++- .../ImageCropperTemplateExtensions.cs | 10 +- .../Models/Mapping/ContentMapperProfile.cs | 7 +- .../Mapping/ContentTypeMapperProfile.cs | 9 +- .../Mapping/ContentTypeProfileExtensions.cs | 3 +- ...taTypeConfigurationFieldDisplayResolver.cs | 10 +- .../Models/Mapping/DataTypeMapperProfile.cs | 11 +- .../Models/Mapping/MediaMapperProfile.cs | 7 +- .../ImageCropperPropertyValueEditor.cs | 21 ++-- .../PublishValueValueEditor.cs | 7 +- .../PublishValuesMultipleValueEditor.cs | 12 +- src/Umbraco.Web/Umbraco.Web.csproj | 1 - 38 files changed, 265 insertions(+), 245 deletions(-) rename src/{Umbraco.Web/PropertyEditors/ValueConverters/ImageCropDataSetTypeConverter.cs => Umbraco.Core/PropertyEditors/ValueConverters/ImageCropperValueTypeConverter.cs} (61%) diff --git a/src/Umbraco.Core/Models/DataType.cs b/src/Umbraco.Core/Models/DataType.cs index 28dc7ba12f..21949ba980 100644 --- a/src/Umbraco.Core/Models/DataType.cs +++ b/src/Umbraco.Core/Models/DataType.cs @@ -69,36 +69,44 @@ namespace Umbraco.Core.Models /// [DataMember] - public object Configuration // fixme is this OK if null? should! + public object Configuration { get { + // if we know we have a configuration (which may be null), return it + // if we don't have an editor, then we have no configuration, return null + // else, use the editor to get the configuration object + if (_hasConfiguration) return _configuration; + if (_editor == null) return null; _configuration = _editor.ConfigurationEditor.ParseConfiguration(_configurationJson); _hasConfiguration = true; _configurationJson = null; + _editor = null; return _configuration; } set { - if (value == null) throw new ArgumentNullException(); // or is this ok? - - // fixme - do it HERE - // fixme - BUT then we have a problem, what if it's changed? - // can't we treat configurations as plain immutable objects?! - // also it means that we just cannot work with dictionaries? - if (value is IConfigureValueType valueTypeConfiguration) - DatabaseType = ValueTypes.ToStorageType(valueTypeConfiguration.ValueType); - if (value is IDictionary dictionaryConfiguration - && dictionaryConfiguration.TryGetValue("", out var valueTypeObject) - && valueTypeObject is string valueTypeString) - DatabaseType = ValueTypes.ToStorageType(valueTypeString); + if (value != null) + { + // fixme - do it HERE + // fixme - BUT then we have a problem, what if it's changed? + // can't we treat configurations as plain immutable objects?! + // also it means that we just cannot work with dictionaries? + if (value is IConfigureValueType valueTypeConfiguration) + DatabaseType = ValueTypes.ToStorageType(valueTypeConfiguration.ValueType); + if (value is IDictionary dictionaryConfiguration + && dictionaryConfiguration.TryGetValue("", out var valueTypeObject) + && valueTypeObject is string valueTypeString) + DatabaseType = ValueTypes.ToStorageType(valueTypeString); + } // fixme detect changes? if it's the same object? need a special comparer! SetPropertyValueAndDetectChanges(value, ref _configuration, Selectors.Configuration); _hasConfiguration = true; _configurationJson = null; + _editor = null; } } @@ -106,10 +114,10 @@ namespace Umbraco.Core.Models public void SetConfiguration(string configurationJson, PropertyEditor editor) { // fixme this is lazy, BUT then WHEN are we figuring out the valueType? + _editor = editor ?? throw new ArgumentNullException(nameof(editor)); _hasConfiguration = false; _configuration = null; _configurationJson = configurationJson; - _editor = editor; OnPropertyChanged(Selectors.Configuration); } } diff --git a/src/Umbraco.Core/Models/DataTypeExtensions.cs b/src/Umbraco.Core/Models/DataTypeExtensions.cs index 2beff9789a..df8a3caea8 100644 --- a/src/Umbraco.Core/Models/DataTypeExtensions.cs +++ b/src/Umbraco.Core/Models/DataTypeExtensions.cs @@ -20,6 +20,9 @@ namespace Umbraco.Core.Models public static T ConfigurationAs(this IDataType dataType) where T : class { + if (dataType == null) + throw new ArgumentNullException(nameof(dataType)); + var configuration = dataType.Configuration; switch (configuration) diff --git a/src/Umbraco.Core/Persistence/Dtos/DataTypeDto.cs b/src/Umbraco.Core/Persistence/Dtos/DataTypeDto.cs index ceeaea38b7..cc51ab19ee 100644 --- a/src/Umbraco.Core/Persistence/Dtos/DataTypeDto.cs +++ b/src/Umbraco.Core/Persistence/Dtos/DataTypeDto.cs @@ -18,11 +18,11 @@ namespace Umbraco.Core.Persistence.Dtos [Column("dbType")] [Length(50)] - public string DbType { get; set; }//NOTE Is set to [varchar] (50) in Sql Server script + public string DbType { get; set; } [Column("config")] [SpecialDbType(SpecialDbTypes.NTEXT)] - [Constraint(Default = "")] + [NullSetting(NullSetting = NullSettings.Null)] public string Configuration { get; set; } [ResultColumn] diff --git a/src/Umbraco.Core/Persistence/Factories/DataTypeFactory.cs b/src/Umbraco.Core/Persistence/Factories/DataTypeFactory.cs index 11c179212f..db05c186d8 100644 --- a/src/Umbraco.Core/Persistence/Factories/DataTypeFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/DataTypeFactory.cs @@ -1,5 +1,4 @@ using System; -using System.Globalization; using Newtonsoft.Json; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Dtos; @@ -11,6 +10,9 @@ namespace Umbraco.Core.Persistence.Factories { public static IDataType BuildEntity(DataTypeDto dto, PropertyEditor editor) { + if (editor == null) + throw new ArgumentNullException(nameof(editor), $"Editor with alias \"{dto.EditorAlias}\" is required."); + var dataType = new DataType(dto.EditorAlias); try @@ -30,7 +32,6 @@ namespace Umbraco.Core.Persistence.Factories dataType.Trashed = dto.NodeDto.Trashed; dataType.CreatorId = dto.NodeDto.UserId ?? 0; - dataType.EditorAlias = editor.Alias; dataType.SetConfiguration(dto.Configuration, editor); // reset dirty initial properties (U4-1946) @@ -50,7 +51,7 @@ namespace Umbraco.Core.Persistence.Factories EditorAlias = entity.EditorAlias, NodeId = entity.Id, DbType = entity.DatabaseType.ToString(), - Configuration = JsonConvert.SerializeObject(entity.Configuration), + Configuration = entity.Configuration == null ? null : JsonConvert.SerializeObject(entity.Configuration), NodeDto = BuildNodeDto(entity) }; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DataTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DataTypeRepository.cs index e6488cc566..9ff9dd4e69 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DataTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DataTypeRepository.cs @@ -53,6 +53,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement dataTypeSql.Where(x => x.NodeObjectType == NodeObjectTypeId); } + // fixme what shall we do when there is no editor for the editor alias? + // we should pass _editors to the factory - and then what? var dtos = Database.Fetch(dataTypeSql); return dtos.Select(x => DataTypeFactory.BuildEntity(x, _editors.Value[x.EditorAlias])).ToArray(); } diff --git a/src/Umbraco.Core/PropertyEditors/ConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/ConfigurationEditor.cs index 339cbdaf06..165780f606 100644 --- a/src/Umbraco.Core/PropertyEditors/ConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/ConfigurationEditor.cs @@ -46,13 +46,18 @@ namespace Umbraco.Core.PropertyEditors /// /// Used to create the actual configuration dictionary from the database value. public virtual object ParseConfiguration(string configurationJson) - => JsonConvert.DeserializeObject>(configurationJson); + => string.IsNullOrWhiteSpace(configurationJson) + ? null + : JsonConvert.DeserializeObject>(configurationJson); + /// + /// Gets the configuration as a typed object. + /// public static TConfiguration ConfigurationAs(object obj) { - // fixme what about nulls? + if (obj == null) return default; if (obj is TConfiguration configuration) return configuration; - throw new InvalidCastException(); // fixme message + throw new InvalidCastException($"Cannot cast configuration of type {obj.GetType().Name} to {typeof(TConfiguration).Name}."); } // notes diff --git a/src/Umbraco.Core/PropertyEditors/ConfigurationEditorOfTConfiguration.cs b/src/Umbraco.Core/PropertyEditors/ConfigurationEditorOfTConfiguration.cs index 6a5bfd4040..bc0f371c35 100644 --- a/src/Umbraco.Core/PropertyEditors/ConfigurationEditorOfTConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/ConfigurationEditorOfTConfiguration.cs @@ -96,6 +96,7 @@ namespace Umbraco.Core.PropertyEditors { try { + if (string.IsNullOrWhiteSpace(configuration)) return default; return JsonConvert.DeserializeObject(configuration); } catch (Exception e) @@ -133,7 +134,6 @@ namespace Umbraco.Core.PropertyEditors /// The configuration. public virtual Dictionary ToEditor(TConfiguration configuration) { - // fixme - how shall we merge? does defaultConfiguration makes any sense here? var dictionary = ObjectExtensions.ToObjectDictionary(configuration); if (configuration is ConfigurationWithAdditionalData withAdditionalData) diff --git a/src/Umbraco.Core/PropertyEditors/PropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/PropertyEditor.cs index 5a7b323cce..b20c9f994c 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyEditor.cs @@ -90,7 +90,24 @@ namespace Umbraco.Core.PropertyEditors [JsonIgnore] public bool IsDeprecated { get; internal set; } // fixme - kill it all in v8 - [JsonProperty("editor", Required = Required.Always)] + /// + /// Gets or sets the value editor. + /// + /// + /// If an instance of a value editor is assigned to the property, + /// then this instance is returned when getting the property value. Otherwise, a + /// new instance is created by CreateValueEditor. + /// The instance created by CreateValueEditor is not cached, i.e. + /// a new instance is created each time the property value is retrieved. The + /// property editor is a singleton, and the value editor cannot be a singleton + /// since it depends on the datatype configuration. + /// Technically, it could be cached by datatype but let's keep things + /// simple enough for now. + /// The property is marked as a Json property with ObjectCreationHandling + /// set to Replace in order to prevent the Json deserializer to retrieve the + /// value of the property before setting it. + /// + [JsonProperty("editor", Required = Required.Always, ObjectCreationHandling = ObjectCreationHandling.Replace)] public ValueEditor ValueEditor { // create a new value editor each time - the property editor can be a @@ -103,12 +120,25 @@ namespace Umbraco.Core.PropertyEditors [JsonIgnore] IValueEditor IParameterEditor.ValueEditor => ValueEditor; // fixme - because we must, but - bah - [JsonProperty("prevalues")] // change, breaks manifests + /// + /// Gets or sets the configuration editor. + /// + /// + /// If an instance of a configuration editor is assigned to the property, + /// then this instance is returned when getting the property value. Otherwise, a + /// new instance is created by CreateConfigurationEditor. + /// The instance created by CreateConfigurationEditor is not cached, i.e. + /// a new instance is created each time the property value is retrieved. The + /// property editor is a singleton, and although the configuration editor could + /// technically be a singleton too, we'd rather not keep configuration editor + /// cached. + /// The property is marked as a Json property with ObjectCreationHandling + /// set to Replace in order to prevent the Json deserializer to retrieve the + /// value of the property before setting it. + /// + [JsonProperty("prevalues", ObjectCreationHandling = ObjectCreationHandling.Replace)] // changing the name would break manifests public ConfigurationEditor ConfigurationEditor { - // create a new configuration editor each time - the property editor can be a - // singleton, and technically the configuration editor could be a singleton - // too, but we'd rather not keep all configuration editor around in memory get => CreateConfigurationEditor(); set => _configurationEditorAssigned = value; } diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/ImageCropperValue.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/ImageCropperValue.cs index 8efd98191d..dd33bb0dd0 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/ImageCropperValue.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/ImageCropperValue.cs @@ -1,16 +1,22 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Globalization; using System.Linq; using System.Runtime.Serialization; using System.Text; using System.Web; +using Newtonsoft.Json; +using Umbraco.Core.Serialization; namespace Umbraco.Core.PropertyEditors.ValueConverters // fixme MOVE TO MODELS OR SOMETHING { /// /// Represents a value of the image cropper value editor. /// + [JsonConverter(typeof(NoTypeConverterJsonConverter))] + [TypeConverter(typeof(ImageCropperValueTypeConverter))] + [DataContract(Name="imageCropDataSet")] public class ImageCropperValue : IHtmlString, IEquatable { /// @@ -31,6 +37,12 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters // fixme MOVE TO MODELS O [DataMember(Name = "crops")] public IEnumerable Crops { get; set; } + /// + public override string ToString() + { + return Crops.Any() ? JsonConvert.SerializeObject(this) : Src; + } + /// public string ToHtmlString() => Src; @@ -39,20 +51,20 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters // fixme MOVE TO MODELS O /// public ImageCropperCrop GetCrop(string alias) { - if (Crops == null || !Crops.Any()) + if (Crops == null) return null; return string.IsNullOrWhiteSpace(alias) - ? Crops.First() + ? Crops.FirstOrDefault() : Crops.FirstOrDefault(x => x.Alias.InvariantEquals(alias)); } // fixme was defined in web project, extension methods? why internal? - internal void AppendCropBaseUrl(StringBuilder url, ImageCropperCrop crop, bool preferFocalPoint) + internal void AppendCropBaseUrl(StringBuilder url, ImageCropperCrop crop, bool defaultCrop, bool preferFocalPoint) { if (preferFocalPoint && HasFocalPoint() || crop != null && crop.Coordinates == null && HasFocalPoint() - || crop == null && HasFocalPoint()) + || defaultCrop && HasFocalPoint()) { url.Append("?center="); url.Append(FocalPoint.Top.ToString(CultureInfo.InvariantCulture)); @@ -89,7 +101,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters // fixme MOVE TO MODELS O var url = new StringBuilder(); - AppendCropBaseUrl(url, crop, useFocalPoint); + AppendCropBaseUrl(url, crop, string.IsNullOrWhiteSpace(alias), useFocalPoint); if (crop != null && useCropDimensions) { @@ -110,7 +122,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters // fixme MOVE TO MODELS O { var url = new StringBuilder(); - AppendCropBaseUrl(url, null, useFocalPoint); + AppendCropBaseUrl(url, null, true, useFocalPoint); url.Append("&width=").Append(width); url.Append("&height=").Append(height); @@ -149,6 +161,8 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters // fixme MOVE TO MODELS O // merge the crop values - the alias + width + height comes from // configuration, but each crop can store its own coordinates + if (configuration == null) return; + var configuredCrops = configuration.Crops; var crops = Crops.ToList(); @@ -183,16 +197,18 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters // fixme MOVE TO MODELS O /// public bool Equals(ImageCropperValue other) - => other != null && (ReferenceEquals(this, other) || Equals(this, other)); + => ReferenceEquals(this, other) || Equals(this, other); /// public override bool Equals(object obj) - => obj != null && (ReferenceEquals(this, obj) || obj is ImageCropperValue other && Equals(this, other)); + => ReferenceEquals(this, obj) || obj is ImageCropperValue other && Equals(this, other); private static bool Equals(ImageCropperValue left, ImageCropperValue right) - => string.Equals(left.Src, right.Src) - && Equals(left.FocalPoint, right.FocalPoint) - && left.ComparableCrops.SequenceEqual(right.ComparableCrops); + => ReferenceEquals(left, right) // deals with both being null, too + || !ReferenceEquals(left, null) && !ReferenceEquals(right, null) + && string.Equals(left.Src, right.Src) + && Equals(left.FocalPoint, right.FocalPoint) + && left.ComparableCrops.SequenceEqual(right.ComparableCrops); private IEnumerable ComparableCrops => Crops?.OrderBy(x => x.Alias) ?? Enumerable.Empty(); @@ -232,15 +248,17 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters // fixme MOVE TO MODELS O /// public bool Equals(ImageCropperFocalPoint other) - => other != null && (ReferenceEquals(this, other) || Equals(this, other)); + => ReferenceEquals(this, other) || Equals(this, other); /// public override bool Equals(object obj) - => obj != null && (ReferenceEquals(this, obj) || obj is ImageCropperFocalPoint other && Equals(this, other)); + => ReferenceEquals(this, obj) || obj is ImageCropperFocalPoint other && Equals(this, other); private static bool Equals(ImageCropperFocalPoint left, ImageCropperFocalPoint right) - => left.Left == right.Left - && left.Top == right.Top; + => ReferenceEquals(left, right) // deals with both being null, too + || !ReferenceEquals(left, null) && !ReferenceEquals(right, null) + && left.Left == right.Left + && left.Top == right.Top; public static bool operator ==(ImageCropperFocalPoint left, ImageCropperFocalPoint right) => Equals(left, right); @@ -281,17 +299,19 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters // fixme MOVE TO MODELS O /// public bool Equals(ImageCropperCrop other) - => other != null && (ReferenceEquals(this, other) || Equals(this, other)); + => ReferenceEquals(this, other) || Equals(this, other); /// public override bool Equals(object obj) - => obj != null && (ReferenceEquals(this, obj) || obj is ImageCropperCrop other && Equals(this, other)); + => ReferenceEquals(this, obj) || obj is ImageCropperCrop other && Equals(this, other); private static bool Equals(ImageCropperCrop left, ImageCropperCrop right) - => string.Equals(left.Alias, right.Alias) - && left.Width == right.Width - && left.Height == right.Height - && Equals(left.Coordinates, right.Coordinates); + => ReferenceEquals(left, right) // deals with both being null, too + || !ReferenceEquals(left, null) && !ReferenceEquals(right, null) + && string.Equals(left.Alias, right.Alias) + && left.Width == right.Width + && left.Height == right.Height + && Equals(left.Coordinates, right.Coordinates); public static bool operator ==(ImageCropperCrop left, ImageCropperCrop right) => Equals(left, right); @@ -336,17 +356,19 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters // fixme MOVE TO MODELS O /// public bool Equals(ImageCropperCropCoordinates other) - => other != null && (ReferenceEquals(this, other) || Equals(this, other)); + => ReferenceEquals(this, other) || Equals(this, other); /// public override bool Equals(object obj) - => obj != null && (ReferenceEquals(this, obj) || obj is ImageCropperCropCoordinates other && Equals(this, other)); + => ReferenceEquals(this, obj) || obj is ImageCropperCropCoordinates other && Equals(this, other); private static bool Equals(ImageCropperCropCoordinates left, ImageCropperCropCoordinates right) - => left.X1 == right.X1 - && left.X2 == right.X2 - && left.Y1 == right.Y1 - && left.Y2 == right.Y2; + => ReferenceEquals(left, right) // deals with both being null, too + || !ReferenceEquals(left, null) && !ReferenceEquals(right, null) + && left.X1 == right.X1 + && left.X2 == right.X2 + && left.Y1 == right.Y1 + && left.Y2 == right.Y2; public static bool operator ==(ImageCropperCropCoordinates left, ImageCropperCropCoordinates right) => Equals(left, right); diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/ImageCropDataSetTypeConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/ImageCropperValueTypeConverter.cs similarity index 61% rename from src/Umbraco.Web/PropertyEditors/ValueConverters/ImageCropDataSetTypeConverter.cs rename to src/Umbraco.Core/PropertyEditors/ValueConverters/ImageCropperValueTypeConverter.cs index 0060dd6cc0..7631d32efc 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/ImageCropDataSetTypeConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/ImageCropperValueTypeConverter.cs @@ -4,33 +4,30 @@ using System.Globalization; using System.Linq; using Newtonsoft.Json.Linq; using Umbraco.Core.Composing; -using Umbraco.Core.PropertyEditors.ValueConverters; -using Umbraco.Web.Models; -namespace Umbraco.Web.PropertyEditors.ValueConverters +namespace Umbraco.Core.PropertyEditors.ValueConverters { /// - /// Used to do some type conversions from ImageCropDataSet to string and JObject - /// fixme WHY? + /// Converts to string or JObject (why?). /// - public class ImageCropDataSetTypeConverter : TypeConverter + public class ImageCropperValueTypeConverter : TypeConverter { private static readonly Type[] ConvertableTypes = { typeof(JObject) }; public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { return ConvertableTypes.Any(x => TypeHelper.IsTypeAssignableFrom(x, destinationType)) - || base.CanConvertFrom(context, destinationType); + || CanConvertFrom(context, destinationType); } public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { - var cropDataSet = value as ImageCropperValue; - if (cropDataSet == null) + var cropperValue = value as ImageCropperValue; + if (cropperValue == null) return null; return TypeHelper.IsTypeAssignableFrom(destinationType) - ? JObject.FromObject(cropDataSet) + ? JObject.FromObject(cropperValue) : base.ConvertTo(context, culture, value, destinationType); } } diff --git a/src/Umbraco.Core/PropertyEditors/ValueTypes.cs b/src/Umbraco.Core/PropertyEditors/ValueTypes.cs index fea89943aa..8df9def440 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueTypes.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueTypes.cs @@ -100,7 +100,7 @@ namespace Umbraco.Core.PropertyEditors return ValueStorageType.Date; default: - throw new ArgumentOutOfRangeException(nameof(valueType), "Not a valid ValueTypes"); + throw new ArgumentOutOfRangeException(nameof(valueType), $"Value \"{valueType}\" is not a valid ValueTypes."); } } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 72a75c5503..40ca8c12fe 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -338,6 +338,7 @@ + diff --git a/src/Umbraco.Tests/Persistence/Mappers/DataTypeMapperTest.cs b/src/Umbraco.Tests/Persistence/Mappers/DataTypeMapperTest.cs index 43ec3545d8..848a60641f 100644 --- a/src/Umbraco.Tests/Persistence/Mappers/DataTypeMapperTest.cs +++ b/src/Umbraco.Tests/Persistence/Mappers/DataTypeMapperTest.cs @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Mappers string column = new DataTypeMapper().Map(new SqlCeSyntaxProvider(), "DatabaseType"); // Assert - Assert.That(column, Is.EqualTo("[cmsDataType].[dbType]")); + Assert.That(column, Is.EqualTo("[uDataType].[dbType]")); } [Test] @@ -48,7 +48,7 @@ namespace Umbraco.Tests.Persistence.Mappers string column = new DataTypeMapper().Map(new SqlCeSyntaxProvider(), "EditorAlias"); // Assert - Assert.That(column, Is.EqualTo("[cmsDataType].[propertyEditorAlias]")); + Assert.That(column, Is.EqualTo("[uDataType].[propertyEditorAlias]")); } } } diff --git a/src/Umbraco.Tests/Persistence/Mappers/PropertyTypeMapperTest.cs b/src/Umbraco.Tests/Persistence/Mappers/PropertyTypeMapperTest.cs index b3164f720f..9b1baafd51 100644 --- a/src/Umbraco.Tests/Persistence/Mappers/PropertyTypeMapperTest.cs +++ b/src/Umbraco.Tests/Persistence/Mappers/PropertyTypeMapperTest.cs @@ -31,7 +31,7 @@ namespace Umbraco.Tests.Persistence.Mappers public void Can_Map_DataTypeDefinitionId_Property() { // Act - string column = new PropertyTypeMapper().Map(new SqlCeSyntaxProvider(), "DataTypeDefinitionId"); + string column = new PropertyTypeMapper().Map(new SqlCeSyntaxProvider(), "DataTypeId"); // Assert Assert.That(column, Is.EqualTo("[cmsPropertyType].[dataTypeId]")); @@ -54,17 +54,17 @@ namespace Umbraco.Tests.Persistence.Mappers string column = new PropertyTypeMapper().Map(new SqlCeSyntaxProvider(), "PropertyEditorAlias"); // Assert - Assert.That(column, Is.EqualTo("[cmsDataType].[propertyEditorAlias]")); + Assert.That(column, Is.EqualTo("[uDataType].[propertyEditorAlias]")); } [Test] public void Can_Map_DataTypeDatabaseType_Property() { // Act - string column = new PropertyTypeMapper().Map(new SqlCeSyntaxProvider(), "DataTypeDatabaseType"); + string column = new PropertyTypeMapper().Map(new SqlCeSyntaxProvider(), "ValueStorageType"); // Assert - Assert.That(column, Is.EqualTo("[cmsDataType].[dbType]")); + Assert.That(column, Is.EqualTo("[uDataType].[dbType]")); } } } diff --git a/src/Umbraco.Tests/Persistence/Querying/ContentTypeRepositorySqlClausesTest.cs b/src/Umbraco.Tests/Persistence/Querying/ContentTypeRepositorySqlClausesTest.cs index 59f30c92ed..ba8155dc0a 100644 --- a/src/Umbraco.Tests/Persistence/Querying/ContentTypeRepositorySqlClausesTest.cs +++ b/src/Umbraco.Tests/Persistence/Querying/ContentTypeRepositorySqlClausesTest.cs @@ -94,7 +94,7 @@ namespace Umbraco.Tests.Persistence.Querying expected.SelectAll() .From("[cmsPropertyTypeGroup]") .RightJoin("[cmsPropertyType]").On("[cmsPropertyTypeGroup].[id] = [cmsPropertyType].[propertyTypeGroupId]") - .InnerJoin("[cmsDataType]").On("[cmsPropertyType].[dataTypeId] = [cmsDataType].[nodeId]"); + .InnerJoin("[uDataType]").On("[cmsPropertyType].[dataTypeId] = [uDataType].[nodeId]"); var sql = Sql(); sql.SelectAll() @@ -140,7 +140,7 @@ namespace Umbraco.Tests.Persistence.Querying expected.SelectAll() .From("[cmsPropertyTypeGroup]") .RightJoin("[cmsPropertyType]").On("[cmsPropertyTypeGroup].[id] = [cmsPropertyType].[propertyTypeGroupId]") - .InnerJoin("[cmsDataType]").On("[cmsPropertyType].[dataTypeId] = [cmsDataType].[nodeId]") + .InnerJoin("[uDataType]").On("[cmsPropertyType].[dataTypeId] = [uDataType].[nodeId]") .Where("([cmsPropertyType].[contentTypeId] = @0)", 1050); var sql = Sql(); diff --git a/src/Umbraco.Tests/Persistence/Querying/ContentTypeSqlMappingTests.cs b/src/Umbraco.Tests/Persistence/Querying/ContentTypeSqlMappingTests.cs index f6908e6e26..1a459e61b5 100644 --- a/src/Umbraco.Tests/Persistence/Querying/ContentTypeSqlMappingTests.cs +++ b/src/Umbraco.Tests/Persistence/Querying/ContentTypeSqlMappingTests.cs @@ -148,9 +148,7 @@ namespace Umbraco.Tests.Persistence.Querying scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 99999, Trashed = false, ParentId = -1, UserId = 0, Level = 0, Path = "-1,99999", SortOrder = 0, UniqueId = new Guid("129241F0-D24E-4FC3-92D1-BC2D48B7C431"), Text = "Test Content Type", NodeObjectType = Constants.ObjectTypes.DocumentType, CreateDate = DateTime.Now }); scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntax.GetQuotedTableName("umbracoNode")))); - scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntax.GetQuotedTableName(Constants.DatabaseSchema.Tables.DataType)))); scope.Database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 55555, EditorAlias = Constants.PropertyEditors.Aliases.Textbox, DbType = "Nvarchar" }); - scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF ", SqlSyntax.GetQuotedTableName(Constants.DatabaseSchema.Tables.DataType)))); scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", SqlSyntax.GetQuotedTableName("cmsContentType")))); scope.Database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 88888, NodeId = 99999, Alias = "TestContentType", Icon = "icon-folder", Thumbnail = "folder.png", IsContainer = false, AllowAtRoot = true }); diff --git a/src/Umbraco.Tests/Persistence/Querying/DataTypeDefinitionRepositorySqlClausesTest.cs b/src/Umbraco.Tests/Persistence/Querying/DataTypeDefinitionRepositorySqlClausesTest.cs index 6b468c403e..2b3611cb02 100644 --- a/src/Umbraco.Tests/Persistence/Querying/DataTypeDefinitionRepositorySqlClausesTest.cs +++ b/src/Umbraco.Tests/Persistence/Querying/DataTypeDefinitionRepositorySqlClausesTest.cs @@ -19,8 +19,8 @@ namespace Umbraco.Tests.Persistence.Querying var expected = new Sql(); expected.Select("*") - .From("[cmsDataType]") - .InnerJoin("[umbracoNode]").On("[cmsDataType].[nodeId] = [umbracoNode].[id]") + .From("[uDataType]") + .InnerJoin("[umbracoNode]").On("[uDataType].[nodeId] = [umbracoNode].[id]") .Where("([umbracoNode].[nodeObjectType] = @0)", new Guid("30a2a501-1978-4ddb-a57b-f7efed43ba3c")); var sql = Sql(); diff --git a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs index 7fcacd939c..20d066adb8 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs @@ -1,15 +1,12 @@ -using System; -using System.Linq; +using System.Linq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories; using Umbraco.Tests.TestHelpers; -using Umbraco.Core.Composing; using Umbraco.Tests.Testing; using LightInject; -using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Scoping; @@ -19,44 +16,6 @@ namespace Umbraco.Tests.Persistence.Repositories [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] public class DataTypeDefinitionRepositoryTest : TestWithDatabaseBase { - //protected override CacheHelper CreateCacheHelper() - //{ - // // hackish, but it works - // var testName = TestContext.CurrentContext.Test.Name; - // if (testName == "Can_Get_Pre_Value_As_String_With_Cache" - // || testName == "Can_Get_Pre_Value_Collection_With_Cache") - // { - // return new CacheHelper( - // new ObjectCacheRuntimeCacheProvider(), - // new StaticCacheProvider(), - // new StaticCacheProvider(), - // new IsolatedRuntimeCache(type => new ObjectCacheRuntimeCacheProvider())); // default would be NullCacheProvider - // } - - // return base.CreateCacheHelper(); - //} - - protected override void ComposeCacheHelper() - { - // hackish, but it works - var testName = TestContext.CurrentContext.Test.Name; - if (testName == "Can_Get_Pre_Value_As_String_With_Cache" || testName == "Can_Get_Pre_Value_Collection_With_Cache") - { - var cacheHelper = new CacheHelper( - new ObjectCacheRuntimeCacheProvider(), - new StaticCacheProvider(), - new StaticCacheProvider(), - new IsolatedRuntimeCache(type => new ObjectCacheRuntimeCacheProvider())); // default would be NullCacheProvider - - Container.RegisterSingleton(f => cacheHelper); - Container.RegisterSingleton(f => f.GetInstance().RuntimeCache); - } - else - { - base.ComposeCacheHelper(); - } - } - private IDataTypeRepository CreateRepository() { return Container.GetInstance(); @@ -73,7 +32,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); var accessor = (IScopeAccessor) provider; - using (var scope = provider.CreateScope()) + using (provider.CreateScope()) { var containerRepository = CreateContainerRepository(accessor); var repository = CreateRepository(); @@ -98,7 +57,7 @@ namespace Umbraco.Tests.Persistence.Repositories var result = repository.Move(dataType, container1).ToArray(); - Assert.AreEqual(2, result.Count()); + Assert.AreEqual(2, result.Length); //re-get dataType = repository.Get(dataType.Id); @@ -116,7 +75,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); var accessor = (IScopeAccessor) provider; - using (var scope = provider.CreateScope()) + using (provider.CreateScope()) { var containerRepository = CreateContainerRepository(accessor); var container = new EntityContainer(Constants.ObjectTypes.DataType) { Name = "blah" }; @@ -135,7 +94,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); var accessor = (IScopeAccessor) provider; - using (var scope = provider.CreateScope()) + using (provider.CreateScope()) { var containerRepository = CreateContainerRepository(accessor); var container = new EntityContainer(Constants.ObjectTypes.DataType) { Name = "blah" }; @@ -155,7 +114,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); var accessor = (IScopeAccessor) provider; - using (var scope = provider.CreateScope()) + using (provider.CreateScope()) { var containerRepository = CreateContainerRepository(accessor); var repository = CreateRepository(); @@ -175,7 +134,7 @@ namespace Umbraco.Tests.Persistence.Repositories var provider = TestObjects.GetScopeProvider(Logger); var accessor = (IScopeAccessor) provider; - using (var scope = provider.CreateScope()) + using (provider.CreateScope()) { var containerRepository = CreateContainerRepository(accessor); var repository = CreateRepository(); @@ -201,9 +160,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Create() { var provider = TestObjects.GetScopeProvider(Logger); - var accessor = (IScopeAccessor) provider; - using (var scope = provider.CreateScope()) + using (provider.CreateScope()) { var repository = CreateRepository(); IDataType dataType = new DataType(-1, Constants.PropertyEditors.Aliases.RadioButtonList) {Name = "test"}; @@ -227,9 +185,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_DataTypeDefinitionRepository() { var provider = TestObjects.GetScopeProvider(Logger); - var accessor = (IScopeAccessor) provider; - using (var scope = provider.CreateScope()) + using (provider.CreateScope()) { var repository = CreateRepository(); // Act @@ -246,20 +203,19 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_DataTypeDefinitionRepository() { var provider = TestObjects.GetScopeProvider(Logger); - var accessor = (IScopeAccessor) provider; - using (var scope = provider.CreateScope()) + using (provider.CreateScope()) { var repository = CreateRepository(); // Act - var dataTypeDefinitions = repository.GetMany(); + var dataTypeDefinitions = repository.GetMany().ToArray(); // Assert Assert.That(dataTypeDefinitions, Is.Not.Null); Assert.That(dataTypeDefinitions.Any(), Is.True); Assert.That(dataTypeDefinitions.Any(x => x == null), Is.False); - Assert.That(dataTypeDefinitions.Count(), Is.EqualTo(24)); + Assert.That(dataTypeDefinitions.Length, Is.EqualTo(24)); } } @@ -267,20 +223,19 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_With_Params_On_DataTypeDefinitionRepository() { var provider = TestObjects.GetScopeProvider(Logger); - var accessor = (IScopeAccessor) provider; - using (var scope = provider.CreateScope()) + using (provider.CreateScope()) { var repository = CreateRepository(); // Act - var dataTypeDefinitions = repository.GetMany(-40, -41, -42); + var dataTypeDefinitions = repository.GetMany(-40, -41, -42).ToArray(); // Assert Assert.That(dataTypeDefinitions, Is.Not.Null); Assert.That(dataTypeDefinitions.Any(), Is.True); Assert.That(dataTypeDefinitions.Any(x => x == null), Is.False); - Assert.That(dataTypeDefinitions.Count(), Is.EqualTo(3)); + Assert.That(dataTypeDefinitions.Length, Is.EqualTo(3)); } } @@ -288,7 +243,6 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_DataTypeDefinitionRepository() { var provider = TestObjects.GetScopeProvider(Logger); - var accessor = (IScopeAccessor) provider; using (var scope = provider.CreateScope()) { @@ -296,12 +250,12 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var query = scope.SqlContext.Query().Where(x => x.EditorAlias == Constants.PropertyEditors.Aliases.RadioButtonList); - var result = repository.Get(query); + var result = repository.Get(query).ToArray(); // Assert Assert.That(result, Is.Not.Null); Assert.That(result.Any(), Is.True); - Assert.That(result.FirstOrDefault().Name, Is.EqualTo("Radiobox")); + Assert.That(result.FirstOrDefault()?.Name, Is.EqualTo("Radiobox")); } } @@ -309,7 +263,6 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_DataTypeDefinitionRepository() { var provider = TestObjects.GetScopeProvider(Logger); - var accessor = (IScopeAccessor) provider; using (var scope = provider.CreateScope()) { @@ -328,12 +281,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_DataTypeDefinitionRepository() { var provider = TestObjects.GetScopeProvider(Logger); - var accessor = (IScopeAccessor) provider; - using (var scope = provider.CreateScope()) + using (provider.CreateScope()) { var repository = CreateRepository(); - var dataTypeDefinition = new DataType("Test.TestEditor") + var dataTypeDefinition = new DataType(Constants.PropertyEditors.Aliases.NoEdit) { DatabaseType = ValueStorageType.Integer, Name = "AgeDataType", @@ -344,7 +296,6 @@ namespace Umbraco.Tests.Persistence.Repositories repository.Save(dataTypeDefinition); var exists = repository.Exists(dataTypeDefinition.Id); - var fetched = repository.Get(dataTypeDefinition.Id); // Assert @@ -359,12 +310,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_DataTypeDefinitionRepository() { var provider = TestObjects.GetScopeProvider(Logger); - var accessor = (IScopeAccessor) provider; - using (var scope = provider.CreateScope()) + using (provider.CreateScope()) { var repository = CreateRepository(); - var dataTypeDefinition = new DataType("Test.blah") + var dataTypeDefinition = new DataType(Constants.PropertyEditors.Aliases.Integer) { DatabaseType = ValueStorageType.Integer, Name = "AgeDataType", @@ -375,7 +325,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Act var definition = repository.Get(dataTypeDefinition.Id); definition.Name = "AgeDataType Updated"; - definition.EditorAlias = "Test.TestEditor"; //change + definition.EditorAlias = Constants.PropertyEditors.Aliases.NoEdit; //change repository.Save(definition); var definitionUpdated = repository.Get(dataTypeDefinition.Id); @@ -383,7 +333,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Assert Assert.That(definitionUpdated, Is.Not.Null); Assert.That(definitionUpdated.Name, Is.EqualTo("AgeDataType Updated")); - Assert.That(definitionUpdated.EditorAlias, Is.EqualTo("Test.TestEditor")); + Assert.That(definitionUpdated.EditorAlias, Is.EqualTo(Constants.PropertyEditors.Aliases.NoEdit)); } } @@ -391,12 +341,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_DataTypeDefinitionRepository() { var provider = TestObjects.GetScopeProvider(Logger); - var accessor = (IScopeAccessor) provider; - using (var scope = provider.CreateScope()) + using (provider.CreateScope()) { var repository = CreateRepository(); - var dataTypeDefinition = new DataType("Test.TestEditor") + var dataTypeDefinition = new DataType(Constants.PropertyEditors.Aliases.NoEdit) { DatabaseType = ValueStorageType.Integer, Name = "AgeDataType", @@ -422,9 +371,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_DataTypeDefinitionRepository() { var provider = TestObjects.GetScopeProvider(Logger); - var accessor = (IScopeAccessor) provider; - using (var scope = provider.CreateScope()) + using (provider.CreateScope()) { var repository = CreateRepository(); diff --git a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs index 9dc6dc921f..d5da545a8e 100644 --- a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs +++ b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs @@ -1,6 +1,5 @@ using System; using System.Globalization; -using System.Linq; using LightInject; using Moq; using Newtonsoft.Json; @@ -8,12 +7,9 @@ using NUnit.Framework; using Newtonsoft.Json.Linq; using Umbraco.Core; using Umbraco.Core.Composing; -using Umbraco.Core.Logging; -using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.ValueConverters; -using Umbraco.Core.Services; using Umbraco.Web.Models; using Umbraco.Web; @@ -31,31 +27,31 @@ namespace Umbraco.Tests.PropertyEditors public void CanConvertImageCropperDataSetSrcToString() { //cropperJson3 - has not crops - var sourceObj = CropperJson3.SerializeToCropDataSet(); - var destObj = sourceObj.TryConvertTo(); - Assert.IsTrue(destObj.Success); - Assert.AreEqual(destObj.Result, "/media/1005/img_0672.jpg"); + var cropperValue = CropperJson3.DeserializeImageCropperValue(); + var serialized = cropperValue.TryConvertTo(); + Assert.IsTrue(serialized.Success); + Assert.AreEqual("/media/1005/img_0672.jpg", serialized.Result); } [Test] public void CanConvertImageCropperDataSetJObject() { //cropperJson3 - has not crops - var sourceObj = CropperJson3.SerializeToCropDataSet(); - var destObj = sourceObj.TryConvertTo(); - Assert.IsTrue(destObj.Success); - Assert.AreEqual(sourceObj, destObj.Result.ToObject()); + var cropperValue = CropperJson3.DeserializeImageCropperValue(); + var serialized = cropperValue.TryConvertTo(); + Assert.IsTrue(serialized.Success); + Assert.AreEqual(cropperValue, serialized.Result.ToObject()); } [Test] public void CanConvertImageCropperDataSetJsonToString() { - var sourceObj = CropperJson1.SerializeToCropDataSet(); - var destObj = sourceObj.TryConvertTo(); - Assert.IsTrue(destObj.Success); - Assert.IsTrue(destObj.Result.DetectIsJson()); + var cropperValue = CropperJson1.DeserializeImageCropperValue(); + var serialized = cropperValue.TryConvertTo(); + Assert.IsTrue(serialized.Success); + Assert.IsTrue(serialized.Result.DetectIsJson()); var obj = JsonConvert.DeserializeObject(CropperJson1, new JsonSerializerSettings {Culture = CultureInfo.InvariantCulture, FloatParseHandling = FloatParseHandling.Decimal}); - Assert.AreEqual(sourceObj, obj); + Assert.AreEqual(cropperValue, obj); } [TestCase(CropperJson1, CropperJson1, true)] @@ -68,11 +64,11 @@ namespace Umbraco.Tests.PropertyEditors container.ConfigureUmbracoCore(); container.RegisterCollectionBuilder(); - var converter = new Core.PropertyEditors.ValueConverters.ImageCropperValueConverter(); + var converter = new ImageCropperValueConverter(); var factory = new PublishedContentTypeFactory(Mock.Of(), new PropertyValueConverterCollection(Array.Empty()), Mock.Of()); var result = converter.ConvertSourceToIntermediate(null, factory.CreatePropertyType("test", 0, "test"), val1, false); // does not use type for conversion - var resultShouldMatch = val2.SerializeToCropDataSet(); + var resultShouldMatch = val2.DeserializeImageCropperValue(); if (expected) { Assert.AreEqual(resultShouldMatch, result); @@ -84,7 +80,7 @@ namespace Umbraco.Tests.PropertyEditors } finally { - Core.Composing.Current.Reset(); + Current.Reset(); } } @@ -142,7 +138,7 @@ namespace Umbraco.Tests.PropertyEditors [Test] public void GetBaseCropUrlFromModelTest() { - var cropDataSet = CropperJson1.SerializeToCropDataSet(); + var cropDataSet = CropperJson1.DeserializeImageCropperValue(); var urlString = cropDataSet.GetCropUrl("thumb"); Assert.AreEqual("?crop=0.58729977382575338,0.055768992440203169,0,0.32457553600198386&cropmode=percentage&width=100&height=100", urlString); } diff --git a/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs b/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs index 7dcfef3c89..9f9425e71a 100644 --- a/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Globalization; using Moq; +using Newtonsoft.Json; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; @@ -63,7 +64,7 @@ namespace Umbraco.Tests.PropertyEditors var editor = new PublishValuesMultipleValueEditor(false, Mock.Of(), new ValueEditorAttribute("alias", "name", "view")); - var prop = new Property(1, new PropertyType(new DataType(1, "Test.TestEditor"))); + var prop = new Property(1, new PropertyType(new DataType(1, "Test.TestEditor") { Id = 1 })); prop.SetValue("1234,4567,8910"); var result = editor.ConvertDbToString(prop.PropertyType, prop.GetValue(), dataTypeService); @@ -95,7 +96,7 @@ namespace Umbraco.Tests.PropertyEditors var editor = new PublishValueValueEditor(new ValueEditorAttribute("alias", "name", "view"), Mock.Of()); - var prop = new Property(1, new PropertyType(new DataType(1, "Test.TestEditor"))); + var prop = new Property(1, new PropertyType(new DataType(1, "Test.TestEditor") { Id = 1 })); prop.SetValue("1234"); var result = editor.ConvertDbToString(prop.PropertyType, prop.GetValue(), dataTypeService); @@ -138,14 +139,10 @@ namespace Umbraco.Tests.PropertyEditors var result = editor.ToEditor(defaultVals, configuration); - Assert.AreEqual(1, result.Count); - Assert.IsTrue(result.ContainsKey("items")); - var items = result["items"] as IDictionary>; - Assert.IsNotNull(items); - Assert.AreEqual("Item 1", items[1]["value"]); - Assert.AreEqual("Item 2", items[2]["value"]); - Assert.AreEqual("Item 3", items[3]["value"]); + // 'result' is meant to be serialized, is built with anonymous objects + // so we cannot really test what's in it - but by serializing it + var json = JsonConvert.SerializeObject(result); + Assert.AreEqual("{\"items\":{\"1\":{\"value\":\"Item 1\",\"sortOrder\":1},\"2\":{\"value\":\"Item 2\",\"sortOrder\":2},\"3\":{\"value\":\"Item 3\",\"sortOrder\":3}}}", json); } - } } diff --git a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs index ab95929c4c..165130fef3 100644 --- a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs @@ -55,8 +55,7 @@ namespace Umbraco.Tests.PropertyEditors [TestCase("STRING", "hello", "hello")] [TestCase("TEXT", "hello", "hello")] [TestCase("INT", "123", 123)] - [TestCase("INTEGER", "123", 123)] - [TestCase("INTEGER", "", null)] //test empty string for int + [TestCase("INT", "", null)] //test empty string for int [TestCase("DATETIME", "", null)] //test empty string for date public void Value_Editor_Can_Convert_To_Clr_Type(string valueType, string val, object expected) { diff --git a/src/Umbraco.Tests/Published/NestedContentTests.cs b/src/Umbraco.Tests/Published/NestedContentTests.cs index 95320ab144..c333032599 100644 --- a/src/Umbraco.Tests/Published/NestedContentTests.cs +++ b/src/Umbraco.Tests/Published/NestedContentTests.cs @@ -36,7 +36,7 @@ namespace Umbraco.Tests.Published Configuration = new NestedContentConfiguration { MinItems = 1, - MaxItems = 2, + MaxItems = 1, ContentTypes = new[] { new NestedContentConfiguration.ContentType { Alias = "contentN1" } diff --git a/src/Umbraco.Tests/Services/CachedDataTypeServiceTests.cs b/src/Umbraco.Tests/Services/CachedDataTypeServiceTests.cs index cf57220fb5..937117f952 100644 --- a/src/Umbraco.Tests/Services/CachedDataTypeServiceTests.cs +++ b/src/Umbraco.Tests/Services/CachedDataTypeServiceTests.cs @@ -1,4 +1,5 @@ using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Tests.Testing; @@ -20,7 +21,7 @@ namespace Umbraco.Tests.Services { var dataTypeService = ServiceContext.DataTypeService; - IDataType dataType = new DataType(-1, "Test.TestEditor") { Name = "Testing Textfield", DatabaseType = ValueStorageType.Ntext }; + IDataType dataType = new DataType(-1, Constants.PropertyEditors.Aliases.NoEdit) { Name = "Testing Textfield", DatabaseType = ValueStorageType.Ntext }; dataTypeService.Save(dataType); //Get all the first time (no cache) diff --git a/src/Umbraco.Tests/Services/DataTypeServiceTests.cs b/src/Umbraco.Tests/Services/DataTypeServiceTests.cs index 2f5833f3a8..5491017dae 100644 --- a/src/Umbraco.Tests/Services/DataTypeServiceTests.cs +++ b/src/Umbraco.Tests/Services/DataTypeServiceTests.cs @@ -24,7 +24,7 @@ namespace Umbraco.Tests.Services var dataTypeService = ServiceContext.DataTypeService; // Act - IDataType dataType = new DataType(-1, "Test.TestEditor") { Name = "Testing Textfield", DatabaseType = ValueStorageType.Ntext }; + IDataType dataType = new DataType(-1, Constants.PropertyEditors.Aliases.NoEdit) { Name = "Testing Textfield", DatabaseType = ValueStorageType.Ntext }; dataTypeService.Save(dataType); // Assert diff --git a/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs b/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs index b1ba59e5c1..c60c8e2c06 100644 --- a/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs +++ b/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs @@ -152,7 +152,7 @@ namespace Umbraco.Tests.TestHelpers.Entities var contentCollection = new PropertyTypeCollection(true); contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.Textbox, ValueStorageType.Ntext) { Alias = "title", Name = "Title", Description = "", Mandatory = false, SortOrder = 1, DataTypeId = -88 }); - contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.Textbox, ValueStorageType.Ntext) { Alias = "bodyText", Name = "Body Text", Description = "", Mandatory = false, SortOrder = 2, DataTypeId = -87 }); + contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.TinyMce, ValueStorageType.Ntext) { Alias = "bodyText", Name = "Body Text", Description = "", Mandatory = false, SortOrder = 2, DataTypeId = -87 }); contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.Textbox, ValueStorageType.Ntext) { Alias = "author", Name = "Author", Description = "Name of the author", Mandatory = false, SortOrder = 3, DataTypeId = -88 }); contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = "Content", SortOrder = 1 }); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index ffb93c8b79..76c6fa7d44 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -303,6 +303,7 @@ namespace Umbraco.Tests.Testing Container.RegisterSingleton(); // somehow property editor ends up wanting this + Container.RegisterCollectionBuilder(); Container.RegisterSingleton(); // note - don't register collections, use builders diff --git a/src/Umbraco.Web/Editors/DataTypeController.cs b/src/Umbraco.Web/Editors/DataTypeController.cs index 48d74cc1bb..289a7b19bf 100644 --- a/src/Umbraco.Web/Editors/DataTypeController.cs +++ b/src/Umbraco.Web/Editors/DataTypeController.cs @@ -197,20 +197,18 @@ namespace Umbraco.Web.Editors //TODO: Check if the property editor has changed, if it has ensure we don't pass the // existing values to the new property editor! - //get the configuration, current and new - var newConfiguration = dataType.ConfigurationFields.ToDictionary(x => x.Key, x => x.Value); + // get the current configuration, + // get the new configuration as a dictionary (this is how we get it from model) + // and map it to an actual configuration object var currentConfiguration = dataType.PersistedDataType.Configuration; + var configurationDictionary = dataType.ConfigurationFields.ToDictionary(x => x.Key, x => x.Value); + var configuration = dataType.PropertyEditor.ConfigurationEditor.FromEditor(configurationDictionary, currentConfiguration); - // fixme FromEditor should accept a dictionary - // then ToEditor should return a dictionary! - - //we need to allow for the property editor to deserialize the prevalues - var configuration = dataType.PropertyEditor.ConfigurationEditor.FromEditor(newConfiguration, currentConfiguration); dataType.PersistedDataType.Configuration = configuration; + // save the data type try { - //save the data type Services.DataTypeService.Save(dataType.PersistedDataType, Security.CurrentUser.Id); } catch (DuplicateNameException ex) @@ -219,10 +217,9 @@ namespace Umbraco.Web.Editors throw new HttpResponseException(Request.CreateValidationErrorResponse(ModelState)); } + // map back to display model, and return var display = Mapper.Map(dataType.PersistedDataType); display.AddSuccessNotification(Services.TextService.Localize("speechBubbles/dataTypeSaved"), ""); - - //now return the updated model return display; } diff --git a/src/Umbraco.Web/ImageCropperTemplateExtensions.cs b/src/Umbraco.Web/ImageCropperTemplateExtensions.cs index 48cb1df141..ed134d2e58 100644 --- a/src/Umbraco.Web/ImageCropperTemplateExtensions.cs +++ b/src/Umbraco.Web/ImageCropperTemplateExtensions.cs @@ -236,7 +236,7 @@ namespace Umbraco.Web ImageCropperValue cropDataSet = null; if (string.IsNullOrEmpty(imageCropperValue) == false && imageCropperValue.DetectIsJson() && (imageCropMode == ImageCropMode.Crop || imageCropMode == null)) { - cropDataSet = imageCropperValue.SerializeToCropDataSet(); + cropDataSet = imageCropperValue.DeserializeImageCropperValue(); } return GetCropUrl( imageUrl, cropDataSet, width, height, cropAlias, quality, imageCropMode, @@ -318,11 +318,12 @@ namespace Umbraco.Web { var crop = cropDataSet.GetCrop(cropAlias); + // if a crop was specified, but not found, return null if (crop == null && !string.IsNullOrWhiteSpace(cropAlias)) - return null; // fixme is this ok? compared to what we had? + return null; imageProcessorUrl.Append(cropDataSet.Src); - cropDataSet.AppendCropBaseUrl(imageProcessorUrl, crop, preferFocalPoint); + cropDataSet.AppendCropBaseUrl(imageProcessorUrl, crop, string.IsNullOrWhiteSpace(cropAlias), preferFocalPoint); if (crop != null & useCropDimensions) { @@ -431,8 +432,7 @@ namespace Umbraco.Web return string.Empty; } - // fixme this is DEserialize !! arf! - internal static ImageCropperValue SerializeToCropDataSet(this string json) + internal static ImageCropperValue DeserializeImageCropperValue(this string json) { var imageCrops = new ImageCropperValue(); if (json.DetectIsJson()) diff --git a/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs index 5ebd5956d4..73f474c46d 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs @@ -56,6 +56,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.Alias, opt => opt.Ignore()) .ForMember(dest => dest.Tabs, opt => opt.ResolveUsing(src => tabsAndPropertiesResolver.Resolve(src))) .ForMember(dest => dest.AllowedActions, opt => opt.ResolveUsing(src => actionButtonsResolver.Resolve(src))) + .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()) .AfterMap((src, dest) => AfterMap(src, dest, dataTypeService, textService, contentTypeService, contentService)); //FROM IContent TO ContentItemBasic @@ -67,7 +68,8 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.Icon, opt => opt.MapFrom(src => src.ContentType.Icon)) .ForMember(dest => dest.Trashed, opt => opt.MapFrom(src => src.Trashed)) .ForMember(dest => dest.ContentTypeAlias, opt => opt.MapFrom(src => src.ContentType.Alias)) - .ForMember(dest => dest.Alias, opt => opt.Ignore()); + .ForMember(dest => dest.Alias, opt => opt.Ignore()) + .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()); //FROM IContent TO ContentItemDto CreateMap>() @@ -76,7 +78,8 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.Owner, opt => opt.ResolveUsing(src => contentOwnerResolver.Resolve(src))) .ForMember(dest => dest.Updater, opt => opt.Ignore()) .ForMember(dest => dest.Icon, opt => opt.Ignore()) - .ForMember(dest => dest.Alias, opt => opt.Ignore()); + .ForMember(dest => dest.Alias, opt => opt.Ignore()) + .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()); } /// diff --git a/src/Umbraco.Web/Models/Mapping/ContentTypeMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/ContentTypeMapperProfile.cs index 466f21ca5a..c53c6177d0 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentTypeMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentTypeMapperProfile.cs @@ -160,13 +160,16 @@ namespace Umbraco.Web.Models.Mapping CreateMap() .ForMember(dest => dest.Udi, opt => opt.MapFrom(source => Udi.Create(Constants.UdiEntityType.MemberType, source.Key))) - .ForMember(dest => dest.Blueprints, opt => opt.Ignore()); + .ForMember(dest => dest.Blueprints, opt => opt.Ignore()) + .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()); CreateMap() .ForMember(dest => dest.Udi, opt => opt.MapFrom(source => Udi.Create(Constants.UdiEntityType.MediaType, source.Key))) - .ForMember(dest => dest.Blueprints, opt => opt.Ignore()); + .ForMember(dest => dest.Blueprints, opt => opt.Ignore()) + .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()); CreateMap() .ForMember(dest => dest.Udi, opt => opt.MapFrom(source => Udi.Create(Constants.UdiEntityType.DocumentType, source.Key))) - .ForMember(dest => dest.Blueprints, opt => opt.Ignore()); + .ForMember(dest => dest.Blueprints, opt => opt.Ignore()) + .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()); CreateMap() diff --git a/src/Umbraco.Web/Models/Mapping/ContentTypeProfileExtensions.cs b/src/Umbraco.Web/Models/Mapping/ContentTypeProfileExtensions.cs index 4de7439e0e..d67eaf8ea2 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentTypeProfileExtensions.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentTypeProfileExtensions.cs @@ -141,7 +141,8 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.AllowedContentTypes, opt => opt.MapFrom(src => src.AllowedContentTypes.Select(x => x.Id.Value))) .ForMember(dest => dest.CompositeContentTypes, opt => opt.MapFrom(src => src.ContentTypeComposition)) .ForMember(dest => dest.LockedCompositeContentTypes, opt => opt.ResolveUsing(src => lockedCompositionsResolver.Resolve(src))) - .ForMember(dest => dest.Groups, opt => opt.ResolveUsing(src => propertyTypeGroupResolver.Resolve(src))); + .ForMember(dest => dest.Groups, opt => opt.ResolveUsing(src => propertyTypeGroupResolver.Resolve(src))) + .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()); } /// diff --git a/src/Umbraco.Web/Models/Mapping/DataTypeConfigurationFieldDisplayResolver.cs b/src/Umbraco.Web/Models/Mapping/DataTypeConfigurationFieldDisplayResolver.cs index d86ad1cf3b..efc538a8a0 100644 --- a/src/Umbraco.Web/Models/Mapping/DataTypeConfigurationFieldDisplayResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/DataTypeConfigurationFieldDisplayResolver.cs @@ -41,6 +41,7 @@ namespace Umbraco.Web.Models.Mapping throw new InvalidOperationException($"Could not find a property editor with alias \"{dataType.EditorAlias}\"."); var configuration = dataType.Configuration; + Dictionary configurationDictionary = null; var fields = Array.Empty(); // if we have a property editor, @@ -49,14 +50,13 @@ namespace Umbraco.Web.Models.Mapping if (editor != null) { fields = editor.ConfigurationEditor.Fields.Select(Mapper.Map).ToArray(); - configuration = editor.ConfigurationEditor.ToEditor(editor.DefaultConfiguration, configuration); + configurationDictionary = editor.ConfigurationEditor.ToEditor(editor.DefaultConfiguration, configuration); } - // either it's a dictionary already, or convert - // fixme if it's no a dictionary we should just throw at that point - var dictionary = configuration as IDictionary ?? ObjectExtensions.ToObjectDictionary(configuration); + if (configurationDictionary == null) + configurationDictionary = new Dictionary(); - MapPreValueValuesToPreValueFields(fields, dictionary); + MapPreValueValuesToPreValueFields(fields, configurationDictionary); return fields; } diff --git a/src/Umbraco.Web/Models/Mapping/DataTypeMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/DataTypeMapperProfile.cs index 1044b0f104..0bd2ceab54 100644 --- a/src/Umbraco.Web/Models/Mapping/DataTypeMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/DataTypeMapperProfile.cs @@ -20,7 +20,7 @@ namespace Umbraco.Web.Models.Mapping { // create, capture, cache var availablePropertyEditorsResolver = new AvailablePropertyEditorsResolver(UmbracoConfig.For.UmbracoSettings().Content); - var preValueDisplayResolver = new DataTypeConfigurationFieldDisplayResolver(); + var configurationDisplayResolver = new DataTypeConfigurationFieldDisplayResolver(); var databaseTypeResolver = new DatabaseTypeResolver(); CreateMap(); @@ -54,6 +54,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.Alias, opt => opt.Ignore()) .ForMember(dest => dest.Group, opt => opt.Ignore()) .ForMember(dest => dest.IsSystemDataType, opt => opt.MapFrom(src => systemIds.Contains(src.Id))) + .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()) .AfterMap((src, dest) => { if (Current.PropertyEditors.TryGet(src.EditorAlias, out var editor)) @@ -67,7 +68,7 @@ namespace Umbraco.Web.Models.Mapping CreateMap() .ForMember(dest => dest.Udi, opt => opt.MapFrom(src => Udi.Create(Constants.UdiEntityType.DataType, src.Key))) .ForMember(dest => dest.AvailableEditors, opt => opt.ResolveUsing(src => availablePropertyEditorsResolver.Resolve(src))) - .ForMember(dest => dest.PreValues, opt => opt.ResolveUsing(src => preValueDisplayResolver.Resolve(src))) + .ForMember(dest => dest.PreValues, opt => opt.ResolveUsing(src => configurationDisplayResolver.Resolve(src))) .ForMember(dest => dest.SelectedEditor, opt => opt.MapFrom(src => src.EditorAlias.IsNullOrWhiteSpace() ? null : src.EditorAlias)) .ForMember(dest => dest.HasPrevalues, opt => opt.Ignore()) .ForMember(dest => dest.Notifications, opt => opt.Ignore()) @@ -75,6 +76,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.Alias, opt => opt.Ignore()) .ForMember(dest => dest.Group, opt => opt.Ignore()) .ForMember(dest => dest.IsSystemDataType, opt => opt.MapFrom(src => systemIds.Contains(src.Id))) + .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()) .AfterMap((src, dest) => { if (Current.PropertyEditors.TryGet(src.EditorAlias, out var editor)) @@ -86,7 +88,7 @@ namespace Umbraco.Web.Models.Mapping //gets a list of PreValueFieldDisplay objects from the data type definition CreateMap>() - .ConvertUsing(src => preValueDisplayResolver.Resolve(src)); + .ConvertUsing(src => configurationDisplayResolver.Resolve(src)); CreateMap() .ConstructUsing(src => new DataType(src.EditorAlias) {CreateDate = DateTime.Now}) @@ -98,7 +100,8 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.DatabaseType, opt => opt.ResolveUsing(src => databaseTypeResolver.Resolve(src))) .ForMember(dest => dest.CreatorId, opt => opt.Ignore()) .ForMember(dest => dest.Level, opt => opt.Ignore()) - .ForMember(dest => dest.SortOrder, opt => opt.Ignore()); + .ForMember(dest => dest.SortOrder, opt => opt.Ignore()) + .ForMember(dest => dest.Configuration, opt => opt.Ignore()); //Converts a property editor to a new list of pre-value fields - used when creating a new data type or changing a data type with new pre-vals CreateMap>() diff --git a/src/Umbraco.Web/Models/Mapping/MediaMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/MediaMapperProfile.cs index 9360466d76..70329a0d48 100644 --- a/src/Umbraco.Web/Models/Mapping/MediaMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/MediaMapperProfile.cs @@ -43,6 +43,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.Alias, opt => opt.Ignore()) .ForMember(dest => dest.IsContainer, opt => opt.Ignore()) .ForMember(dest => dest.Tabs, opt => opt.ResolveUsing(src => tabsAndPropertiesResolver.Resolve(src))) + .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()) .AfterMap((src, dest) => AfterMap(src, dest, dataTypeService, textService, logger, mediaService)); //FROM IMedia TO ContentItemBasic @@ -54,7 +55,8 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.ContentTypeAlias, opt => opt.MapFrom(src => src.ContentType.Alias)) .ForMember(dest => dest.Published, opt => opt.Ignore()) .ForMember(dest => dest.Updater, opt => opt.Ignore()) - .ForMember(dest => dest.Alias, opt => opt.Ignore()); + .ForMember(dest => dest.Alias, opt => opt.Ignore()) + .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()); //FROM IMedia TO ContentItemDto CreateMap>() @@ -63,7 +65,8 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.Published, opt => opt.Ignore()) .ForMember(dest => dest.Updater, opt => opt.Ignore()) .ForMember(dest => dest.Icon, opt => opt.Ignore()) - .ForMember(dest => dest.Alias, opt => opt.Ignore()); + .ForMember(dest => dest.Alias, opt => opt.Ignore()) + .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()); } private static void AfterMap(IMedia media, MediaItemDisplay display, IDataTypeService dataTypeService, ILocalizedTextService localizedText, ILogger logger, IMediaService mediaService) diff --git a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyValueEditor.cs b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyValueEditor.cs index 53c55c31ed..8dfb99422a 100644 --- a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyValueEditor.cs @@ -161,19 +161,16 @@ namespace Umbraco.Web.PropertyEditors if (value == null || string.IsNullOrEmpty(value.ToString())) return null; - // fixme - no idea of what we should do here, and ConvertDbToString should die anyways - throw new NotImplementedException(); + // if we dont have a json structure, we will get it from the property type + var val = value.ToString(); + if (val.DetectIsJson()) + return val; - //// if we dont have a json structure, we will get it from the property type - //var val = value.ToString(); - //if (val.DetectIsJson()) - // return val; - - //// more magic here ;-( - //var config = dataTypeService.GetPreValuesByDataTypeId(propertyType.DataTypeId).FirstOrDefault(); - //var crops = string.IsNullOrEmpty(config) ? "[]" : config; - //var newVal = "{src: '" + val + "', crops: " + crops + "}"; - //return newVal; + // more magic here ;-( + var configuration = dataTypeService.GetDataType(propertyType.DataTypeId).ConfigurationAs(); + var crops = configuration?.Crops; // fixme but Crops should not be a string and then we'd serialize them + if (string.IsNullOrWhiteSpace(crops)) crops = "[]"; + return "{src: '" + val + "', crops: " + crops + "}"; } } } diff --git a/src/Umbraco.Web/PropertyEditors/PublishValueValueEditor.cs b/src/Umbraco.Web/PropertyEditors/PublishValueValueEditor.cs index 6f5ad91aa5..a594252ef3 100644 --- a/src/Umbraco.Web/PropertyEditors/PublishValueValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/PublishValueValueEditor.cs @@ -32,9 +32,12 @@ namespace Umbraco.Web.PropertyEditors if (value == null) return null; - // fixme we should probably completely kill this editor - + // get the configuration items + // if none, fallback to base var configuration = dataTypeService.GetDataType(propertyType.DataTypeId).ConfigurationAs(); + if (configuration == null) + return base.ConvertDbToString(propertyType, value, dataTypeService); + var items = configuration.Items; var idAttempt = value.TryConvertTo(); diff --git a/src/Umbraco.Web/PropertyEditors/PublishValuesMultipleValueEditor.cs b/src/Umbraco.Web/PropertyEditors/PublishValuesMultipleValueEditor.cs index 378419b02f..2a1788b93b 100644 --- a/src/Umbraco.Web/PropertyEditors/PublishValuesMultipleValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/PublishValuesMultipleValueEditor.cs @@ -49,16 +49,18 @@ namespace Umbraco.Web.PropertyEditors return propertyValue.ToString(); } - //get the multiple ids + // get the multiple ids + // if none, fallback to base var selectedIds = propertyValue.ToString().Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries); if (selectedIds.Any() == false) - { - //nothing there, fallback to base return base.ConvertDbToString(propertyType, propertyValue, dataTypeService); - } - // fixme I have no idea what I'm doing here + // get the configuration items + // if none, fallback to base var configuration = dataTypeService.GetDataType(propertyType.DataTypeId).ConfigurationAs(); + if (configuration == null) + return base.ConvertDbToString(propertyType, propertyValue, dataTypeService); + var items = configuration.Items.Where(x => selectedIds.Contains(x.Id.ToInvariantString())).Select(x => x.Value); return string.Join(",", items); } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index eb282ccf50..b01881af10 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -473,7 +473,6 @@ -