From 1522260111d473792eac7ae57eb4bf697429ba55 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 10 Jun 2020 18:09:54 +1000 Subject: [PATCH] Reverts the nested content changes, fixes up the GetEmptyByKey --- .../V_8_7_0/StackedContentToBlockList.cs | 26 +++++++------- .../Published/NestedContentTests.cs | 20 +++++------ .../src/common/resources/content.resource.js | 14 ++++---- src/Umbraco.Web/Editors/ContentController.cs | 25 +++++--------- .../NestedContentManyValueConverter.cs | 10 +++--- .../NestedContentSingleValueConverter.cs | 8 ++--- .../NestedContentValueConverterBase.cs | 34 ++++++++++++++++--- 7 files changed, 76 insertions(+), 61 deletions(-) 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 index 5e1396a392..0e8533a549 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_7_0/StackedContentToBlockList.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_7_0/StackedContentToBlockList.cs @@ -73,11 +73,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_7_0 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 - { - Alias = t.Alias, - StringToRawProperties = propLk[t.NodeId].Union(joinLk[t.NodeId].SelectMany(r => propLk[r])).ToArray() - }); + 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; } @@ -249,15 +245,14 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_7_0 { 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 { Key = ctGuid }; + 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; - // TODO: retrive the key for the content type. - //obj["contentTypeAlias"] = ct.Alias; + obj["udi"] = udi; + obj["contentTypeKey"] = ct.Key; if (ct.StringToRawProperties != null && ct.StringToRawProperties.Length > 0) { @@ -291,9 +286,16 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_7_0 private class KnownContentType { - public string Alias { get; set; } - public Guid Key { get; set; } - public string[] StringToRawProperties { get; set; } + 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.Tests/Published/NestedContentTests.cs b/src/Umbraco.Tests/Published/NestedContentTests.cs index 70da652a9a..7f499d479b 100644 --- a/src/Umbraco.Tests/Published/NestedContentTests.cs +++ b/src/Umbraco.Tests/Published/NestedContentTests.cs @@ -100,8 +100,8 @@ namespace Umbraco.Tests.Published .Returns((string alias) => { return alias == "contentN1" - ? (IList) new List() - : (IList) new List(); + ? (IList)new List() + : (IList)new List(); }); var contentCache = new Mock(); @@ -119,12 +119,10 @@ namespace Umbraco.Tests.Published .Setup(x => x.PublishedSnapshot) .Returns(publishedSnapshot.Object); - var blockEditorConverter = new BlockEditorConverter(publishedSnapshotAccessor.Object, publishedModelFactory.Object); - var converters = new PropertyValueConverterCollection(new IPropertyValueConverter[] { - new NestedContentSingleValueConverter(blockEditorConverter, publishedModelFactory.Object, proflog), - new NestedContentManyValueConverter(blockEditorConverter, publishedModelFactory.Object, proflog), + new NestedContentSingleValueConverter(publishedSnapshotAccessor.Object, publishedModelFactory.Object, proflog), + new NestedContentManyValueConverter(publishedSnapshotAccessor.Object, publishedModelFactory.Object, proflog), }); var factory = new PublishedContentTypeFactory(publishedModelFactory.Object, converters, dataTypeService); @@ -166,7 +164,7 @@ namespace Umbraco.Tests.Published (var contentType1, _) = CreateContentTypes(); // nested single converter returns the proper value clr type TestModel, and cache level - Assert.AreEqual(typeof (TestElementModel), contentType1.GetPropertyType("property1").ClrType); + Assert.AreEqual(typeof(TestElementModel), contentType1.GetPropertyType("property1").ClrType); Assert.AreEqual(PropertyCacheLevel.Element, contentType1.GetPropertyType("property1").CacheLevel); var key = Guid.NewGuid(); @@ -174,7 +172,7 @@ namespace Umbraco.Tests.Published var content = new SolidPublishedContent(contentType1) { Key = key, - Properties = new [] + Properties = new[] { new TestPublishedProperty(contentType1.GetPropertyType("property1"), $@"[ {{ ""key"": ""{keyA}"", ""propertyN1"": ""foo"", ""ncContentTypeAlias"": ""contentN1"" }} @@ -185,7 +183,7 @@ namespace Umbraco.Tests.Published // nested single converter returns proper TestModel value Assert.IsInstanceOf(value); - var valueM = (TestElementModel) value; + var valueM = (TestElementModel)value; Assert.AreEqual("foo", valueM.PropValue); Assert.AreEqual(keyA, valueM.Key); } @@ -196,7 +194,7 @@ namespace Umbraco.Tests.Published (_, var contentType2) = CreateContentTypes(); // nested many converter returns the proper value clr type IEnumerable, and cache level - Assert.AreEqual(typeof (IEnumerable), contentType2.GetPropertyType("property2").ClrType); + Assert.AreEqual(typeof(IEnumerable), contentType2.GetPropertyType("property2").ClrType); Assert.AreEqual(PropertyCacheLevel.Element, contentType2.GetPropertyType("property2").CacheLevel); var key = Guid.NewGuid(); @@ -218,7 +216,7 @@ namespace Umbraco.Tests.Published // nested many converter returns proper IEnumerable value Assert.IsInstanceOf>(value); Assert.IsInstanceOf>(value); - var valueM = ((IEnumerable) value).ToArray(); + var valueM = ((IEnumerable)value).ToArray(); Assert.AreEqual("foo", valueM[0].PropValue); Assert.AreEqual(keyA, valueM[0].Key); Assert.AreEqual("bar", valueM[1].PropValue); diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js index da21a1e0a2..169da14d46 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js @@ -388,7 +388,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { umbRequestHelper.getApiUrl( "contentApiBaseUrl", "GetBlueprintById", - [{ id: id }])), + { id: id })), 'Failed to retrieve data for content id ' + id) .then(function (result) { return $q.when(umbDataFormatter.formatContentGetData(result)); @@ -401,7 +401,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { umbRequestHelper.getApiUrl( "contentApiBaseUrl", "GetNotificationOptions", - [{ contentId: id }])), + { contentId: id })), 'Failed to retrieve data for content id ' + id); }, @@ -502,7 +502,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { umbRequestHelper.getApiUrl( "contentApiBaseUrl", "GetEmpty", - [{ contentTypeAlias: alias }, { parentId: parentId }])), + { contentTypeAlias: alias, parentId: parentId })), 'Failed to retrieve data for empty content item type ' + alias) .then(function (result) { return $q.when(umbDataFormatter.formatContentGetData(result)); @@ -510,7 +510,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { }, /** * @ngdoc method - * @name umbraco.resources.contentResource#getScaffoldByID + * @name umbraco.resources.contentResource#getScaffoldByKey * @methodOf umbraco.resources.contentResource * * @description @@ -523,7 +523,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { * * ##usage *
-         * contentResource.getScaffoldById(1234, '...')
+         * contentResource.getScaffoldByKey(1234, '...')
          *    .then(function(scaffold) {
          *        var myDoc = scaffold;
           *        myDoc.name = "My new document";
@@ -547,7 +547,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
                     umbRequestHelper.getApiUrl(
                         "contentApiBaseUrl",
                         "GetEmptyByKey",
-                        [{ contentTypeKey: contentTypeKey }, { parentId: parentId }])),
+                        { contentTypeKey: contentTypeKey, parentId: parentId })),
                 'Failed to retrieve data for empty content item id ' + contentTypeId)
                 .then(function (result) {
                     return $q.when(umbDataFormatter.formatContentGetData(result));
@@ -561,7 +561,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
                     umbRequestHelper.getApiUrl(
                         "contentApiBaseUrl",
                         "GetEmpty",
-                        [{ blueprintId: blueprintId }, { parentId: parentId }])),
+                        { blueprintId: blueprintId, parentId: parentId })),
                 'Failed to retrieve blueprint for id ' + blueprintId)
                 .then(function (result) {
                     return $q.when(umbDataFormatter.formatContentGetData(result));
diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs
index 42e7ff9f5a..b004d49ab0 100644
--- a/src/Umbraco.Web/Editors/ContentController.cs
+++ b/src/Umbraco.Web/Editors/ContentController.cs
@@ -355,18 +355,7 @@ namespace Umbraco.Web.Editors
                 throw new HttpResponseException(HttpStatusCode.NotFound);
             }
 
-            var emptyContent = Services.ContentService.Create("", parentId, contentType.Alias, Security.GetUserId().ResultOr(0));
-            var mapped = MapToDisplay(emptyContent);
-            // translate the content type name if applicable
-            mapped.ContentTypeName = Services.TextService.UmbracoDictionaryTranslate(mapped.ContentTypeName);
-            // if your user type doesn't have access to the Settings section it would not get this property mapped
-            if (mapped.DocumentType != null)
-                mapped.DocumentType.Name = Services.TextService.UmbracoDictionaryTranslate(mapped.DocumentType.Name);
-
-            //remove the listview app if it exists
-            mapped.ContentApps = mapped.ContentApps.Where(x => x.Alias != "umbListView").ToList();
-
-            return mapped;
+            return GetEmpty(contentType, parentId);
         }
 
 
@@ -376,17 +365,19 @@ namespace Umbraco.Web.Editors
         /// 
         /// 
         [OutgoingEditorModelEvent]
-        public ContentItemDisplay GetEmptyByKey(string contentTypeKey, int parentId)
+        public ContentItemDisplay GetEmptyByKey(Guid contentTypeKey, int parentId)
         {
-
-            Guid.TryParse(contentTypeKey, out Guid contentTypeGuid);
-
-            var contentType = Services.ContentTypeService.Get(contentTypeGuid);
+            var contentType = Services.ContentTypeService.Get(contentTypeKey);
             if (contentType == null)
             {
                 throw new HttpResponseException(HttpStatusCode.NotFound);
             }
 
+            return GetEmpty(contentType, parentId);
+        }
+
+        private ContentItemDisplay GetEmpty(IContentType contentType, int parentId)
+        {
             var emptyContent = Services.ContentService.Create("", parentId, contentType.Alias, Security.GetUserId().ResultOr(0));
             var mapped = MapToDisplay(emptyContent);
             // translate the content type name if applicable
diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentManyValueConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentManyValueConverter.cs
index b961048851..11b924552e 100644
--- a/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentManyValueConverter.cs
+++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentManyValueConverter.cs
@@ -23,8 +23,8 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
         /// 
         /// Initializes a new instance of the  class.
         /// 
-        public NestedContentManyValueConverter(BlockEditorConverter blockEditorConverter, IPublishedModelFactory publishedModelFactory, IProfilingLogger proflog)
-            : base(blockEditorConverter, publishedModelFactory)
+        public NestedContentManyValueConverter(IPublishedSnapshotAccessor publishedSnapshotAccessor, IPublishedModelFactory publishedModelFactory, IProfilingLogger proflog)
+            : base(publishedSnapshotAccessor, publishedModelFactory)
         {
             _proflog = proflog;
         }
@@ -38,8 +38,8 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
         {
             var contentTypes = propertyType.DataType.ConfigurationAs().ContentTypes;
             return contentTypes.Length == 1
-                ? typeof (IEnumerable<>).MakeGenericType(ModelType.For(contentTypes[0].Alias))
-                : typeof (IEnumerable);
+                ? typeof(IEnumerable<>).MakeGenericType(ModelType.For(contentTypes[0].Alias))
+                : typeof(IEnumerable);
         }
 
         /// 
@@ -71,7 +71,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
 
                 foreach (var sourceObject in objects)
                 {
-                    var element = BlockEditorConverter.ConvertToElement(sourceObject, NestedContentPropertyEditor.ContentTypeAliasPropertyKey, referenceCacheLevel, preview);
+                    var element = ConvertToElement(sourceObject, referenceCacheLevel, preview);
                     if (element != null)
                         elements.Add(element);
                 }
diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentSingleValueConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentSingleValueConverter.cs
index b3a2a9294d..c9859c9770 100644
--- a/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentSingleValueConverter.cs
+++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentSingleValueConverter.cs
@@ -22,8 +22,8 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
         /// 
         /// Initializes a new instance of the  class.
         /// 
-        public NestedContentSingleValueConverter(BlockEditorConverter blockEditorConverter, IPublishedModelFactory publishedModelFactory, IProfilingLogger proflog)
-            : base(blockEditorConverter, publishedModelFactory)
+        public NestedContentSingleValueConverter(IPublishedSnapshotAccessor publishedSnapshotAccessor, IPublishedModelFactory publishedModelFactory, IProfilingLogger proflog)
+            : base(publishedSnapshotAccessor, publishedModelFactory)
         {
             _proflog = proflog;
         }
@@ -56,7 +56,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
         {
             using (_proflog.DebugDuration($"ConvertPropertyToNestedContent ({propertyType.DataType.Id})"))
             {
-                var value = (string) inter;
+                var value = (string)inter;
                 if (string.IsNullOrWhiteSpace(value)) return null;
 
                 var objects = JsonConvert.DeserializeObject>(value);
@@ -65,7 +65,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
                 if (objects.Count > 1)
                     throw new InvalidOperationException();
 
-                return BlockEditorConverter.ConvertToElement(objects[0], NestedContentPropertyEditor.ContentTypeAliasPropertyKey, referenceCacheLevel, preview);
+                return ConvertToElement(objects[0], referenceCacheLevel, preview);
             }
         }
     }
diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentValueConverterBase.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentValueConverterBase.cs
index 4295daf5fe..7c18d8ebca 100644
--- a/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentValueConverterBase.cs
+++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentValueConverterBase.cs
@@ -1,19 +1,23 @@
-using Umbraco.Core;
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json.Linq;
+using Umbraco.Core;
 using Umbraco.Core.Models.PublishedContent;
 using Umbraco.Core.PropertyEditors;
+using Umbraco.Web.PublishedCache;
 
 namespace Umbraco.Web.PropertyEditors.ValueConverters
 {
     public abstract class NestedContentValueConverterBase : PropertyValueConverterBase
     {
+        private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
 
-        protected NestedContentValueConverterBase(BlockEditorConverter blockEditorConverter, IPublishedModelFactory publishedModelFactory)
+        protected NestedContentValueConverterBase(IPublishedSnapshotAccessor publishedSnapshotAccessor, IPublishedModelFactory publishedModelFactory)
         {
-            BlockEditorConverter = blockEditorConverter;
+            _publishedSnapshotAccessor = publishedSnapshotAccessor;
             PublishedModelFactory = publishedModelFactory;
         }
 
-        protected BlockEditorConverter BlockEditorConverter { get; }
         protected IPublishedModelFactory PublishedModelFactory { get; }
 
         public static bool IsNested(IPublishedPropertyType publishedProperty)
@@ -35,6 +39,26 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
             return IsNested(publishedProperty) && !IsNestedSingle(publishedProperty);
         }
 
-        
+        protected IPublishedElement ConvertToElement(JObject sourceObject, PropertyCacheLevel referenceCacheLevel, bool preview)
+        {
+            var elementTypeAlias = sourceObject[NestedContentPropertyEditor.ContentTypeAliasPropertyKey]?.ToObject();
+            if (string.IsNullOrEmpty(elementTypeAlias))
+                return null;
+
+            // only convert element types - content types will cause an exception when PublishedModelFactory creates the model
+            var publishedContentType = _publishedSnapshotAccessor.PublishedSnapshot.Content.GetContentType(elementTypeAlias);
+            if (publishedContentType == null || publishedContentType.IsElement == false)
+                return null;
+
+            var propertyValues = sourceObject.ToObject>();
+
+            if (!propertyValues.TryGetValue("key", out var keyo)
+                || !Guid.TryParse(keyo.ToString(), out var key))
+                key = Guid.Empty;
+
+            IPublishedElement element = new PublishedElement(publishedContentType, key, propertyValues, preview, referenceCacheLevel, _publishedSnapshotAccessor);
+            element = PublishedModelFactory.CreateModel(element);
+            return element;
+        }
     }
 }