diff --git a/src/Umbraco.Core/Constants-PropertyEditors.cs b/src/Umbraco.Core/Constants-PropertyEditors.cs
index 126613cdb3..b09987ad90 100644
--- a/src/Umbraco.Core/Constants-PropertyEditors.cs
+++ b/src/Umbraco.Core/Constants-PropertyEditors.cs
@@ -44,26 +44,6 @@ namespace Umbraco.Core
///
public const string DateTime = "Umbraco.DateTime";
- ///
- /// DropDown List.
- ///
- public const string DropDownList = "Umbraco.DropDown";
-
- ///
- /// DropDown List, Publish Keys.
- ///
- public const string DropdownlistPublishKeys = "Umbraco.DropdownlistPublishingKeys";
-
- ///
- /// DropDown List Multiple.
- ///
- public const string DropDownListMultiple = "Umbraco.DropDownMultiple";
-
- ///
- /// DropDown List Multiple, Publish Keys.
- ///
- public const string DropdownlistMultiplePublishKeys = "Umbraco.DropdownlistMultiplePublishKeys";
-
///
/// DropDown List.
///
diff --git a/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs b/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs
index c4ebfb664b..eb7cafcb01 100644
--- a/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs
+++ b/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs
@@ -117,7 +117,7 @@ namespace Umbraco.Core.Migrations.Install
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DropDownMultiple, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DropDownMultiple}", SortOrder = 2, UniqueId = new Guid("0b6a45e7-44ba-430d-9da5-4e46060b9e03"), Text = "Dropdown", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -41, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-41", SortOrder = 2, UniqueId = new Guid("5046194e-4237-453c-a547-15db3a07c4e1"), Text = "Date Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -40, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-40", SortOrder = 2, UniqueId = new Guid("bb5f57c9-ce2b-4bb9-b697-4caca783a805"), Text = "Radiobox", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
- _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -39, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-39", SortOrder = 2, UniqueId = new Guid("f38f0ac7-1d27-439c-9f3f-089cd8825a53"), Text = "Dropdown multiple", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
+ _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DropDownSingle, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DropDownSingle}", SortOrder = 2, UniqueId = new Guid("f38f0ac7-1d27-439c-9f3f-089cd8825a53"), Text = "Dropdown multiple", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -37, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-37", SortOrder = 2, UniqueId = new Guid("0225af17-b302-49cb-9176-b9f35cab9c17"), Text = "Approved Color", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -36, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-36", SortOrder = 2, UniqueId = new Guid("e4d66c0f-b935-4200-81f0-025f7256b89a"), Text = "Date Picker with time", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultContentListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DefaultContentListView}", SortOrder = 2, UniqueId = new Guid("C0808DD3-8133-4E4B-8CE8-E2BEA84A96A4"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Content", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
diff --git a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs
index 5b0838573e..9ad7ccb48e 100644
--- a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs
+++ b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs
@@ -138,6 +138,8 @@ namespace Umbraco.Core.Migrations.Upgrade
Chain("{6A2C7C1B-A9DB-4EA9-B6AB-78E7D5B722A7}");
Chain("{77874C77-93E5-4488-A404-A630907CEEF0}");
+ Chain("{23275462-446E-44C7-8C2C-3B8C1127B07D}");
+ Chain("{6B251841-3069-4AD5-8AE9-861F9523E8DA}");
//FINAL
diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DataTypeMigration.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DataTypeMigration.cs
index eb39f37112..d7180385f0 100644
--- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DataTypeMigration.cs
+++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DataTypeMigration.cs
@@ -7,10 +7,11 @@ using NPoco;
using Umbraco.Core.Migrations.Install;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Dtos;
-using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Persistence.Querying;
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
{
+
public class DataTypeMigration : MigrationBase
{
public DataTypeMigration(IMigrationContext context)
@@ -79,10 +80,6 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
Database.Update(dataType);
}
-
- // drop preValues table
- // FIXME keep it around for now
- //Delete.Table("cmsDataTypePreValues");
}
[TableName("cmsDataTypePreValues")]
diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs
new file mode 100644
index 0000000000..c9eba205e8
--- /dev/null
+++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs
@@ -0,0 +1,145 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Newtonsoft.Json;
+using Umbraco.Core.Persistence;
+using Umbraco.Core.Persistence.Dtos;
+using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Logging;
+
+namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
+{
+ public class DropDownPropertyEditorsMigration : MigrationBase
+ {
+ public DropDownPropertyEditorsMigration(IMigrationContext context) : base(context)
+ {
+ }
+
+ public override void Migrate()
+ {
+ //need to convert the old drop down data types to use the new one
+ var oldDropDowns = Database.Fetch(Sql().Select().Where(x => x.EditorAlias.Contains(".DropDown")));
+ foreach(var dd in oldDropDowns)
+ {
+ //nothing to change if there is no config
+ if (dd.Configuration.IsNullOrWhiteSpace()) continue;
+
+ ValueListConfiguration config;
+ try
+ {
+ config = JsonConvert.DeserializeObject(dd.Configuration);
+ }
+ catch (Exception ex)
+ {
+ Logger.Error(ex, $"Invalid drop down configuration detected: \"{dd.Configuration}\", cannot convert editor, values will be cleared");
+ dd.Configuration = null;
+ Database.Update(dd);
+ continue;
+ }
+
+ var propDataSql = Sql().Select("*").From()
+ .InnerJoin().On(x => x.Id, x => x.PropertyTypeId)
+ .InnerJoin().On(x => x.NodeId, x => x.DataTypeId)
+ .Where(x => x.EditorAlias == dd.EditorAlias);
+
+ var propDatas = Database.Query(propDataSql);
+ var toUpdate = new List();
+ foreach (var propData in propDatas)
+ {
+ if (UpdatePropertyDataDto(propData, config))
+ {
+ //update later, we are iterating all values right now so no SQL can be run inside of this iteration (i.e. Query)
+ toUpdate.Add(propData);
+ }
+ }
+
+ //run the property data updates
+ foreach(var propData in toUpdate)
+ {
+ Database.Update(propData);
+ }
+
+ var requiresCacheRebuild = false;
+ switch (dd.EditorAlias)
+ {
+ case "Umbraco.DropDown":
+ UpdateDataType(dd, config, false);
+ break;
+ case "Umbraco.DropdownlistPublishingKeys":
+ UpdateDataType(dd, config, false);
+ requiresCacheRebuild = true;
+ break;
+ case "Umbraco.DropDownMultiple":
+ UpdateDataType(dd, config, false);
+ break;
+ case "Umbraco.DropdownlistMultiplePublishKeys":
+ UpdateDataType(dd, config, true);
+ requiresCacheRebuild = true;
+ break;
+ }
+
+ if (requiresCacheRebuild)
+ {
+ //TODO: How to force rebuild the cache?
+ }
+ }
+ }
+
+ private void UpdateDataType(DataTypeDto dataType, ValueListConfiguration config, bool isMultiple)
+ {
+ dataType.EditorAlias = Constants.PropertyEditors.Aliases.DropDownListFlexible;
+ var flexConfig = new
+ {
+ multiple = isMultiple,
+ items = config.Items
+ };
+ dataType.Configuration = JsonConvert.SerializeObject(flexConfig);
+ }
+
+ private bool UpdatePropertyDataDto(PropertyDataDto propData, ValueListConfiguration config)
+ {
+ //Get the INT ids stored for this property/drop down
+ IEnumerable ids = null;
+ if (!propData.VarcharValue.IsNullOrWhiteSpace())
+ {
+ ids = ConvertStringValues(propData.VarcharValue);
+ }
+ else if (!propData.TextValue.IsNullOrWhiteSpace())
+ {
+ ids = ConvertStringValues(propData.TextValue);
+ }
+ else if (propData.IntegerValue.HasValue)
+ {
+ ids = new[] { propData.IntegerValue.Value };
+ }
+
+ //if there are INT ids, convert them to values based on the configured pre-values
+ if (ids != null)
+ {
+ //map the ids to values
+ var vals = new List();
+ foreach (var id in ids)
+ {
+ var val = config.Items.FirstOrDefault(x => x.Id == id);
+ if (val != null)
+ vals.Add(val.Value);
+ }
+
+ propData.VarcharValue = string.Join(",", vals);
+ propData.TextValue = null;
+ propData.IntegerValue = null;
+ return true;
+ }
+
+ return false;
+ }
+
+ private IEnumerable ConvertStringValues(string val)
+ {
+ return val.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
+ .Select(x => int.TryParse(x, out var i) ? i : int.MinValue)
+ .Where(x => x != int.MinValue);
+ }
+
+ }
+}
diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropPreValueTable.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropPreValueTable.cs
new file mode 100644
index 0000000000..26402cc477
--- /dev/null
+++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/DropPreValueTable.cs
@@ -0,0 +1,15 @@
+namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
+{
+ public class DropPreValueTable : MigrationBase
+ {
+ public DropPreValueTable(IMigrationContext context) : base(context)
+ {
+ }
+
+ public override void Migrate()
+ {
+ // drop preValues table
+ Delete.Table("cmsDataTypePreValues").Do();
+ }
+ }
+}
diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListMultipleValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListMultipleValueConverter.cs
deleted file mode 100644
index d91f45292c..0000000000
--- a/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListMultipleValueConverter.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Umbraco.Core.Models.PublishedContent;
-
-namespace Umbraco.Core.PropertyEditors.ValueConverters
-{
- [DefaultPropertyValueConverter]
- public class DropdownListMultipleValueConverter : PropertyValueConverterBase
- {
- public override bool IsConverter(PublishedPropertyType propertyType)
- => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.DropDownListMultiple);
-
- public override Type GetPropertyValueType(PublishedPropertyType propertyType)
- => typeof (IEnumerable);
-
- public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType)
- => PropertyCacheLevel.Element;
-
- public override object ConvertIntermediateToObject(IPublishedElement owner, PublishedPropertyType propertyType, PropertyCacheLevel cacheLevel, object source, bool preview)
- {
- var sourceString = (source ?? "").ToString();
-
- if (string.IsNullOrEmpty(sourceString))
- return Enumerable.Empty();
-
- var values =
- sourceString.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(v => v.Trim());
-
- return values;
- }
- }
-}
diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListMultipleWithKeysValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListMultipleWithKeysValueConverter.cs
deleted file mode 100644
index bceebc232b..0000000000
--- a/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListMultipleWithKeysValueConverter.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Umbraco.Core.Models.PublishedContent;
-
-namespace Umbraco.Core.PropertyEditors.ValueConverters
-{
- [DefaultPropertyValueConverter]
- public class DropdownListMultipleWithKeysValueConverter : PropertyValueConverterBase
- {
- public override bool IsConverter(PublishedPropertyType propertyType)
- => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.DropdownlistMultiplePublishKeys);
-
- public override Type GetPropertyValueType(PublishedPropertyType propertyType)
- => typeof (IEnumerable);
-
- public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType)
- => PropertyCacheLevel.Element;
-
- public override object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType, object source, bool preview)
- {
- if (source == null)
- return new int[] { };
-
- var prevalueIds = source.ToString()
- .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
- .Select(p => p.Trim())
- .Select(int.Parse)
- .ToArray();
-
- return prevalueIds;
- }
- }
-}
diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListValueConverter.cs
deleted file mode 100644
index 5fe1967f32..0000000000
--- a/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListValueConverter.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System;
-using Umbraco.Core.Models.PublishedContent;
-
-namespace Umbraco.Core.PropertyEditors.ValueConverters
-{
- [DefaultPropertyValueConverter]
- public class DropdownListValueConverter : PropertyValueConverterBase
- {
- public override bool IsConverter(PublishedPropertyType propertyType)
- => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.DropDownList);
-
- public override Type GetPropertyValueType(PublishedPropertyType propertyType)
- => typeof (string);
-
- public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType)
- => PropertyCacheLevel.Element;
-
- public override object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType, object source, bool preview)
- {
- return source?.ToString() ?? string.Empty;
- }
- }
-}
diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListWithKeysValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListWithKeysValueConverter.cs
deleted file mode 100644
index 960cd4afa6..0000000000
--- a/src/Umbraco.Core/PropertyEditors/ValueConverters/DropdownListWithKeysValueConverter.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System;
-using Umbraco.Core.Models.PublishedContent;
-
-namespace Umbraco.Core.PropertyEditors.ValueConverters
-{
- [DefaultPropertyValueConverter]
- public class DropdownListWithKeysValueConverter : PropertyValueConverterBase
- {
- public override bool IsConverter(PublishedPropertyType propertyType)
- => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.DropdownlistPublishKeys);
-
- public override Type GetPropertyValueType(PublishedPropertyType propertyType)
- => typeof (int);
-
- public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType)
- => PropertyCacheLevel.Element;
-
- public override object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType, object source, bool preview)
- {
- var intAttempt = source.TryConvertTo();
- if (intAttempt.Success)
- return intAttempt.Result;
-
- return null;
- }
- }
-}
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index 6951a9e17a..4d4bbb32e2 100644
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -356,6 +356,8 @@
+
+
@@ -1239,10 +1241,6 @@
-
-
-
-
diff --git a/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs b/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs
index 9ba5ccf6f2..129116bf61 100644
--- a/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs
+++ b/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs
@@ -21,28 +21,15 @@ namespace Umbraco.Tests.PropertyEditors
/// Tests for the base classes of ValueEditors and PreValueEditors that are used for Property Editors that edit
/// multiple values such as the drop down list, check box list, color picker, etc....
///
+ ///
+ /// Mostly this used to test the we'd store INT Ids in the Db but publish STRING values or sometimes the INT values
+ /// to cache. Now we always just deal with strings and we'll keep the tests that show that.
+ ///
[TestFixture]
public class MultiValuePropertyEditorTests
{
- //TODO: Test the other formatting methods for the drop down classes
-
[Test]
- public void DropDownMultipleValueEditor_With_Keys_Format_Data_For_Cache()
- {
- var dataTypeServiceMock = new Mock();
- var editor = new PublishValuesMultipleValueEditor(true, Mock.Of(), new DataEditorAttribute("key", "nam", "view"));
-
- var dataType = new DataType(new CheckBoxListPropertyEditor(Mock.Of(), Mock.Of()));
- var prop = new Property(1, new PropertyType(dataType));
- prop.SetValue("1234,4567,8910");
-
- var result = editor.ConvertDbToString(prop.PropertyType, prop.GetValue(), new Mock().Object);
-
- Assert.AreEqual("1234,4567,8910", result);
- }
-
- [Test]
- public void DropDownMultipleValueEditor_No_Keys_Format_Data_For_Cache()
+ public void DropDownMultipleValueEditor_Format_Data_For_Cache()
{
var dataType = new DataType(new CheckBoxListPropertyEditor(Mock.Of(), Mock.Of()))
{
@@ -61,7 +48,7 @@ namespace Umbraco.Tests.PropertyEditors
var dataTypeService = new TestObjects.TestDataTypeService(dataType);
var prop = new Property(1, new PropertyType(dataType));
- prop.SetValue("1234,4567,8910");
+ prop.SetValue("Value 1,Value 2,Value 3");
var valueEditor = dataType.Editor.GetValueEditor();
((DataValueEditor) valueEditor).Configuration = dataType.Configuration;
@@ -90,7 +77,7 @@ namespace Umbraco.Tests.PropertyEditors
var dataTypeService = new TestObjects.TestDataTypeService(dataType);
var prop = new Property(1, new PropertyType(dataType));
- prop.SetValue("1234");
+ prop.SetValue("Value 2");
var result = dataType.Editor.GetValueEditor().ConvertDbToString(prop.PropertyType, prop.GetValue(), dataTypeService);
diff --git a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueConverterTests.cs b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueConverterTests.cs
index 2c3a2d1583..7ec23158f6 100644
--- a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueConverterTests.cs
+++ b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueConverterTests.cs
@@ -1,8 +1,14 @@
using System;
using System.Collections.Generic;
+using System.Linq;
+using Moq;
using NUnit.Framework;
+using Umbraco.Core.Models;
+using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.PropertyEditors.ValueConverters;
+using Umbraco.Web.PropertyEditors;
+using Umbraco.Web.PropertyEditors.ValueConverters;
namespace Umbraco.Tests.PropertyEditors
{
@@ -79,27 +85,26 @@ namespace Umbraco.Tests.PropertyEditors
[TestCase(null, new string[] { })]
public void CanConvertDropdownListMultiplePropertyEditor(object value, IEnumerable expected)
{
- var converter = new DropdownListMultipleValueConverter();
- var inter = converter.ConvertSourceToIntermediate(null, null, value, false);
- var result = converter.ConvertIntermediateToObject(null, null, PropertyCacheLevel.Unknown, inter, false);
+ var mockPublishedContentTypeFactory = new Mock();
+ mockPublishedContentTypeFactory.Setup(x => x.GetDataType(123))
+ .Returns(new PublishedDataType(123, "test", new Lazy