diff --git a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs index 9bd1972ee4..03ba58d15e 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs @@ -7,7 +7,6 @@ using Umbraco.Core.Migrations.Upgrade.V_8_0_0; using Umbraco.Core.Migrations.Upgrade.V_8_0_1; using Umbraco.Core.Migrations.Upgrade.V_8_1_0; using Umbraco.Core.Migrations.Upgrade.V_8_6_0; -using Umbraco.Core.Migrations.Upgrade.V_8_7_0; namespace Umbraco.Core.Migrations.Upgrade { @@ -194,10 +193,7 @@ namespace Umbraco.Core.Migrations.Upgrade // to 8.7.0... To("{a78e3369-8ea3-40ec-ad3f-5f76929d2b20}"); - - // to 8.7.0... - To("{DFA35FA2-BFBB-433F-84E5-BD75940CDDF6}"); - To("{DA434576-3DEF-46D7-942A-CE34D7F7FB8A}"); + //FINAL } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_7_0/ConvertToElements.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_7_0/ConvertToElements.cs deleted file mode 100644 index fbcd55ec92..0000000000 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_7_0/ConvertToElements.cs +++ /dev/null @@ -1,80 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System.Collections.Generic; -using System.Linq; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Dtos; - -namespace Umbraco.Core.Migrations.Upgrade.V_8_7_0 -{ - public class ConvertToElements : MigrationBase - { - public ConvertToElements(IMigrationContext context) : base(context) - { - } - - public override void Migrate() - { - // Get all document type IDs by alias - var docTypes = Database.Fetch(); - var docTypeMap = new Dictionary(docTypes.Count); - docTypes.ForEach(d => docTypeMap[d.Alias] = d.NodeId); - - // Find all Nested Content or Block List data types - var dataTypes = GetDataTypes(Constants.PropertyEditors.Aliases.BlockList); - - // Find all document types listed in each - var elementTypeIds = dataTypes.SelectMany(d => GetDocTypeIds(d.Configuration, docTypeMap)).ToList(); - - // Find all compositions those document types use - var parentElementTypeIds = Database.Fetch(Sql() - .Select() - .From() - .WhereIn(c => c.ChildId, elementTypeIds) - ).Select(c => c.ParentId); - - elementTypeIds = elementTypeIds.Union(parentElementTypeIds).ToList(); - - // Convert all those document types to element type - // TODO: We need to wait on an update from @benjaminc to make this 'safe' - // see https://github.com/umbraco/Umbraco-CMS/pull/7910#discussion_r409927495 - foreach (var docType in docTypes) - { - if (!elementTypeIds.Contains(docType.NodeId)) continue; - - docType.IsElement = true; - Database.Update(docType); - } - } - - private List GetDataTypes(params string[] aliases) - { - var sql = Sql() - .Select() - .From() - .WhereIn(d => d.EditorAlias, aliases); - - return Database.Fetch(sql); - } - - private IEnumerable GetDocTypeIds(string configuration, Dictionary idMap) - { - if (configuration.IsNullOrWhiteSpace() || configuration[0] != '{') return Enumerable.Empty(); - - var obj = JObject.Parse(configuration); - if (obj["blocks"] is JArray blArr) - { - var arr = blArr.ToObject(); - return arr.Select(i => idMap.TryGetValue(i.Alias, out var id) ? id : 0).Where(i => i != 0); - } - - return Enumerable.Empty(); - } - - public class BlockConfiguration - { - [JsonProperty("contentTypeAlias")] - public string Alias { get; set; } - } - } -} diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_7_0/StackedContentToBlockList.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_7_0/StackedContentToBlockList.cs deleted file mode 100644 index 0e8533a549..0000000000 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_7_0/StackedContentToBlockList.cs +++ /dev/null @@ -1,301 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Umbraco.Core.Logging; -using Umbraco.Core.Migrations.PostMigrations; -using Umbraco.Core.Models; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Dtos; -using Umbraco.Core.PropertyEditors; - -namespace Umbraco.Core.Migrations.Upgrade.V_8_7_0 -{ - public class StackedContentToBlockList : MigrationBase - { - public StackedContentToBlockList(IMigrationContext context) : base(context) - { - } - - public override void Migrate() - { - // Convert all Stacked Content properties to Block List properties, both in the data types and in the property data - var refreshCache = Migrate(GetDataTypes("Our.Umbraco.StackedContent"), GetKnownDocumentTypes()); - - // if some data types have been updated directly in the database (editing DataTypeDto and/or PropertyDataDto), - // bypassing the services, then we need to rebuild the cache entirely, including the umbracoContentNu table - if (refreshCache) - Context.AddPostMigration(); - } - - private List GetDataTypes(string alias) - { - var sql = Sql() - .Select() - .From() - .Where(d => d.EditorAlias == alias); - - return Database.Fetch(sql); - } - - private Dictionary GetKnownDocumentTypes() - { - var sql = Sql() - .Select(r => r.Select(x => x.NodeDto)) - .From() - .InnerJoin() - .On(c => c.NodeId, n => n.NodeId); - - var types = Database.Fetch(sql); - var typeMap = new Dictionary(types.Count); - types.ForEach(t => typeMap[t.NodeId] = t); - - sql = Sql() - .Select() - .From(); - var joins = Database.Fetch(sql); - // Find all relationships between types, either inherited or composited - var joinLk = joins - .Union(types - .Where(t => typeMap.ContainsKey(t.NodeDto.ParentId)) - .Select(t => new ContentType2ContentTypeDto { ChildId = t.NodeId, ParentId = t.NodeDto.ParentId })) - .ToLookup(j => j.ChildId, j => j.ParentId); - - sql = Sql() - .Select(r => r.Select(x => x.DataTypeDto)) - .From() - .InnerJoin() - .On(c => c.DataTypeId, n => n.NodeId) - .WhereIn(d => d.EditorAlias, new[] { Constants.PropertyEditors.Aliases.NestedContent, Constants.PropertyEditors.Aliases.ColorPicker }); - var props = Database.Fetch(sql); - // Get all nested content and color picker property aliases by content type ID - var propLk = props.ToLookup(p => p.ContentTypeId, p => p.Alias); - - var knownMap = new Dictionary(types.Count); - types.ForEach(t => knownMap[t.NodeDto.UniqueId] = new KnownContentType(t.Alias, t.NodeDto.UniqueId, propLk[t.NodeId].Union(joinLk[t.NodeId].SelectMany(r => propLk[r])).ToArray())); - return knownMap; - } - - private bool Migrate(IEnumerable dataTypesToMigrate, Dictionary knownDocumentTypes) - { - var refreshCache = false; - - foreach (var dataType in dataTypesToMigrate) - { - if (!dataType.Configuration.IsNullOrWhiteSpace()) - { - var config = UpdateConfiguration(dataType, knownDocumentTypes); - - if (config.Blocks.Length > 0) UpdatePropertyData(dataType, config, knownDocumentTypes); - } - - UpdateDataType(dataType); - - refreshCache = true; - } - - return refreshCache; - } - - private BlockListConfiguration UpdateConfiguration(DataTypeDto dataType, Dictionary knownDocumentTypes) - { - var old = JsonConvert.DeserializeObject(dataType.Configuration); - var config = new BlockListConfiguration - { - Blocks = old.ContentTypes?.Select(t => new BlockListConfiguration.BlockConfiguration - { - Key = knownDocumentTypes.TryGetValue(t.IcContentTypeGuid, out var ct) ? ct.Key : Guid.Empty, - Label = t.NameTemplate - }).Where(c => c.Key != null).ToArray(), - UseInlineEditingAsDefault = old.SingleItemMode == "1" || old.SingleItemMode == bool.TrueString - }; - - if (int.TryParse(old.MaxItems, out var max) && max > 0) - { - config.ValidationLimit = new BlockListConfiguration.NumberRange { Max = max }; - } - - dataType.Configuration = ConfigurationEditor.ToDatabase(config); - - return config; - } - - private void UpdatePropertyData(DataTypeDto dataType, BlockListConfiguration config, Dictionary knownDocumentTypes) - { - // get property data dtos - var propertyDataDtos = Database.Fetch(Sql() - .Select() - .From() - .InnerJoin().On((pt, pd) => pt.Id == pd.PropertyTypeId) - .InnerJoin().On((dt, pt) => dt.NodeId == pt.DataTypeId) - .Where(x => x.DataTypeId == dataType.NodeId)); - - // update dtos - var updatedDtos = propertyDataDtos.Where(x => UpdatePropertyDataDto(x, config, knownDocumentTypes)); - - // persist changes - foreach (var propertyDataDto in updatedDtos) - Database.Update(propertyDataDto); - } - - - private bool UpdatePropertyDataDto(PropertyDataDto dto, BlockListConfiguration config, Dictionary knownDocumentTypes) - { - var model = new SimpleModel(); - - if (dto != null && !dto.TextValue.IsNullOrWhiteSpace() && dto.TextValue[0] == '[') - { - var scObjs = JsonConvert.DeserializeObject(dto.TextValue); - foreach (var obj in scObjs) model.AddDataItem(obj, knownDocumentTypes); - } - - dto.TextValue = JsonConvert.SerializeObject(model); - - return true; - } - - private void UpdateDataType(DataTypeDto dataType) - { - dataType.DbType = ValueStorageType.Ntext.ToString(); - dataType.EditorAlias = Constants.PropertyEditors.Aliases.BlockList; - - Database.Update(dataType); - } - - private class BlockListConfiguration - { - - [JsonProperty("blocks")] - public BlockConfiguration[] Blocks { get; set; } - - - [JsonProperty("validationLimit")] - public NumberRange ValidationLimit { get; set; } = new NumberRange(); - - public class NumberRange - { - [JsonProperty("min")] - public int? Min { get; set; } - - [JsonProperty("max")] - public int? Max { get; set; } - } - - public class BlockConfiguration - { - [JsonProperty("backgroundColor")] - public string BackgroundColor { get; set; } - - [JsonProperty("iconColor")] - public string IconColor { get; set; } - - [JsonProperty("thumbnail")] - public string Thumbnail { get; set; } - - [JsonProperty("contentTypeKey")] - public Guid Key { get; set; } - - [JsonProperty("settingsElementTypeKey")] - public string settingsElementTypeKey { get; set; } - - [JsonProperty("view")] - public string View { get; set; } - - [JsonProperty("label")] - public string Label { get; set; } - - [JsonProperty("editorSize")] - public string EditorSize { get; set; } - } - - [JsonProperty("useInlineEditingAsDefault")] - public bool UseInlineEditingAsDefault { get; set; } - - [JsonProperty("maxPropertyWidth")] - public string MaxPropertyWidth { get; set; } - } - - private class StackedContentConfiguration - { - - public class StackedContentType - { - public Guid IcContentTypeGuid { get; set; } - public string NameTemplate { get; set; } - } - - public StackedContentType[] ContentTypes { get; set; } - public string EnableCopy { get; set; } - public string EnableFilter { get; set; } - public string EnablePreview { get; set; } - public string HideLabel { get; set; } - public string MaxItems { get; set; } - public string SingleItemMode { get; set; } - } - - private class SimpleModel - { - [JsonProperty("layout")] - public SimpleLayout Layout { get; } = new SimpleLayout(); - [JsonProperty("data")] - public List Data { get; } = new List(); - - public void AddDataItem(JObject obj, Dictionary knownDocumentTypes) - { - if (!Guid.TryParse(obj["key"].ToString(), out var key)) key = Guid.NewGuid(); - if (!Guid.TryParse(obj["icContentTypeGuid"].ToString(), out var ctGuid)) ctGuid = Guid.Empty; - if (!knownDocumentTypes.TryGetValue(ctGuid, out var ct)) ct = new KnownContentType(null, ctGuid, null); - - obj.Remove("key"); - obj.Remove("icContentTypeGuid"); - - var udi = new GuidUdi(Constants.UdiEntityType.Element, key).ToString(); - obj["udi"] = udi; - obj["contentTypeKey"] = ct.Key; - - if (ct.StringToRawProperties != null && ct.StringToRawProperties.Length > 0) - { - // Nested content inside a stacked content item used to be stored as a deserialized string of the JSON array - // Now we store the content as the raw JSON array, so we need to convert from the string form to the array - foreach (var prop in ct.StringToRawProperties) - { - var val = obj[prop]; - var value = val?.ToString(); - if (val != null && val.Type == JTokenType.String && !value.IsNullOrWhiteSpace()) - obj[prop] = JsonConvert.DeserializeObject(value); - } - } - - Data.Add(obj); - Layout.Refs.Add(new SimpleLayout.SimpleLayoutRef { Udi = udi }); - } - - public class SimpleLayout - { - [JsonProperty(Constants.PropertyEditors.Aliases.BlockList)] - public List Refs { get; } = new List(); - - public class SimpleLayoutRef - { - [JsonProperty("udi")] - public string Udi { get; set; } - } - } - } - - private class KnownContentType - { - public KnownContentType(string alias, Guid key, string[] stringToRawProperties) - { - Alias = alias ?? throw new ArgumentNullException(nameof(alias)); - Key = key; - StringToRawProperties = stringToRawProperties ?? throw new ArgumentNullException(nameof(stringToRawProperties)); - } - - public string Alias { get; } - public Guid Key { get; } - public string[] StringToRawProperties { get; } - } - } -} diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index eb3b487dcd..a5c1141d8b 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -132,8 +132,6 @@ - -