From bbf4c1882556f7dbf2906245e0e6bb383a00104d Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Tue, 7 Nov 2017 17:12:04 +0100 Subject: [PATCH 1/5] U4-10646 Sorting nodes in edge cases can lead to blanking out of property data --- src/Umbraco.Core/Services/ContentService.cs | 90 +++++++++++++++++++ src/Umbraco.Core/Services/IContentService.cs | 16 +++- src/Umbraco.Web/Editors/ContentController.cs | 5 +- .../umbraco/webservices/nodeSorter.asmx.cs | 6 +- 4 files changed, 107 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index 8b13492d42..e7e98ef19c 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -1845,6 +1845,96 @@ namespace Umbraco.Core.Services } } + return true; + } + + /// + /// Sorts a collection of objects by updating the SortOrder according + /// to the ordering of node Ids passed in. + /// + /// + /// Using this method will ensure that the Published-state is maintained upon sorting + /// so the cache is updated accordingly - as needed. + /// + /// + /// + /// + /// True if sorting succeeded, otherwise False + public bool Sort(int[] ids, int userId = 0, bool raiseEvents = true) + { + var shouldBePublished = new List(); + var shouldBeSaved = new List(); + + using (new WriteLock(Locker)) + { + var allContent = GetByIds(ids).ToDictionary(x => x.Id, x => x); + var items = ids.Select(x => allContent[x]); + + using (var uow = UowProvider.GetUnitOfWork()) + { + var asArray = items.ToArray(); + var saveEventArgs = new SaveEventArgs(asArray); + if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs)) + { + uow.Commit(); + return false; + } + + var repository = RepositoryFactory.CreateContentRepository(uow); + + var i = 0; + foreach (var content in asArray) + { + //If the current sort order equals that of the content + //we don't need to update it, so just increment the sort order + //and continue. + if (content.SortOrder == i) + { + i++; + continue; + } + + content.SortOrder = i; + content.WriterId = userId; + i++; + + if (content.Published) + { + //TODO: This should not be an inner operation, but if we do this, it cannot raise events and cannot be cancellable! + var published = _publishingStrategy.Publish(uow, content, userId).Success; + shouldBePublished.Add(content); + } + else + shouldBeSaved.Add(content); + + repository.AddOrUpdate(content); + //add or update a preview + repository.AddOrUpdatePreviewXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, _userService, c)); + } + + foreach (var content in shouldBePublished) + { + //Create and Save ContentXml DTO + repository.AddOrUpdateContentXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, _userService, c)); + } + + if (raiseEvents) + { + saveEventArgs.CanCancel = false; + uow.Events.Dispatch(Saved, this, saveEventArgs); + } + + if (shouldBePublished.Any()) + { + //TODO: This should not be an inner operation, but if we do this, it cannot raise events and cannot be cancellable! + _publishingStrategy.PublishingFinalized(uow, shouldBePublished, false); + } + + Audit(uow, AuditType.Sort, "Sorting content performed by user", userId, 0); + uow.Commit(); + } + } + return true; } diff --git a/src/Umbraco.Core/Services/IContentService.cs b/src/Umbraco.Core/Services/IContentService.cs index 4af87d2b58..6ccdac3a0b 100644 --- a/src/Umbraco.Core/Services/IContentService.cs +++ b/src/Umbraco.Core/Services/IContentService.cs @@ -618,7 +618,21 @@ namespace Umbraco.Core.Services /// /// /// True if sorting succeeded, otherwise False - bool Sort(IEnumerable items, int userId = 0, bool raiseEvents = true); + bool Sort(IEnumerable items, int userId = 0, bool raiseEvents = true); + + /// + /// Sorts a collection of objects by updating the SortOrder according + /// to the ordering of node Ids passed in. + /// + /// + /// Using this method will ensure that the Published-state is maintained upon sorting + /// so the cache is updated accordingly - as needed. + /// + /// + /// + /// + /// True if sorting succeeded, otherwise False + bool Sort(int[] ids, int userId = 0, bool raiseEvents = true); /// /// Gets the parent of the current content as an item. diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index da5e0c3a3b..b0e47e66b2 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -520,11 +520,8 @@ namespace Umbraco.Web.Editors { var contentService = Services.ContentService; - // content service GetByIds does order the content items based on the order of Ids passed in - var content = contentService.GetByIds(sorted.IdSortOrder); - // Save content with new sort order and update content xml in db accordingly - if (contentService.Sort(content) == false) + if (contentService.Sort(sorted.IdSortOrder) == false) { LogHelper.Warn("Content sorting failed, this was probably caused by an event being cancelled"); return Request.CreateValidationErrorResponse("Content sorting failed, this was probably caused by an event being cancelled"); diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/nodeSorter.asmx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/nodeSorter.asmx.cs index 505d715c3e..026d435936 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/nodeSorter.asmx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/nodeSorter.asmx.cs @@ -176,12 +176,8 @@ namespace umbraco.presentation.webservices var contentService = ApplicationContext.Services.ContentService; try { - var intIds = ids.Select(int.Parse).ToArray(); - var allContent = contentService.GetByIds(intIds).ToDictionary(x => x.Id, x => x); - var sortedContent = intIds.Select(x => allContent[x]); - // Save content with new sort order and update db+cache accordingly - var sorted = contentService.Sort(sortedContent); + var sorted = contentService.Sort(ids); // refresh sort order on cached xml // but no... this is not distributed - solely relying on content service & events should be enough From 579c572dd84ea49375d19a1aa4da1cdcaa64e3f2 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Tue, 7 Nov 2017 18:36:37 +0100 Subject: [PATCH 2/5] Oops, missed that I was passing a string array into the int array param --- .../umbraco/webservices/nodeSorter.asmx.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/nodeSorter.asmx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/nodeSorter.asmx.cs index 026d435936..e7603abe2e 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/nodeSorter.asmx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/nodeSorter.asmx.cs @@ -175,9 +175,16 @@ namespace umbraco.presentation.webservices { var contentService = ApplicationContext.Services.ContentService; try - { + { // Save content with new sort order and update db+cache accordingly - var sorted = contentService.Sort(ids); + var intIds = new List(); + foreach (var stringId in ids) + { + int intId; + if (int.TryParse(stringId, out intId)) + intIds.Add(intId); + } + var sorted = contentService.Sort(intIds.ToArray()); // refresh sort order on cached xml // but no... this is not distributed - solely relying on content service & events should be enough From 065e764957240fc6b27fae5cc417c6a427c90bb4 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Mon, 13 Nov 2017 15:27:15 +0100 Subject: [PATCH 3/5] Update to latest Examine --- build/NuSpecs/UmbracoCms.Core.nuspec | 2 +- src/Umbraco.Tests/Umbraco.Tests.csproj | 5 ++--- src/Umbraco.Tests/packages.config | 2 +- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 5 ++--- src/Umbraco.Web.UI/packages.config | 2 +- src/Umbraco.Web/Umbraco.Web.csproj | 5 ++--- src/Umbraco.Web/packages.config | 2 +- src/UmbracoExamine/UmbracoExamine.csproj | 5 ++--- src/UmbracoExamine/packages.config | 2 +- src/umbraco.MacroEngines/packages.config | 2 +- src/umbraco.MacroEngines/umbraco.MacroEngines.csproj | 5 ++--- 11 files changed, 16 insertions(+), 21 deletions(-) diff --git a/build/NuSpecs/UmbracoCms.Core.nuspec b/build/NuSpecs/UmbracoCms.Core.nuspec index eb090ab6d8..936519c656 100644 --- a/build/NuSpecs/UmbracoCms.Core.nuspec +++ b/build/NuSpecs/UmbracoCms.Core.nuspec @@ -34,7 +34,7 @@ - + diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 9edbf907f0..39337fdbc4 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -62,9 +62,8 @@ ..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll - - ..\packages\Examine.0.1.83\lib\net45\Examine.dll - True + + ..\packages\Examine.0.1.88\lib\net45\Examine.dll ..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll diff --git a/src/Umbraco.Tests/packages.config b/src/Umbraco.Tests/packages.config index 231329a75b..ba1e7f2348 100644 --- a/src/Umbraco.Tests/packages.config +++ b/src/Umbraco.Tests/packages.config @@ -3,7 +3,7 @@ - + diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 7c11194d12..f9e3e4debe 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -127,9 +127,8 @@ ..\packages\dotless.1.5.2\lib\dotless.Core.dll - - ..\packages\Examine.0.1.83\lib\net45\Examine.dll - True + + ..\packages\Examine.0.1.88\lib\net45\Examine.dll False diff --git a/src/Umbraco.Web.UI/packages.config b/src/Umbraco.Web.UI/packages.config index 8b22708406..171b61b765 100644 --- a/src/Umbraco.Web.UI/packages.config +++ b/src/Umbraco.Web.UI/packages.config @@ -4,7 +4,7 @@ - + diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index f0211cad64..57f66c3973 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -116,9 +116,8 @@ ..\packages\dotless.1.5.2\lib\dotless.Core.dll - - ..\packages\Examine.0.1.83\lib\net45\Examine.dll - True + + ..\packages\Examine.0.1.88\lib\net45\Examine.dll ..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll diff --git a/src/Umbraco.Web/packages.config b/src/Umbraco.Web/packages.config index daef6ee7fd..e5fc437cac 100644 --- a/src/Umbraco.Web/packages.config +++ b/src/Umbraco.Web/packages.config @@ -3,7 +3,7 @@ - + diff --git a/src/UmbracoExamine/UmbracoExamine.csproj b/src/UmbracoExamine/UmbracoExamine.csproj index eab05ff9a5..3860dbeae6 100644 --- a/src/UmbracoExamine/UmbracoExamine.csproj +++ b/src/UmbracoExamine/UmbracoExamine.csproj @@ -82,9 +82,8 @@ ..\Solution Items\TheFARM-Public.snk - - ..\packages\Examine.0.1.83\lib\net45\Examine.dll - True + + ..\packages\Examine.0.1.88\lib\net45\Examine.dll ..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll diff --git a/src/UmbracoExamine/packages.config b/src/UmbracoExamine/packages.config index 10206f1d14..40bdd28e84 100644 --- a/src/UmbracoExamine/packages.config +++ b/src/UmbracoExamine/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/src/umbraco.MacroEngines/packages.config b/src/umbraco.MacroEngines/packages.config index 7479987df2..6aadcba8d4 100644 --- a/src/umbraco.MacroEngines/packages.config +++ b/src/umbraco.MacroEngines/packages.config @@ -1,6 +1,6 @@  - + diff --git a/src/umbraco.MacroEngines/umbraco.MacroEngines.csproj b/src/umbraco.MacroEngines/umbraco.MacroEngines.csproj index 2a03aab363..d9734abfd8 100644 --- a/src/umbraco.MacroEngines/umbraco.MacroEngines.csproj +++ b/src/umbraco.MacroEngines/umbraco.MacroEngines.csproj @@ -45,9 +45,8 @@ false - - ..\packages\Examine.0.1.83\lib\net45\Examine.dll - True + + ..\packages\Examine.0.1.88\lib\net45\Examine.dll ..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll From cc7a28db65f6e792746129f32a40ce1a3a3e41d7 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Mon, 13 Nov 2017 15:33:04 +0100 Subject: [PATCH 4/5] Update to latest ImageProcessor --- build/NuSpecs/UmbracoCms.Core.nuspec | 4 ++-- build/NuSpecs/UmbracoCms.nuspec | 2 +- src/Umbraco.Core/Umbraco.Core.csproj | 4 ++-- src/Umbraco.Core/packages.config | 2 +- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 13 ++++++------- .../config/imageprocessor/processing.config | 1 + src/Umbraco.Web.UI/packages.config | 8 ++++---- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/build/NuSpecs/UmbracoCms.Core.nuspec b/build/NuSpecs/UmbracoCms.Core.nuspec index 936519c656..1509a4994e 100644 --- a/build/NuSpecs/UmbracoCms.Core.nuspec +++ b/build/NuSpecs/UmbracoCms.Core.nuspec @@ -35,8 +35,8 @@ - - + + diff --git a/build/NuSpecs/UmbracoCms.nuspec b/build/NuSpecs/UmbracoCms.nuspec index 22430a4516..bef9b44964 100644 --- a/build/NuSpecs/UmbracoCms.nuspec +++ b/build/NuSpecs/UmbracoCms.nuspec @@ -19,7 +19,7 @@ - + diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 3dc90f2d41..855e958736 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -56,8 +56,8 @@ ..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll True - - ..\packages\ImageProcessor.2.5.3\lib\net45\ImageProcessor.dll + + ..\packages\ImageProcessor.2.5.6\lib\net45\ImageProcessor.dll ..\packages\log4net.2.0.8\lib\net45-full\log4net.dll diff --git a/src/Umbraco.Core/packages.config b/src/Umbraco.Core/packages.config index 2a84e2d967..00126b9fdb 100644 --- a/src/Umbraco.Core/packages.config +++ b/src/Umbraco.Core/packages.config @@ -3,7 +3,7 @@ - + diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index f9e3e4debe..e67e0855fa 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -134,11 +134,11 @@ False ..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll - - ..\packages\ImageProcessor.2.5.3\lib\net45\ImageProcessor.dll + + ..\packages\ImageProcessor.2.5.6\lib\net45\ImageProcessor.dll - - ..\packages\ImageProcessor.Web.4.8.3\lib\net45\ImageProcessor.Web.dll + + ..\packages\ImageProcessor.Web.4.8.7\lib\net45\ImageProcessor.Web.dll ..\packages\log4net.2.0.8\lib\net45-full\log4net.dll @@ -162,9 +162,8 @@ ..\packages\Microsoft.CodeAnalysis.CSharp.1.0.0\lib\net45\Microsoft.CodeAnalysis.CSharp.dll - - ..\packages\Microsoft.IO.RecyclableMemoryStream.1.2.1\lib\net45\Microsoft.IO.RecyclableMemoryStream.dll - True + + ..\packages\Microsoft.IO.RecyclableMemoryStream.1.2.2\lib\net45\Microsoft.IO.RecyclableMemoryStream.dll ..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll diff --git a/src/Umbraco.Web.UI/config/imageprocessor/processing.config b/src/Umbraco.Web.UI/config/imageprocessor/processing.config index 2ce29a542a..208cd33062 100644 --- a/src/Umbraco.Web.UI/config/imageprocessor/processing.config +++ b/src/Umbraco.Web.UI/config/imageprocessor/processing.config @@ -14,6 +14,7 @@ + diff --git a/src/Umbraco.Web.UI/packages.config b/src/Umbraco.Web.UI/packages.config index 171b61b765..cd55abbd5c 100644 --- a/src/Umbraco.Web.UI/packages.config +++ b/src/Umbraco.Web.UI/packages.config @@ -5,9 +5,9 @@ - - - + + + @@ -22,7 +22,7 @@ - + From 350f5c88c79214f3907c9c5d7805bf11b6e443aa Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Tue, 14 Nov 2017 07:16:14 +0100 Subject: [PATCH 5/5] Bump version to 7.6.12 --- src/SolutionInfo.cs | 4 ++-- src/Umbraco.Core/Configuration/UmbracoVersion.cs | 2 +- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/SolutionInfo.cs b/src/SolutionInfo.cs index 893d164608..d190b5cb72 100644 --- a/src/SolutionInfo.cs +++ b/src/SolutionInfo.cs @@ -11,5 +11,5 @@ using System.Resources; [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("7.6.11")] -[assembly: AssemblyInformationalVersion("7.6.11")] \ No newline at end of file +[assembly: AssemblyFileVersion("7.6.12")] +[assembly: AssemblyInformationalVersion("7.6.12")] \ No newline at end of file diff --git a/src/Umbraco.Core/Configuration/UmbracoVersion.cs b/src/Umbraco.Core/Configuration/UmbracoVersion.cs index 9940495eec..7ec348f970 100644 --- a/src/Umbraco.Core/Configuration/UmbracoVersion.cs +++ b/src/Umbraco.Core/Configuration/UmbracoVersion.cs @@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration { public class UmbracoVersion { - private static readonly Version Version = new Version("7.6.11"); + private static readonly Version Version = new Version("7.6.12"); /// /// Gets the current version of Umbraco. diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index e67e0855fa..17d2e47a9f 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -2377,9 +2377,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\" True True - 7611 + 7612 / - http://localhost:7611 + http://localhost:7612 False False