From 68c4ce200847fb4d63fafa2da51991776546a62a Mon Sep 17 00:00:00 2001 From: Mole Date: Tue, 16 Mar 2021 14:18:17 +0100 Subject: [PATCH 1/7] Wrap calls to map in scopes --- src/Umbraco.Core/Mapping/UmbracoMapper.cs | 40 ++++++++++++++----- src/Umbraco.Tests/Mapping/MappingTests.cs | 37 +++++++++++++---- .../Testing/TestingTests/MockTests.cs | 18 ++++++++- 3 files changed, 77 insertions(+), 18 deletions(-) diff --git a/src/Umbraco.Core/Mapping/UmbracoMapper.cs b/src/Umbraco.Core/Mapping/UmbracoMapper.cs index e62825101c..fe58479335 100644 --- a/src/Umbraco.Core/Mapping/UmbracoMapper.cs +++ b/src/Umbraco.Core/Mapping/UmbracoMapper.cs @@ -4,6 +4,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using Umbraco.Core.Exceptions; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Mapping { @@ -42,12 +43,17 @@ namespace Umbraco.Core.Mapping private readonly ConcurrentDictionary>> _maps = new ConcurrentDictionary>>(); + private readonly IScopeProvider _scopeProvider; + /// /// Initializes a new instance of the class. /// /// - public UmbracoMapper(MapDefinitionCollection profiles) + /// + public UmbracoMapper(MapDefinitionCollection profiles, IScopeProvider scopeProvider) { + _scopeProvider = scopeProvider; + foreach (var profile in profiles) profile.DefineMaps(this); } @@ -203,7 +209,10 @@ namespace Umbraco.Core.Mapping if (ctor != null && map != null) { var target = ctor(source, context); - map(source, target, context); + using (var scope = _scopeProvider.CreateScope()) + { + map(source, target, context); + } return (TTarget)target; } @@ -248,11 +257,14 @@ namespace Umbraco.Core.Mapping { var targetList = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(targetGenericArg)); - foreach (var sourceItem in source) + using (var scope = _scopeProvider.CreateScope()) { - var targetItem = ctor(sourceItem, context); - map(sourceItem, targetItem, context); - targetList.Add(targetItem); + foreach (var sourceItem in source) + { + var targetItem = ctor(sourceItem, context); + map(sourceItem, targetItem, context); + targetList.Add(targetItem); + } } object target = targetList; @@ -292,8 +304,15 @@ namespace Umbraco.Core.Mapping public TTarget Map(TSource source, TTarget target, Action f) { var context = new MapperContext(this); - f(context); - return Map(source, target, context); + + TTarget targetInstance; + using (var scope = _scopeProvider.CreateScope()) + { + f(context); + targetInstance = Map(source, target, context); + } + + return targetInstance; } /// @@ -315,7 +334,10 @@ namespace Umbraco.Core.Mapping // if there is a direct map, map if (map != null) { - map(source, target, context); + using (var scope = _scopeProvider.CreateScope()) + { + map(source, target, context); + } return target; } diff --git a/src/Umbraco.Tests/Mapping/MappingTests.cs b/src/Umbraco.Tests/Mapping/MappingTests.cs index e6a382692c..35f64cac62 100644 --- a/src/Umbraco.Tests/Mapping/MappingTests.cs +++ b/src/Umbraco.Tests/Mapping/MappingTests.cs @@ -1,17 +1,40 @@ using System; using System.Collections.Generic; +using System.Data; using System.Linq; using System.Threading; +using Moq; using NUnit.Framework; +using Umbraco.Core.Events; using Umbraco.Core.Mapping; using Umbraco.Core.Models; +using Umbraco.Core.Scoping; using Umbraco.Web.Models.ContentEditing; +using PropertyCollection = Umbraco.Core.Models.PropertyCollection; namespace Umbraco.Tests.Mapping { [TestFixture] public class MappingTests { + private IScopeProvider _scopeProvider; + + [SetUp] + public void MockScopeProvider() + { + var scopeMock = new Mock(); + scopeMock.Setup(x => x.CreateScope( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Returns(Mock.Of); + + _scopeProvider = scopeMock.Object; + } + [Test] public void SimpleMap() { @@ -19,7 +42,7 @@ namespace Umbraco.Tests.Mapping { new MapperDefinition1(), }); - var mapper = new UmbracoMapper(definitions); + var mapper = new UmbracoMapper(definitions, _scopeProvider); var thing1 = new Thing1 { Value = "value" }; var thing2 = mapper.Map(thing1); @@ -44,7 +67,7 @@ namespace Umbraco.Tests.Mapping { new MapperDefinition1(), }); - var mapper = new UmbracoMapper(definitions); + var mapper = new UmbracoMapper(definitions, _scopeProvider); var thing1A = new Thing1 { Value = "valueA" }; var thing1B = new Thing1 { Value = "valueB" }; @@ -78,7 +101,7 @@ namespace Umbraco.Tests.Mapping { new MapperDefinition1(), }); - var mapper = new UmbracoMapper(definitions); + var mapper = new UmbracoMapper(definitions, _scopeProvider); var thing3 = new Thing3 { Value = "value" }; var thing2 = mapper.Map(thing3); @@ -103,7 +126,7 @@ namespace Umbraco.Tests.Mapping { new MapperDefinition2(), }); - var mapper = new UmbracoMapper(definitions); + var mapper = new UmbracoMapper(definitions, _scopeProvider); // can map a PropertyCollection var source = new PropertyCollection(); @@ -119,7 +142,7 @@ namespace Umbraco.Tests.Mapping new MapperDefinition1(), new MapperDefinition3(), }); - var mapper = new UmbracoMapper(definitions); + var mapper = new UmbracoMapper(definitions, _scopeProvider); // the mapper currently has a map from Thing1 to Thing2 // because Thing3 inherits from Thing1, it will map a Thing3 instance, @@ -179,7 +202,7 @@ namespace Umbraco.Tests.Mapping { new MapperDefinition4(), }); - var mapper = new UmbracoMapper(definitions); + var mapper = new UmbracoMapper(definitions, _scopeProvider); var thing5 = new Thing5() { @@ -203,7 +226,7 @@ namespace Umbraco.Tests.Mapping { new MapperDefinition5(), }); - var mapper = new UmbracoMapper(definitions); + var mapper = new UmbracoMapper(definitions, _scopeProvider); var thing7 = new Thing7(); diff --git a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs index f53b0bfff0..7eacccc8d5 100644 --- a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs +++ b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs @@ -1,4 +1,5 @@ using System; +using System.Data; using System.Globalization; using System.Linq; using System.Web.Security; @@ -9,11 +10,13 @@ using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Dictionary; +using Umbraco.Core.Events; using Umbraco.Core.Logging; using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence; +using Umbraco.Core.Scoping; using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Stubs; @@ -98,10 +101,21 @@ namespace Umbraco.Tests.Testing.TestingTests { var umbracoContext = TestObjects.GetUmbracoContextMock(); + var scopeProvider = new Mock(); + scopeProvider + .Setup(x => x.CreateScope( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Returns(Mock.Of); + var membershipHelper = new MembershipHelper(umbracoContext.HttpContext, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()); var umbracoHelper = new UmbracoHelper(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), membershipHelper); - var umbracoMapper = new UmbracoMapper(new MapDefinitionCollection(new[] { Mock.Of() })); - + var umbracoMapper = new UmbracoMapper(new MapDefinitionCollection(new[] { Mock.Of() }), scopeProvider.Object); + // ReSharper disable once UnusedVariable var umbracoApiController = new FakeUmbracoApiController(Mock.Of(), Mock.Of(), Mock.Of(), ServiceContext.CreatePartial(), AppCaches.NoCache, Mock.Of(), Mock.Of(), umbracoHelper, umbracoMapper); From 637e85ebbb50284e87fe91174dd8be4369a9be77 Mon Sep 17 00:00:00 2001 From: Mole Date: Tue, 16 Mar 2021 14:23:09 +0100 Subject: [PATCH 2/7] Autocomplete scopes --- src/Umbraco.Core/Mapping/UmbracoMapper.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Core/Mapping/UmbracoMapper.cs b/src/Umbraco.Core/Mapping/UmbracoMapper.cs index fe58479335..5800410e16 100644 --- a/src/Umbraco.Core/Mapping/UmbracoMapper.cs +++ b/src/Umbraco.Core/Mapping/UmbracoMapper.cs @@ -209,7 +209,7 @@ namespace Umbraco.Core.Mapping if (ctor != null && map != null) { var target = ctor(source, context); - using (var scope = _scopeProvider.CreateScope()) + using (var scope = _scopeProvider.CreateScope(autoComplete: true)) { map(source, target, context); } @@ -257,7 +257,7 @@ namespace Umbraco.Core.Mapping { var targetList = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(targetGenericArg)); - using (var scope = _scopeProvider.CreateScope()) + using (var scope = _scopeProvider.CreateScope(autoComplete: true)) { foreach (var sourceItem in source) { @@ -306,7 +306,7 @@ namespace Umbraco.Core.Mapping var context = new MapperContext(this); TTarget targetInstance; - using (var scope = _scopeProvider.CreateScope()) + using (var scope = _scopeProvider.CreateScope(autoComplete: true)) { f(context); targetInstance = Map(source, target, context); @@ -334,7 +334,7 @@ namespace Umbraco.Core.Mapping // if there is a direct map, map if (map != null) { - using (var scope = _scopeProvider.CreateScope()) + using (var scope = _scopeProvider.CreateScope(autoComplete: true)) { map(source, target, context); } From aa6d046efef825f4ab41ef778a8f21f9a4712f1e Mon Sep 17 00:00:00 2001 From: Mole Date: Wed, 17 Mar 2021 09:43:36 +0100 Subject: [PATCH 3/7] Remove scope from method that calls another method that has a scope --- src/Umbraco.Core/Mapping/UmbracoMapper.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Core/Mapping/UmbracoMapper.cs b/src/Umbraco.Core/Mapping/UmbracoMapper.cs index 5800410e16..ab96214063 100644 --- a/src/Umbraco.Core/Mapping/UmbracoMapper.cs +++ b/src/Umbraco.Core/Mapping/UmbracoMapper.cs @@ -305,14 +305,8 @@ namespace Umbraco.Core.Mapping { var context = new MapperContext(this); - TTarget targetInstance; - using (var scope = _scopeProvider.CreateScope(autoComplete: true)) - { - f(context); - targetInstance = Map(source, target, context); - } - - return targetInstance; + f(context); + return Map(source, target, context);; } /// From 3b83b7409ee2af1c21ec90507dae3d35a19a7a50 Mon Sep 17 00:00:00 2001 From: Mole Date: Wed, 17 Mar 2021 10:08:08 +0100 Subject: [PATCH 4/7] Clean --- src/Umbraco.Core/Mapping/UmbracoMapper.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Mapping/UmbracoMapper.cs b/src/Umbraco.Core/Mapping/UmbracoMapper.cs index ab96214063..bd2f916524 100644 --- a/src/Umbraco.Core/Mapping/UmbracoMapper.cs +++ b/src/Umbraco.Core/Mapping/UmbracoMapper.cs @@ -304,9 +304,8 @@ namespace Umbraco.Core.Mapping public TTarget Map(TSource source, TTarget target, Action f) { var context = new MapperContext(this); - f(context); - return Map(source, target, context);; + return Map(source, target, context); } /// From 8b6fc762b5edb6af3c62b306265d788a0ed458e1 Mon Sep 17 00:00:00 2001 From: Mole Date: Wed, 7 Apr 2021 13:54:42 +0200 Subject: [PATCH 5/7] Reintroduce old constructor to make non-breaking --- src/Umbraco.Core/Mapping/UmbracoMapper.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Umbraco.Core/Mapping/UmbracoMapper.cs b/src/Umbraco.Core/Mapping/UmbracoMapper.cs index bd2f916524..36e3f9eab9 100644 --- a/src/Umbraco.Core/Mapping/UmbracoMapper.cs +++ b/src/Umbraco.Core/Mapping/UmbracoMapper.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using Umbraco.Core.Composing; using Umbraco.Core.Exceptions; using Umbraco.Core.Scoping; @@ -58,6 +59,14 @@ namespace Umbraco.Core.Mapping profile.DefineMaps(this); } + /// + /// Initializes a new instance of the class. + /// + /// + [Obsolete("This constructor is no longer used and will be removed in future versions, use the other constructor instead")] + public UmbracoMapper(MapDefinitionCollection profiles) : this(profiles, Current.ScopeProvider) + {} + #region Define private static TTarget ThrowCtor(TSource source, MapperContext context) From 9fdbbb54fb3e56f973d684e658940f561612e5b9 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Wed, 7 Apr 2021 15:44:28 +0200 Subject: [PATCH 6/7] Update cypress test to make macros in the grid work again --- .../cypress/integration/Content/content.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Content/content.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Content/content.ts index b7f0b40fa6..0cec374c5d 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Content/content.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Content/content.ts @@ -761,7 +761,7 @@ context('Content', () => { cy.umbracoTreeItem("content", [name]).click(); // Click add cy.get(':nth-child(2) > .preview-row > .preview-col > .preview-cell').click(); // Choose 1 column layout. - cy.get('.umb-column > .templates-preview > :nth-child(2) > .ng-binding').click(); // Choose headline + cy.get('.umb-column > .templates-preview > :nth-child(2) > small').click(); // Choose headline cy.get('.umb-cell-placeholder').click(); // Click macro cy.get(':nth-child(4) > .umb-card-grid-item > :nth-child(1)').click(); From ecf67669ce9cdb4bac5fd52719e43a1fb605e4b5 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Wed, 7 Apr 2021 16:25:46 +0200 Subject: [PATCH 7/7] Attributes could be multiple items, test specifically if `Directory` is an attribute --- src/Umbraco.Web/Editors/CodeFileController.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web/Editors/CodeFileController.cs b/src/Umbraco.Web/Editors/CodeFileController.cs index 409cded781..a6d142a6ea 100644 --- a/src/Umbraco.Web/Editors/CodeFileController.cs +++ b/src/Umbraco.Web/Editors/CodeFileController.cs @@ -638,7 +638,10 @@ namespace Umbraco.Web.Editors { var path = IOHelper.MapPath(systemDirectory + "/" + virtualPath); var dirInfo = new DirectoryInfo(path); - return dirInfo.Attributes == FileAttributes.Directory; + + // If you turn off indexing in Windows this will have the attribute: + // `FileAttributes.Directory | FileAttributes.NotContentIndexed` + return (dirInfo.Attributes & FileAttributes.Directory) != 0; } // this is an internal class for passing stylesheet data from the client to the controller while editing