From 7c20adef0ea622f22b0e5e88e8b211199e153436 Mon Sep 17 00:00:00 2001 From: Steve <6131869+SteveVaneeckhout@users.noreply.github.com> Date: Mon, 23 Nov 2020 10:40:18 +0100 Subject: [PATCH 01/27] Track ng-repeat with id instead of label (#9340) (cherry picked from commit 39c4dcdaaa4d18acc4fd0134e69c48af17dbb535) --- .../src/views/components/content/umb-tabbed-content.html | 2 +- .../elementeditor/umb-element-editor-content.component.html | 2 +- .../src/views/components/member/umb-member-node-info.html | 2 +- .../src/views/media/apps/content/content.html | 2 +- .../src/views/member/apps/content/content.html | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html index d534cd77ed..022c140a2f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html @@ -1,6 +1,6 @@ 
-
+
{{ group.label }}
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/elementeditor/umb-element-editor-content.component.html b/src/Umbraco.Web.UI.Client/src/views/components/elementeditor/umb-element-editor-content.component.html index fae639562f..ecbe880eee 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/elementeditor/umb-element-editor-content.component.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/elementeditor/umb-element-editor-content.component.html @@ -2,7 +2,7 @@
+ ng-repeat="group in vm.model.variants[0].tabs track by group.id">
{{ group.label }}
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/member/umb-member-node-info.html b/src/Umbraco.Web.UI.Client/src/views/components/member/umb-member-node-info.html index 62b2052771..bf8eeffa6f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/member/umb-member-node-info.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/member/umb-member-node-info.html @@ -1,7 +1,7 @@
- +
{{ group.label }}
diff --git a/src/Umbraco.Web.UI.Client/src/views/media/apps/content/content.html b/src/Umbraco.Web.UI.Client/src/views/media/apps/content/content.html index 633eccdf62..816ca987f7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/media/apps/content/content.html +++ b/src/Umbraco.Web.UI.Client/src/views/media/apps/content/content.html @@ -1,5 +1,5 @@
-
+
{{ group.label }}
diff --git a/src/Umbraco.Web.UI.Client/src/views/member/apps/content/content.html b/src/Umbraco.Web.UI.Client/src/views/member/apps/content/content.html index 29df5ba638..7ac2bbd390 100644 --- a/src/Umbraco.Web.UI.Client/src/views/member/apps/content/content.html +++ b/src/Umbraco.Web.UI.Client/src/views/member/apps/content/content.html @@ -1,6 +1,6 @@
-
+
{{ group.label }}
From 21e3cf0887474cba7eec32288f8415adfd823f69 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Fri, 4 Dec 2020 13:01:58 +0100 Subject: [PATCH 02/27] Moved files and introduced IMarkdownToHtmlConverter to avoid packages to handle markdown in core Signed-off-by: Bjarke Berg --- .../HealthCheckSettingsExtensions.cs | 4 +-- .../Diagnostics/IMarchal.cs | 4 +++ .../Diagnostics/MiniDump.cs | 6 ++-- .../Dictionary/UmbracoCultureDictionary.cs | 2 +- .../UmbracoCultureDictionaryFactory.cs | 2 +- .../Editors/UserEditorAuthorizationHelper.cs | 0 ...HealthCheckNotificationMethodCollection.cs | 0 ...heckNotificationMethodCollectionBuilder.cs | 0 .../HealthCheck/HealthCheckResults.cs | 25 ------------- .../EmailNotificationMethod.cs | 7 ++-- .../IHealthCheckNotificationMethod.cs | 0 .../IMarkdownToHtmlConverter.cs | 10 ++++++ .../NotificationMethodBase.cs | 0 .../HealthCheck/MarkdownToHtmlConverter.cs | 35 +++++++++++++++++++ .../HostedServices/HealthCheckNotifier.cs | 2 +- .../Packaging/PackageDataInstallation.cs | 2 -- .../Runtime/CoreInitialComposer.cs | 4 +-- .../HealthCheckSettingsExtensionsTests.cs | 2 +- 18 files changed, 63 insertions(+), 42 deletions(-) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Configuration/Extensions/HealthCheckSettingsExtensions.cs (90%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Diagnostics/IMarchal.cs (58%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Diagnostics/MiniDump.cs (98%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Dictionary/UmbracoCultureDictionary.cs (98%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Dictionary/UmbracoCultureDictionaryFactory.cs (92%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Editors/UserEditorAuthorizationHelper.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/HealthCheck/HealthCheckNotificationMethodCollection.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/HealthCheck/HealthCheckResults.cs (85%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/HealthCheck/NotificationMethods/EmailNotificationMethod.cs (90%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/HealthCheck/NotificationMethods/IHealthCheckNotificationMethod.cs (100%) create mode 100644 src/Umbraco.Core/HealthCheck/NotificationMethods/IMarkdownToHtmlConverter.cs rename src/{Umbraco.Infrastructure => Umbraco.Core}/HealthCheck/NotificationMethods/NotificationMethodBase.cs (100%) create mode 100644 src/Umbraco.Infrastructure/HealthCheck/MarkdownToHtmlConverter.cs diff --git a/src/Umbraco.Infrastructure/Configuration/Extensions/HealthCheckSettingsExtensions.cs b/src/Umbraco.Core/Configuration/Extensions/HealthCheckSettingsExtensions.cs similarity index 90% rename from src/Umbraco.Infrastructure/Configuration/Extensions/HealthCheckSettingsExtensions.cs rename to src/Umbraco.Core/Configuration/Extensions/HealthCheckSettingsExtensions.cs index 92c3608ac1..ae842cb040 100644 --- a/src/Umbraco.Infrastructure/Configuration/Extensions/HealthCheckSettingsExtensions.cs +++ b/src/Umbraco.Core/Configuration/Extensions/HealthCheckSettingsExtensions.cs @@ -1,9 +1,7 @@ using System; -using NCrontab; -using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; -namespace Umbraco.Infrastructure.Configuration.Extensions +namespace Umbraco.Core.Configuration.Extensions { public static class HealthCheckSettingsExtensions { diff --git a/src/Umbraco.Infrastructure/Diagnostics/IMarchal.cs b/src/Umbraco.Core/Diagnostics/IMarchal.cs similarity index 58% rename from src/Umbraco.Infrastructure/Diagnostics/IMarchal.cs rename to src/Umbraco.Core/Diagnostics/IMarchal.cs index 30e6a9e619..cde4592b1b 100644 --- a/src/Umbraco.Infrastructure/Diagnostics/IMarchal.cs +++ b/src/Umbraco.Core/Diagnostics/IMarchal.cs @@ -7,6 +7,10 @@ namespace Umbraco.Core.Diagnostics /// public interface IMarchal { + /// + /// Retrieves a computer-independent description of an exception, and information about the state that existed for the thread when the exception occurred. + /// + /// A pointer to an EXCEPTION_POINTERS structure. IntPtr GetExceptionPointers(); } } diff --git a/src/Umbraco.Infrastructure/Diagnostics/MiniDump.cs b/src/Umbraco.Core/Diagnostics/MiniDump.cs similarity index 98% rename from src/Umbraco.Infrastructure/Diagnostics/MiniDump.cs rename to src/Umbraco.Core/Diagnostics/MiniDump.cs index 57e9b5204b..56635c6b46 100644 --- a/src/Umbraco.Infrastructure/Diagnostics/MiniDump.cs +++ b/src/Umbraco.Core/Diagnostics/MiniDump.cs @@ -2,9 +2,7 @@ using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; -using Umbraco.Core.Composing; using Umbraco.Core.Hosting; -using Umbraco.Core.IO; namespace Umbraco.Core.Diagnostics { @@ -12,7 +10,7 @@ namespace Umbraco.Core.Diagnostics // and https://blogs.msdn.microsoft.com/dondu/2010/10/31/writing-minidumps-from-exceptions-in-c/ // which itself got it from http://blog.kalmbach-software.de/2008/12/13/writing-minidumps-in-c/ - internal static class MiniDump + public static class MiniDump { private static readonly object LockO = new object(); @@ -92,7 +90,9 @@ namespace Umbraco.Core.Diagnostics exp.ExceptionPointers = IntPtr.Zero; if (withException) + { exp.ExceptionPointers = marchal.GetExceptionPointers(); + } var bRet = exp.ExceptionPointers == IntPtr.Zero ? MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint) options, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero) diff --git a/src/Umbraco.Infrastructure/Dictionary/UmbracoCultureDictionary.cs b/src/Umbraco.Core/Dictionary/UmbracoCultureDictionary.cs similarity index 98% rename from src/Umbraco.Infrastructure/Dictionary/UmbracoCultureDictionary.cs rename to src/Umbraco.Core/Dictionary/UmbracoCultureDictionary.cs index b0690c944b..1f23ec645c 100644 --- a/src/Umbraco.Infrastructure/Dictionary/UmbracoCultureDictionary.cs +++ b/src/Umbraco.Core/Dictionary/UmbracoCultureDictionary.cs @@ -17,7 +17,7 @@ namespace Umbraco.Core.Dictionary /// The ILocalizationService is the service used for interacting with this data from the database which isn't all that fast /// (even though there is caching involved, if there's lots of dictionary items the caching is not great) /// - public class DefaultCultureDictionary : ICultureDictionary + internal class DefaultCultureDictionary : ICultureDictionary { private readonly ILocalizationService _localizationService; private readonly IAppCache _requestCache; diff --git a/src/Umbraco.Infrastructure/Dictionary/UmbracoCultureDictionaryFactory.cs b/src/Umbraco.Core/Dictionary/UmbracoCultureDictionaryFactory.cs similarity index 92% rename from src/Umbraco.Infrastructure/Dictionary/UmbracoCultureDictionaryFactory.cs rename to src/Umbraco.Core/Dictionary/UmbracoCultureDictionaryFactory.cs index a2d1fa12d3..e2e30f3d76 100644 --- a/src/Umbraco.Infrastructure/Dictionary/UmbracoCultureDictionaryFactory.cs +++ b/src/Umbraco.Core/Dictionary/UmbracoCultureDictionaryFactory.cs @@ -9,7 +9,7 @@ namespace Umbraco.Core.Dictionary /// /// In the future this will allow use to potentially store dictionary items elsewhere and allows for maximum flexibility. /// - internal class DefaultCultureDictionaryFactory : ICultureDictionaryFactory + public class DefaultCultureDictionaryFactory : ICultureDictionaryFactory { private readonly ILocalizationService _localizationService; private readonly AppCaches _appCaches; diff --git a/src/Umbraco.Infrastructure/Editors/UserEditorAuthorizationHelper.cs b/src/Umbraco.Core/Editors/UserEditorAuthorizationHelper.cs similarity index 100% rename from src/Umbraco.Infrastructure/Editors/UserEditorAuthorizationHelper.cs rename to src/Umbraco.Core/Editors/UserEditorAuthorizationHelper.cs diff --git a/src/Umbraco.Infrastructure/HealthCheck/HealthCheckNotificationMethodCollection.cs b/src/Umbraco.Core/HealthCheck/HealthCheckNotificationMethodCollection.cs similarity index 100% rename from src/Umbraco.Infrastructure/HealthCheck/HealthCheckNotificationMethodCollection.cs rename to src/Umbraco.Core/HealthCheck/HealthCheckNotificationMethodCollection.cs diff --git a/src/Umbraco.Infrastructure/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs b/src/Umbraco.Core/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs similarity index 100% rename from src/Umbraco.Infrastructure/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs rename to src/Umbraco.Core/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs diff --git a/src/Umbraco.Infrastructure/HealthCheck/HealthCheckResults.cs b/src/Umbraco.Core/HealthCheck/HealthCheckResults.cs similarity index 85% rename from src/Umbraco.Infrastructure/HealthCheck/HealthCheckResults.cs rename to src/Umbraco.Core/HealthCheck/HealthCheckResults.cs index 37159b4a49..44955bfaae 100644 --- a/src/Umbraco.Infrastructure/HealthCheck/HealthCheckResults.cs +++ b/src/Umbraco.Core/HealthCheck/HealthCheckResults.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using HeyRed.MarkdownSharp; using Microsoft.Extensions.Logging; using Umbraco.Core; using Umbraco.Core.HealthCheck; @@ -120,33 +119,9 @@ namespace Umbraco.Infrastructure.HealthCheck return sb.ToString(); } - public string ResultsAsHtml(HealthCheckNotificationVerbosity verbosity) - { - var mark = new Markdown(); - var html = mark.Transform(ResultsAsMarkDown(verbosity)); - html = ApplyHtmlHighlighting(html); - return html; - } internal Dictionary> ResultsAsDictionary => _results; - private string ApplyHtmlHighlighting(string html) - { - const string SuccessHexColor = "5cb85c"; - const string WarningHexColor = "f0ad4e"; - const string ErrorHexColor = "d9534f"; - - html = ApplyHtmlHighlightingForStatus(html, StatusResultType.Success, SuccessHexColor); - html = ApplyHtmlHighlightingForStatus(html, StatusResultType.Warning, WarningHexColor); - return ApplyHtmlHighlightingForStatus(html, StatusResultType.Error, ErrorHexColor); - } - - private string ApplyHtmlHighlightingForStatus(string html, StatusResultType status, string color) - { - return html - .Replace("Result: '" + status + "'", "Result: " + status + ""); - } - private string SimpleHtmlToMarkDown(string html) { return html.Replace("", "**") diff --git a/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs b/src/Umbraco.Core/HealthCheck/NotificationMethods/EmailNotificationMethod.cs similarity index 90% rename from src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs rename to src/Umbraco.Core/HealthCheck/NotificationMethods/EmailNotificationMethod.cs index 4d7444447f..d29f3ccb0b 100644 --- a/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs +++ b/src/Umbraco.Core/HealthCheck/NotificationMethods/EmailNotificationMethod.cs @@ -17,6 +17,7 @@ namespace Umbraco.Web.HealthCheck.NotificationMethods private readonly ILocalizedTextService _textService; private readonly IRequestAccessor _requestAccessor; private readonly IEmailSender _emailSender; + private readonly IMarkdownToHtmlConverter _markdownToHtmlConverter; private readonly ContentSettings _contentSettings; @@ -25,7 +26,8 @@ namespace Umbraco.Web.HealthCheck.NotificationMethods IRequestAccessor requestAccessor, IEmailSender emailSender, IOptions healthChecksSettings, - IOptions contentSettings) + IOptions contentSettings, + IMarkdownToHtmlConverter markdownToHtmlConverter) : base(healthChecksSettings) { var recipientEmail = Settings?["RecipientEmail"]; @@ -40,6 +42,7 @@ namespace Umbraco.Web.HealthCheck.NotificationMethods _textService = textService ?? throw new ArgumentNullException(nameof(textService)); _requestAccessor = requestAccessor; _emailSender = emailSender; + _markdownToHtmlConverter = markdownToHtmlConverter; _contentSettings = contentSettings.Value ?? throw new ArgumentNullException(nameof(contentSettings)); } @@ -61,7 +64,7 @@ namespace Umbraco.Web.HealthCheck.NotificationMethods { DateTime.Now.ToShortDateString(), DateTime.Now.ToShortTimeString(), - results.ResultsAsHtml(Verbosity) + _markdownToHtmlConverter.ToHtml(results, Verbosity) }); // Include the umbraco Application URL host in the message subject so that diff --git a/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/IHealthCheckNotificationMethod.cs b/src/Umbraco.Core/HealthCheck/NotificationMethods/IHealthCheckNotificationMethod.cs similarity index 100% rename from src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/IHealthCheckNotificationMethod.cs rename to src/Umbraco.Core/HealthCheck/NotificationMethods/IHealthCheckNotificationMethod.cs diff --git a/src/Umbraco.Core/HealthCheck/NotificationMethods/IMarkdownToHtmlConverter.cs b/src/Umbraco.Core/HealthCheck/NotificationMethods/IMarkdownToHtmlConverter.cs new file mode 100644 index 0000000000..20d8f0f07e --- /dev/null +++ b/src/Umbraco.Core/HealthCheck/NotificationMethods/IMarkdownToHtmlConverter.cs @@ -0,0 +1,10 @@ +using Umbraco.Core.HealthCheck; +using Umbraco.Infrastructure.HealthCheck; + +namespace Umbraco.Web.HealthCheck.NotificationMethods +{ + public interface IMarkdownToHtmlConverter + { + string ToHtml(HealthCheckResults results, HealthCheckNotificationVerbosity verbosity); + } +} diff --git a/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/NotificationMethodBase.cs b/src/Umbraco.Core/HealthCheck/NotificationMethods/NotificationMethodBase.cs similarity index 100% rename from src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/NotificationMethodBase.cs rename to src/Umbraco.Core/HealthCheck/NotificationMethods/NotificationMethodBase.cs diff --git a/src/Umbraco.Infrastructure/HealthCheck/MarkdownToHtmlConverter.cs b/src/Umbraco.Infrastructure/HealthCheck/MarkdownToHtmlConverter.cs new file mode 100644 index 0000000000..39c5fe0bf2 --- /dev/null +++ b/src/Umbraco.Infrastructure/HealthCheck/MarkdownToHtmlConverter.cs @@ -0,0 +1,35 @@ +using HeyRed.MarkdownSharp; +using Umbraco.Core.HealthCheck; +using Umbraco.Infrastructure.HealthCheck; +using Umbraco.Web.HealthCheck.NotificationMethods; + +namespace Umbraco.Web.HealthCheck +{ + public class MarkdownToHtmlConverter : IMarkdownToHtmlConverter + { + public string ToHtml(HealthCheckResults results, HealthCheckNotificationVerbosity verbosity) + { + var mark = new Markdown(); + var html = mark.Transform(results.ResultsAsMarkDown(verbosity)); + html = ApplyHtmlHighlighting(html); + return html; + } + + private string ApplyHtmlHighlighting(string html) + { + const string SuccessHexColor = "5cb85c"; + const string WarningHexColor = "f0ad4e"; + const string ErrorHexColor = "d9534f"; + + html = ApplyHtmlHighlightingForStatus(html, StatusResultType.Success, SuccessHexColor); + html = ApplyHtmlHighlightingForStatus(html, StatusResultType.Warning, WarningHexColor); + return ApplyHtmlHighlightingForStatus(html, StatusResultType.Error, ErrorHexColor); + } + + private string ApplyHtmlHighlightingForStatus(string html, StatusResultType status, string color) + { + return html + .Replace("Result: '" + status + "'", "Result: " + status + ""); + } + } +} diff --git a/src/Umbraco.Infrastructure/HostedServices/HealthCheckNotifier.cs b/src/Umbraco.Infrastructure/HostedServices/HealthCheckNotifier.cs index 58decb80c4..1e775abaa9 100644 --- a/src/Umbraco.Infrastructure/HostedServices/HealthCheckNotifier.cs +++ b/src/Umbraco.Infrastructure/HostedServices/HealthCheckNotifier.cs @@ -5,12 +5,12 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Extensions; using Umbraco.Core.Configuration.Models; using Umbraco.Core.HealthCheck; using Umbraco.Core.Logging; using Umbraco.Core.Scoping; using Umbraco.Core.Sync; -using Umbraco.Infrastructure.Configuration.Extensions; using Umbraco.Infrastructure.HealthCheck; using Umbraco.Web.HealthCheck; diff --git a/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs b/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs index 84e65732c2..5f5ee63642 100644 --- a/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs +++ b/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs @@ -8,7 +8,6 @@ using System.Xml.XPath; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Umbraco.Core.Collections; -using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; @@ -17,7 +16,6 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; using Umbraco.Core.Serialization; using Umbraco.Core.Services; -using Umbraco.Core.Services.Implement; using Umbraco.Core.Strings; namespace Umbraco.Core.Packaging diff --git a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs index 910a9a25e2..2a988a70a4 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs @@ -60,9 +60,6 @@ using IntegerValidator = Umbraco.Core.PropertyEditors.Validators.IntegerValidato using TextStringValueConverter = Umbraco.Core.PropertyEditors.ValueConverters.TextStringValueConverter; using Microsoft.Extensions.Logging; using Umbraco.Core.DependencyInjection; -using Umbraco.Core.Configuration.HealthChecks; -using Umbraco.Core.HealthCheck; -using Umbraco.Core.HealthCheck.Checks; using Umbraco.Core.Security; namespace Umbraco.Core.Runtime @@ -303,6 +300,7 @@ namespace Umbraco.Core.Runtime builder.Services.AddUnique(); // register *all* checks, except those marked [HideFromTypeFinder] of course + builder.Services.AddUnique(); builder.HealthChecks() .Add(() => builder.TypeLoader.GetTypes()); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Configuration/Models/Extensions/HealthCheckSettingsExtensionsTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Configuration/Models/Extensions/HealthCheckSettingsExtensionsTests.cs index 833e5c865b..0eca0b7d02 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Configuration/Models/Extensions/HealthCheckSettingsExtensionsTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Configuration/Models/Extensions/HealthCheckSettingsExtensionsTests.cs @@ -1,8 +1,8 @@ using System; using NUnit.Framework; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Extensions; using Umbraco.Core.Configuration.Models; -using Umbraco.Infrastructure.Configuration.Extensions; namespace Umbraco.Tests.UnitTests.Umbraco.Core.Configuration.Models.Extensions { From eb03145fa6fcee9babb6633219975c33de7d2c02 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Fri, 4 Dec 2020 15:04:29 +0100 Subject: [PATCH 03/27] Moved media files and introduced IImageDimensionExtractor and to avoid System.drawing in core --- .../InstallSteps/StarterKitInstallStep.cs | 3 +-- .../Install/Models/InstallInstructions.cs | 0 .../Media/EmbedProviders/DailyMotion.cs | 7 ++++- .../Media/EmbedProviders/EmbedProviderBase.cs | 13 +++++++--- .../EmbedProvidersCollection.cs | 0 .../EmbedProvidersCollectionBuilder.cs | 0 .../Media/EmbedProviders/Flickr.cs | 5 ++++ .../Media/EmbedProviders/GettyImages.cs | 5 ++++ .../Media/EmbedProviders/Giphy.cs | 11 ++++---- .../Media/EmbedProviders/Hulu.cs | 7 ++++- .../Media/EmbedProviders/Issuu.cs | 7 ++++- .../Media/EmbedProviders/Kickstarter.cs | 5 ++++ .../Media/EmbedProviders/OEmbedResponse.cs | 17 ++++++------ .../Media/EmbedProviders/Slideshare.cs | 5 ++++ .../Media/EmbedProviders/SoundCloud.cs | 7 ++++- .../Media/EmbedProviders/Ted.cs | 7 ++++- .../Media/EmbedProviders/Twitter.cs | 5 ++++ .../Media/EmbedProviders/Vimeo.cs | 7 ++++- .../Media/EmbedProviders/Youtube.cs | 7 ++++- .../Media/Exif/BitConverterEx.cs | 0 .../Media/Exif/ExifBitConverter.cs | 0 .../Media/Exif/ExifEnums.cs | 0 .../Media/Exif/ExifExceptions.cs | 0 .../Media/Exif/ExifExtendedProperty.cs | 0 .../Media/Exif/ExifFileTypeDescriptor.cs | 0 .../Media/Exif/ExifInterOperability.cs | 0 .../Media/Exif/ExifProperty.cs | 0 .../Media/Exif/ExifPropertyCollection.cs | 0 .../Media/Exif/ExifPropertyFactory.cs | 0 .../Media/Exif/ExifTag.cs | 0 .../Media/Exif/ExifTagFactory.cs | 0 .../Media/Exif/IFD.cs | 0 .../Media/Exif/ImageFile.cs | 6 ----- .../Media/Exif/ImageFileDirectory.cs | 0 .../Media/Exif/ImageFileDirectoryEntry.cs | 0 .../Media/Exif/ImageFileFormat.cs | 0 .../Media/Exif/JFIFEnums.cs | 0 .../Media/Exif/JFIFExtendedProperty.cs | 0 .../Media/Exif/JFIFThumbnail.cs | 0 .../Media/Exif/JPEGExceptions.cs | 0 .../Media/Exif/JPEGFile.cs | 10 ------- .../Media/Exif/JPEGMarker.cs | 0 .../Media/Exif/JPEGSection.cs | 0 .../Media/Exif/MathEx.cs | 0 .../Media/Exif/SvgFile.cs | 8 +----- .../Media/Exif/TIFFFile.cs | 11 -------- .../Media/Exif/TIFFHeader.cs | 0 .../Media/Exif/TIFFStrip.cs | 0 .../Media/Exif/Utility.cs | 0 .../Media/ExifImageDimensionExtractor.cs | 26 +++++++++++++++++++ .../Media/TypeDetector/JpegDetector.cs | 0 .../TypeDetector/RasterizedTypeDetector.cs | 0 .../Media/TypeDetector/SvgDetector.cs | 0 .../Media/TypeDetector/TIFFDetector.cs | 0 .../Services}/IInstallationService.cs | 0 .../Install/InstallSteps/NewInstallStep.cs | 3 +-- .../Media/IImageDimensionExtractor.cs | 9 +++++++ ...geHelper.cs => ImageDimensionExtractor.cs} | 24 +++++------------ src/Umbraco.Infrastructure/Media/ImageSize.cs | 15 +++++++++++ .../Media/UploadAutoFillProperties.cs | 12 +++++---- .../Runtime/CoreInitialComposer.cs | 8 +++--- 61 files changed, 163 insertions(+), 87 deletions(-) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Install/InstallSteps/StarterKitInstallStep.cs (98%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Install/Models/InstallInstructions.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/EmbedProviders/DailyMotion.cs (86%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/EmbedProviders/EmbedProviderBase.cs (88%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/EmbedProviders/EmbedProvidersCollection.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/EmbedProviders/EmbedProvidersCollectionBuilder.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/EmbedProviders/Flickr.cs (90%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/EmbedProviders/GettyImages.cs (86%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/EmbedProviders/Giphy.cs (83%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/EmbedProviders/Hulu.cs (85%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/EmbedProviders/Issuu.cs (86%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/EmbedProviders/Kickstarter.cs (84%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/EmbedProviders/OEmbedResponse.cs (78%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/EmbedProviders/Slideshare.cs (85%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/EmbedProviders/SoundCloud.cs (84%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/EmbedProviders/Ted.cs (85%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/EmbedProviders/Twitter.cs (85%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/EmbedProviders/Vimeo.cs (85%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/EmbedProviders/Youtube.cs (86%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/BitConverterEx.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/ExifBitConverter.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/ExifEnums.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/ExifExceptions.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/ExifExtendedProperty.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/ExifFileTypeDescriptor.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/ExifInterOperability.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/ExifProperty.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/ExifPropertyCollection.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/ExifPropertyFactory.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/ExifTag.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/ExifTagFactory.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/IFD.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/ImageFile.cs (94%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/ImageFileDirectory.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/ImageFileDirectoryEntry.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/ImageFileFormat.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/JFIFEnums.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/JFIFExtendedProperty.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/JFIFThumbnail.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/JPEGExceptions.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/JPEGFile.cs (99%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/JPEGMarker.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/JPEGSection.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/MathEx.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/SvgFile.cs (86%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/TIFFFile.cs (93%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/TIFFHeader.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/TIFFStrip.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/Exif/Utility.cs (100%) create mode 100644 src/Umbraco.Core/Media/ExifImageDimensionExtractor.cs rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/TypeDetector/JpegDetector.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/TypeDetector/RasterizedTypeDetector.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/TypeDetector/SvgDetector.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Media/TypeDetector/TIFFDetector.cs (100%) rename src/{Umbraco.Infrastructure/Services/Implement => Umbraco.Core/Services}/IInstallationService.cs (100%) create mode 100644 src/Umbraco.Infrastructure/Media/IImageDimensionExtractor.cs rename src/Umbraco.Infrastructure/Media/{ImageHelper.cs => ImageDimensionExtractor.cs} (58%) create mode 100644 src/Umbraco.Infrastructure/Media/ImageSize.cs diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/StarterKitInstallStep.cs b/src/Umbraco.Core/Install/InstallSteps/StarterKitInstallStep.cs similarity index 98% rename from src/Umbraco.Infrastructure/Install/InstallSteps/StarterKitInstallStep.cs rename to src/Umbraco.Core/Install/InstallSteps/StarterKitInstallStep.cs index 4cd25c16bb..e3cd56c5c1 100644 --- a/src/Umbraco.Infrastructure/Install/InstallSteps/StarterKitInstallStep.cs +++ b/src/Umbraco.Core/Install/InstallSteps/StarterKitInstallStep.cs @@ -3,10 +3,9 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using Umbraco.Core.Security; -using Umbraco.Net; using Umbraco.Core.Services; +using Umbraco.Net; using Umbraco.Web.Install.Models; -using Umbraco.Web.Security; namespace Umbraco.Web.Install.InstallSteps { diff --git a/src/Umbraco.Infrastructure/Install/Models/InstallInstructions.cs b/src/Umbraco.Core/Install/Models/InstallInstructions.cs similarity index 100% rename from src/Umbraco.Infrastructure/Install/Models/InstallInstructions.cs rename to src/Umbraco.Core/Install/Models/InstallInstructions.cs diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/DailyMotion.cs b/src/Umbraco.Core/Media/EmbedProviders/DailyMotion.cs similarity index 86% rename from src/Umbraco.Infrastructure/Media/EmbedProviders/DailyMotion.cs rename to src/Umbraco.Core/Media/EmbedProviders/DailyMotion.cs index 78ea0b8662..f56a29c2d5 100644 --- a/src/Umbraco.Infrastructure/Media/EmbedProviders/DailyMotion.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/DailyMotion.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Umbraco.Core.Serialization; namespace Umbraco.Web.Media.EmbedProviders { @@ -10,7 +11,7 @@ namespace Umbraco.Web.Media.EmbedProviders { @"dailymotion.com/video/.*" }; - + public override Dictionary RequestParams => new Dictionary() { //ApiUrl/?format=xml @@ -24,5 +25,9 @@ namespace Umbraco.Web.Media.EmbedProviders return GetXmlProperty(xmlDocument, "/oembed/html"); } + + public DailyMotion(IJsonSerializer jsonSerializer) : base(jsonSerializer) + { + } } } diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/EmbedProviderBase.cs b/src/Umbraco.Core/Media/EmbedProviders/EmbedProviderBase.cs similarity index 88% rename from src/Umbraco.Infrastructure/Media/EmbedProviders/EmbedProviderBase.cs rename to src/Umbraco.Core/Media/EmbedProviders/EmbedProviderBase.cs index 539c01f69b..cc7f5d2349 100644 --- a/src/Umbraco.Infrastructure/Media/EmbedProviders/EmbedProviderBase.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/EmbedProviderBase.cs @@ -1,16 +1,23 @@ -using Newtonsoft.Json; -using System; +using System; using System.Collections.Generic; using System.Net; using System.Net.Http; using System.Text; using System.Xml; using Umbraco.Core.Media; +using Umbraco.Core.Serialization; namespace Umbraco.Web.Media.EmbedProviders { public abstract class EmbedProviderBase : IEmbedProvider { + private readonly IJsonSerializer _jsonSerializer; + + protected EmbedProviderBase(IJsonSerializer jsonSerializer) + { + _jsonSerializer = jsonSerializer; + } + private static HttpClient _httpClient; public abstract string ApiEndpoint { get; } @@ -58,7 +65,7 @@ namespace Umbraco.Web.Media.EmbedProviders public virtual T GetJsonResponse(string url) where T : class { var response = DownloadResponse(url); - return JsonConvert.DeserializeObject(response); + return _jsonSerializer.Deserialize(response); } public virtual XmlDocument GetXmlResponse(string url) diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/EmbedProvidersCollection.cs b/src/Umbraco.Core/Media/EmbedProviders/EmbedProvidersCollection.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/EmbedProviders/EmbedProvidersCollection.cs rename to src/Umbraco.Core/Media/EmbedProviders/EmbedProvidersCollection.cs diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/EmbedProvidersCollectionBuilder.cs b/src/Umbraco.Core/Media/EmbedProviders/EmbedProvidersCollectionBuilder.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/EmbedProviders/EmbedProvidersCollectionBuilder.cs rename to src/Umbraco.Core/Media/EmbedProviders/EmbedProvidersCollectionBuilder.cs diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/Flickr.cs b/src/Umbraco.Core/Media/EmbedProviders/Flickr.cs similarity index 90% rename from src/Umbraco.Infrastructure/Media/EmbedProviders/Flickr.cs rename to src/Umbraco.Core/Media/EmbedProviders/Flickr.cs index d067060014..a6ead2df3a 100644 --- a/src/Umbraco.Infrastructure/Media/EmbedProviders/Flickr.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/Flickr.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Net; +using Umbraco.Core.Serialization; namespace Umbraco.Web.Media.EmbedProviders { @@ -27,5 +28,9 @@ namespace Umbraco.Web.Media.EmbedProviders return string.Format("\"{3}\"", imageUrl, imageWidth, imageHeight, WebUtility.HtmlEncode(imageTitle)); } + + public Flickr(IJsonSerializer jsonSerializer) : base(jsonSerializer) + { + } } } diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/GettyImages.cs b/src/Umbraco.Core/Media/EmbedProviders/GettyImages.cs similarity index 86% rename from src/Umbraco.Infrastructure/Media/EmbedProviders/GettyImages.cs rename to src/Umbraco.Core/Media/EmbedProviders/GettyImages.cs index 34b383614d..0db0a97b8e 100644 --- a/src/Umbraco.Infrastructure/Media/EmbedProviders/GettyImages.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/GettyImages.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Umbraco.Core.Serialization; namespace Umbraco.Web.Media.EmbedProviders { @@ -23,5 +24,9 @@ namespace Umbraco.Web.Media.EmbedProviders return oembed.GetHtml(); } + + public GettyImages(IJsonSerializer jsonSerializer) : base(jsonSerializer) + { + } } } diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/Giphy.cs b/src/Umbraco.Core/Media/EmbedProviders/Giphy.cs similarity index 83% rename from src/Umbraco.Infrastructure/Media/EmbedProviders/Giphy.cs rename to src/Umbraco.Core/Media/EmbedProviders/Giphy.cs index 1069de749c..319afda5b6 100644 --- a/src/Umbraco.Infrastructure/Media/EmbedProviders/Giphy.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/Giphy.cs @@ -1,8 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Collections.Generic; +using Umbraco.Core.Serialization; namespace Umbraco.Web.Media.EmbedProviders { @@ -28,5 +25,9 @@ namespace Umbraco.Web.Media.EmbedProviders return oembed.GetHtml(); } + + public Giphy(IJsonSerializer jsonSerializer) : base(jsonSerializer) + { + } } } diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/Hulu.cs b/src/Umbraco.Core/Media/EmbedProviders/Hulu.cs similarity index 85% rename from src/Umbraco.Infrastructure/Media/EmbedProviders/Hulu.cs rename to src/Umbraco.Core/Media/EmbedProviders/Hulu.cs index 150439832a..4deea8c23d 100644 --- a/src/Umbraco.Infrastructure/Media/EmbedProviders/Hulu.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/Hulu.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Umbraco.Core.Serialization; namespace Umbraco.Web.Media.EmbedProviders { @@ -10,7 +11,7 @@ namespace Umbraco.Web.Media.EmbedProviders { @"hulu.com/watch/.*" }; - + public override Dictionary RequestParams => new Dictionary(); public override string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0) @@ -20,5 +21,9 @@ namespace Umbraco.Web.Media.EmbedProviders return oembed.GetHtml(); } + + public Hulu(IJsonSerializer jsonSerializer) : base(jsonSerializer) + { + } } } diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/Issuu.cs b/src/Umbraco.Core/Media/EmbedProviders/Issuu.cs similarity index 86% rename from src/Umbraco.Infrastructure/Media/EmbedProviders/Issuu.cs rename to src/Umbraco.Core/Media/EmbedProviders/Issuu.cs index 2b33473453..3baaf7ea35 100644 --- a/src/Umbraco.Infrastructure/Media/EmbedProviders/Issuu.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/Issuu.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Umbraco.Core.Serialization; namespace Umbraco.Web.Media.EmbedProviders { @@ -10,7 +11,7 @@ namespace Umbraco.Web.Media.EmbedProviders { @"issuu.com/.*/docs/.*" }; - + public override Dictionary RequestParams => new Dictionary() { //ApiUrl/?format=xml @@ -24,5 +25,9 @@ namespace Umbraco.Web.Media.EmbedProviders return GetXmlProperty(xmlDocument, "/oembed/html"); } + + public Issuu(IJsonSerializer jsonSerializer) : base(jsonSerializer) + { + } } } diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/Kickstarter.cs b/src/Umbraco.Core/Media/EmbedProviders/Kickstarter.cs similarity index 84% rename from src/Umbraco.Infrastructure/Media/EmbedProviders/Kickstarter.cs rename to src/Umbraco.Core/Media/EmbedProviders/Kickstarter.cs index 4de45ae2e3..ef75b6ebe8 100644 --- a/src/Umbraco.Infrastructure/Media/EmbedProviders/Kickstarter.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/Kickstarter.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Umbraco.Core.Serialization; namespace Umbraco.Web.Media.EmbedProviders { @@ -20,5 +21,9 @@ namespace Umbraco.Web.Media.EmbedProviders return oembed.GetHtml(); } + + public Kickstarter(IJsonSerializer jsonSerializer) : base(jsonSerializer) + { + } } } diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/OEmbedResponse.cs b/src/Umbraco.Core/Media/EmbedProviders/OEmbedResponse.cs similarity index 78% rename from src/Umbraco.Infrastructure/Media/EmbedProviders/OEmbedResponse.cs rename to src/Umbraco.Core/Media/EmbedProviders/OEmbedResponse.cs index cc3e34931e..8178a97742 100644 --- a/src/Umbraco.Infrastructure/Media/EmbedProviders/OEmbedResponse.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/OEmbedResponse.cs @@ -1,11 +1,12 @@ using System.Net; -using Newtonsoft.Json; +using System.Runtime.Serialization; namespace Umbraco.Web.Media.EmbedProviders { /// /// Wrapper class for OEmbed response /// + [DataContract] public class OEmbedResponse { public string Type { get; set; } @@ -14,25 +15,25 @@ namespace Umbraco.Web.Media.EmbedProviders public string Title { get; set; } - [JsonProperty("author_name")] + [DataMember(Name ="author_name")] public string AuthorName { get; set; } - [JsonProperty("author_url")] + [DataMember(Name ="author_url")] public string AuthorUrl { get; set; } - [JsonProperty("provider_name")] + [DataMember(Name ="provider_name")] public string ProviderName { get; set; } - [JsonProperty("provider_url")] + [DataMember(Name ="provider_url")] public string ProviderUrl { get; set; } - [JsonProperty("thumbnail_url")] + [DataMember(Name ="thumbnail_url")] public string ThumbnailUrl { get; set; } - [JsonProperty("thumbnail_height")] + [DataMember(Name ="thumbnail_height")] public double? ThumbnailHeight { get; set; } - [JsonProperty("thumbnail_width")] + [DataMember(Name ="thumbnail_width")] public double? ThumbnailWidth { get; set; } public string Html { get; set; } diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/Slideshare.cs b/src/Umbraco.Core/Media/EmbedProviders/Slideshare.cs similarity index 85% rename from src/Umbraco.Infrastructure/Media/EmbedProviders/Slideshare.cs rename to src/Umbraco.Core/Media/EmbedProviders/Slideshare.cs index 6d3a010c7a..7fa149d145 100644 --- a/src/Umbraco.Infrastructure/Media/EmbedProviders/Slideshare.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/Slideshare.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Umbraco.Core.Serialization; namespace Umbraco.Web.Media.EmbedProviders { @@ -20,5 +21,9 @@ namespace Umbraco.Web.Media.EmbedProviders return GetXmlProperty(xmlDocument, "/oembed/html"); } + + public Slideshare(IJsonSerializer jsonSerializer) : base(jsonSerializer) + { + } } } diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/SoundCloud.cs b/src/Umbraco.Core/Media/EmbedProviders/SoundCloud.cs similarity index 84% rename from src/Umbraco.Infrastructure/Media/EmbedProviders/SoundCloud.cs rename to src/Umbraco.Core/Media/EmbedProviders/SoundCloud.cs index 080437a246..43cc92b0b4 100644 --- a/src/Umbraco.Infrastructure/Media/EmbedProviders/SoundCloud.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/SoundCloud.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Umbraco.Core.Serialization; namespace Umbraco.Web.Media.EmbedProviders { @@ -10,7 +11,7 @@ namespace Umbraco.Web.Media.EmbedProviders { @"soundcloud.com\/*" }; - + public override Dictionary RequestParams => new Dictionary(); public override string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0) @@ -20,5 +21,9 @@ namespace Umbraco.Web.Media.EmbedProviders return GetXmlProperty(xmlDocument, "/oembed/html"); } + + public Soundcloud(IJsonSerializer jsonSerializer) : base(jsonSerializer) + { + } } } diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/Ted.cs b/src/Umbraco.Core/Media/EmbedProviders/Ted.cs similarity index 85% rename from src/Umbraco.Infrastructure/Media/EmbedProviders/Ted.cs rename to src/Umbraco.Core/Media/EmbedProviders/Ted.cs index aa14423349..cd4b78d065 100644 --- a/src/Umbraco.Infrastructure/Media/EmbedProviders/Ted.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/Ted.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Umbraco.Core.Serialization; namespace Umbraco.Web.Media.EmbedProviders { @@ -10,7 +11,7 @@ namespace Umbraco.Web.Media.EmbedProviders { @"ted.com\/talks\/*" }; - + public override Dictionary RequestParams => new Dictionary(); public override string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0) @@ -20,5 +21,9 @@ namespace Umbraco.Web.Media.EmbedProviders return GetXmlProperty(xmlDocument, "/oembed/html"); } + + public Ted(IJsonSerializer jsonSerializer) : base(jsonSerializer) + { + } } } diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/Twitter.cs b/src/Umbraco.Core/Media/EmbedProviders/Twitter.cs similarity index 85% rename from src/Umbraco.Infrastructure/Media/EmbedProviders/Twitter.cs rename to src/Umbraco.Core/Media/EmbedProviders/Twitter.cs index 9286934a4d..2bb4203411 100644 --- a/src/Umbraco.Infrastructure/Media/EmbedProviders/Twitter.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/Twitter.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Umbraco.Core.Serialization; namespace Umbraco.Web.Media.EmbedProviders { @@ -20,5 +21,9 @@ namespace Umbraco.Web.Media.EmbedProviders return oembed.GetHtml(); } + + public Twitter(IJsonSerializer jsonSerializer) : base(jsonSerializer) + { + } } } diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/Vimeo.cs b/src/Umbraco.Core/Media/EmbedProviders/Vimeo.cs similarity index 85% rename from src/Umbraco.Infrastructure/Media/EmbedProviders/Vimeo.cs rename to src/Umbraco.Core/Media/EmbedProviders/Vimeo.cs index 806f40a10c..709ba61b3b 100644 --- a/src/Umbraco.Infrastructure/Media/EmbedProviders/Vimeo.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/Vimeo.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Umbraco.Core.Serialization; namespace Umbraco.Web.Media.EmbedProviders { @@ -10,7 +11,7 @@ namespace Umbraco.Web.Media.EmbedProviders { @"vimeo\.com/" }; - + public override Dictionary RequestParams => new Dictionary(); public override string GetMarkup(string url, int maxWidth = 0, int maxHeight = 0) @@ -20,5 +21,9 @@ namespace Umbraco.Web.Media.EmbedProviders return GetXmlProperty(xmlDocument, "/oembed/html"); } + + public Vimeo(IJsonSerializer jsonSerializer) : base(jsonSerializer) + { + } } } diff --git a/src/Umbraco.Infrastructure/Media/EmbedProviders/Youtube.cs b/src/Umbraco.Core/Media/EmbedProviders/Youtube.cs similarity index 86% rename from src/Umbraco.Infrastructure/Media/EmbedProviders/Youtube.cs rename to src/Umbraco.Core/Media/EmbedProviders/Youtube.cs index 4e6f437047..30b83caa88 100644 --- a/src/Umbraco.Infrastructure/Media/EmbedProviders/Youtube.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/Youtube.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Umbraco.Core.Serialization; namespace Umbraco.Web.Media.EmbedProviders { @@ -11,7 +12,7 @@ namespace Umbraco.Web.Media.EmbedProviders @"youtu.be/.*", @"youtube.com/watch.*" }; - + public override Dictionary RequestParams => new Dictionary() { //ApiUrl/?format=json @@ -25,5 +26,9 @@ namespace Umbraco.Web.Media.EmbedProviders return oembed.GetHtml(); } + + public YouTube(IJsonSerializer jsonSerializer) : base(jsonSerializer) + { + } } } diff --git a/src/Umbraco.Infrastructure/Media/Exif/BitConverterEx.cs b/src/Umbraco.Core/Media/Exif/BitConverterEx.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/BitConverterEx.cs rename to src/Umbraco.Core/Media/Exif/BitConverterEx.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifBitConverter.cs b/src/Umbraco.Core/Media/Exif/ExifBitConverter.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/ExifBitConverter.cs rename to src/Umbraco.Core/Media/Exif/ExifBitConverter.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifEnums.cs b/src/Umbraco.Core/Media/Exif/ExifEnums.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/ExifEnums.cs rename to src/Umbraco.Core/Media/Exif/ExifEnums.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifExceptions.cs b/src/Umbraco.Core/Media/Exif/ExifExceptions.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/ExifExceptions.cs rename to src/Umbraco.Core/Media/Exif/ExifExceptions.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifExtendedProperty.cs b/src/Umbraco.Core/Media/Exif/ExifExtendedProperty.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/ExifExtendedProperty.cs rename to src/Umbraco.Core/Media/Exif/ExifExtendedProperty.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifFileTypeDescriptor.cs b/src/Umbraco.Core/Media/Exif/ExifFileTypeDescriptor.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/ExifFileTypeDescriptor.cs rename to src/Umbraco.Core/Media/Exif/ExifFileTypeDescriptor.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifInterOperability.cs b/src/Umbraco.Core/Media/Exif/ExifInterOperability.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/ExifInterOperability.cs rename to src/Umbraco.Core/Media/Exif/ExifInterOperability.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifProperty.cs b/src/Umbraco.Core/Media/Exif/ExifProperty.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/ExifProperty.cs rename to src/Umbraco.Core/Media/Exif/ExifProperty.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifPropertyCollection.cs b/src/Umbraco.Core/Media/Exif/ExifPropertyCollection.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/ExifPropertyCollection.cs rename to src/Umbraco.Core/Media/Exif/ExifPropertyCollection.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifPropertyFactory.cs b/src/Umbraco.Core/Media/Exif/ExifPropertyFactory.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/ExifPropertyFactory.cs rename to src/Umbraco.Core/Media/Exif/ExifPropertyFactory.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifTag.cs b/src/Umbraco.Core/Media/Exif/ExifTag.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/ExifTag.cs rename to src/Umbraco.Core/Media/Exif/ExifTag.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/ExifTagFactory.cs b/src/Umbraco.Core/Media/Exif/ExifTagFactory.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/ExifTagFactory.cs rename to src/Umbraco.Core/Media/Exif/ExifTagFactory.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/IFD.cs b/src/Umbraco.Core/Media/Exif/IFD.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/IFD.cs rename to src/Umbraco.Core/Media/Exif/IFD.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/ImageFile.cs b/src/Umbraco.Core/Media/Exif/ImageFile.cs similarity index 94% rename from src/Umbraco.Infrastructure/Media/Exif/ImageFile.cs rename to src/Umbraco.Core/Media/Exif/ImageFile.cs index acd8ce8eec..f59f9dc73f 100644 --- a/src/Umbraco.Infrastructure/Media/Exif/ImageFile.cs +++ b/src/Umbraco.Core/Media/Exif/ImageFile.cs @@ -1,5 +1,4 @@ using System.ComponentModel; -using System.Drawing; using System.IO; using System.Text; using Umbraco.Web.Media.TypeDetector; @@ -52,11 +51,6 @@ namespace Umbraco.Web.Media.Exif #endregion #region Instance Methods - /// - /// Converts the to a . - /// - /// Returns a containing image data. - public abstract Image ToImage (); /// /// Saves the to the specified file. diff --git a/src/Umbraco.Infrastructure/Media/Exif/ImageFileDirectory.cs b/src/Umbraco.Core/Media/Exif/ImageFileDirectory.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/ImageFileDirectory.cs rename to src/Umbraco.Core/Media/Exif/ImageFileDirectory.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/ImageFileDirectoryEntry.cs b/src/Umbraco.Core/Media/Exif/ImageFileDirectoryEntry.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/ImageFileDirectoryEntry.cs rename to src/Umbraco.Core/Media/Exif/ImageFileDirectoryEntry.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/ImageFileFormat.cs b/src/Umbraco.Core/Media/Exif/ImageFileFormat.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/ImageFileFormat.cs rename to src/Umbraco.Core/Media/Exif/ImageFileFormat.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/JFIFEnums.cs b/src/Umbraco.Core/Media/Exif/JFIFEnums.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/JFIFEnums.cs rename to src/Umbraco.Core/Media/Exif/JFIFEnums.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/JFIFExtendedProperty.cs b/src/Umbraco.Core/Media/Exif/JFIFExtendedProperty.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/JFIFExtendedProperty.cs rename to src/Umbraco.Core/Media/Exif/JFIFExtendedProperty.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/JFIFThumbnail.cs b/src/Umbraco.Core/Media/Exif/JFIFThumbnail.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/JFIFThumbnail.cs rename to src/Umbraco.Core/Media/Exif/JFIFThumbnail.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/JPEGExceptions.cs b/src/Umbraco.Core/Media/Exif/JPEGExceptions.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/JPEGExceptions.cs rename to src/Umbraco.Core/Media/Exif/JPEGExceptions.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/JPEGFile.cs b/src/Umbraco.Core/Media/Exif/JPEGFile.cs similarity index 99% rename from src/Umbraco.Infrastructure/Media/Exif/JPEGFile.cs rename to src/Umbraco.Core/Media/Exif/JPEGFile.cs index 35c3788abd..83e6a81eec 100644 --- a/src/Umbraco.Infrastructure/Media/Exif/JPEGFile.cs +++ b/src/Umbraco.Core/Media/Exif/JPEGFile.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Drawing; using System.IO; using System.Text; @@ -260,15 +259,6 @@ namespace Umbraco.Web.Media.Exif Save(stream, true); } - /// - /// Returns a System.Drawing.Image created with image data. - /// - public override Image ToImage() - { - MemoryStream stream = new MemoryStream(); - Save(stream); - return Image.FromStream(stream); - } #endregion #region Private Helper Methods diff --git a/src/Umbraco.Infrastructure/Media/Exif/JPEGMarker.cs b/src/Umbraco.Core/Media/Exif/JPEGMarker.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/JPEGMarker.cs rename to src/Umbraco.Core/Media/Exif/JPEGMarker.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/JPEGSection.cs b/src/Umbraco.Core/Media/Exif/JPEGSection.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/JPEGSection.cs rename to src/Umbraco.Core/Media/Exif/JPEGSection.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/MathEx.cs b/src/Umbraco.Core/Media/Exif/MathEx.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/MathEx.cs rename to src/Umbraco.Core/Media/Exif/MathEx.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/SvgFile.cs b/src/Umbraco.Core/Media/Exif/SvgFile.cs similarity index 86% rename from src/Umbraco.Infrastructure/Media/Exif/SvgFile.cs rename to src/Umbraco.Core/Media/Exif/SvgFile.cs index 8916ac0801..1213bb513f 100644 --- a/src/Umbraco.Infrastructure/Media/Exif/SvgFile.cs +++ b/src/Umbraco.Core/Media/Exif/SvgFile.cs @@ -1,6 +1,4 @@ -using System; -using System.Drawing; -using System.IO; +using System.IO; using System.Linq; using System.Xml.Linq; @@ -29,9 +27,5 @@ namespace Umbraco.Web.Media.Exif { } - public override Image ToImage() - { - throw new NotImplementedException(); - } } } diff --git a/src/Umbraco.Infrastructure/Media/Exif/TIFFFile.cs b/src/Umbraco.Core/Media/Exif/TIFFFile.cs similarity index 93% rename from src/Umbraco.Infrastructure/Media/Exif/TIFFFile.cs rename to src/Umbraco.Core/Media/Exif/TIFFFile.cs index 4f5301d526..19575eaff2 100644 --- a/src/Umbraco.Infrastructure/Media/Exif/TIFFFile.cs +++ b/src/Umbraco.Core/Media/Exif/TIFFFile.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Drawing; using System.IO; namespace Umbraco.Web.Media.Exif @@ -162,16 +161,6 @@ namespace Umbraco.Web.Media.Exif } } - /// - /// Converts the to a . - /// - /// Returns a containing image data. - public override Image ToImage() - { - MemoryStream stream = new MemoryStream(); - Save(stream); - return Image.FromStream(stream); - } #endregion } } diff --git a/src/Umbraco.Infrastructure/Media/Exif/TIFFHeader.cs b/src/Umbraco.Core/Media/Exif/TIFFHeader.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/TIFFHeader.cs rename to src/Umbraco.Core/Media/Exif/TIFFHeader.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/TIFFStrip.cs b/src/Umbraco.Core/Media/Exif/TIFFStrip.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/TIFFStrip.cs rename to src/Umbraco.Core/Media/Exif/TIFFStrip.cs diff --git a/src/Umbraco.Infrastructure/Media/Exif/Utility.cs b/src/Umbraco.Core/Media/Exif/Utility.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/Exif/Utility.cs rename to src/Umbraco.Core/Media/Exif/Utility.cs diff --git a/src/Umbraco.Core/Media/ExifImageDimensionExtractor.cs b/src/Umbraco.Core/Media/ExifImageDimensionExtractor.cs new file mode 100644 index 0000000000..441d2d6170 --- /dev/null +++ b/src/Umbraco.Core/Media/ExifImageDimensionExtractor.cs @@ -0,0 +1,26 @@ +using System; +using System.IO; +using Umbraco.Web.Media.Exif; + +namespace Umbraco.Core.Media +{ + public static class ExifImageDimensionExtractor + { + public static bool TryGetDimensions(Stream stream, out int width, out int height) + { + var jpgInfo = ImageFile.FromStream(stream); + height = -1; + width = -1; + if (jpgInfo != null + && jpgInfo.Format != ImageFileFormat.Unknown + && jpgInfo.Properties.ContainsKey(ExifTag.PixelYDimension) + && jpgInfo.Properties.ContainsKey(ExifTag.PixelXDimension)) + { + height = Convert.ToInt32(jpgInfo.Properties[ExifTag.PixelYDimension].Value); + width = Convert.ToInt32(jpgInfo.Properties[ExifTag.PixelXDimension].Value); + } + + return height > 0 && width > 0; + } + } +} diff --git a/src/Umbraco.Infrastructure/Media/TypeDetector/JpegDetector.cs b/src/Umbraco.Core/Media/TypeDetector/JpegDetector.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/TypeDetector/JpegDetector.cs rename to src/Umbraco.Core/Media/TypeDetector/JpegDetector.cs diff --git a/src/Umbraco.Infrastructure/Media/TypeDetector/RasterizedTypeDetector.cs b/src/Umbraco.Core/Media/TypeDetector/RasterizedTypeDetector.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/TypeDetector/RasterizedTypeDetector.cs rename to src/Umbraco.Core/Media/TypeDetector/RasterizedTypeDetector.cs diff --git a/src/Umbraco.Infrastructure/Media/TypeDetector/SvgDetector.cs b/src/Umbraco.Core/Media/TypeDetector/SvgDetector.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/TypeDetector/SvgDetector.cs rename to src/Umbraco.Core/Media/TypeDetector/SvgDetector.cs diff --git a/src/Umbraco.Infrastructure/Media/TypeDetector/TIFFDetector.cs b/src/Umbraco.Core/Media/TypeDetector/TIFFDetector.cs similarity index 100% rename from src/Umbraco.Infrastructure/Media/TypeDetector/TIFFDetector.cs rename to src/Umbraco.Core/Media/TypeDetector/TIFFDetector.cs diff --git a/src/Umbraco.Infrastructure/Services/Implement/IInstallationService.cs b/src/Umbraco.Core/Services/IInstallationService.cs similarity index 100% rename from src/Umbraco.Infrastructure/Services/Implement/IInstallationService.cs rename to src/Umbraco.Core/Services/IInstallationService.cs diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs b/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs index 96e4a9ae34..234f414f5f 100644 --- a/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs +++ b/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs @@ -7,7 +7,6 @@ using Microsoft.Extensions.Options; using Newtonsoft.Json; using Umbraco.Core; using Umbraco.Core.BackOffice; -using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Migrations.Install; using Umbraco.Core.Services; @@ -25,7 +24,7 @@ namespace Umbraco.Web.Install.InstallSteps /// display a simple continue installation view. /// [InstallSetupStep(InstallationType.NewInstall, "User", 20, "")] - internal class NewInstallStep : InstallSetupStep + public class NewInstallStep : InstallSetupStep { private readonly IUserService _userService; private readonly DatabaseBuilder _databaseBuilder; diff --git a/src/Umbraco.Infrastructure/Media/IImageDimensionExtractor.cs b/src/Umbraco.Infrastructure/Media/IImageDimensionExtractor.cs new file mode 100644 index 0000000000..3da7f37393 --- /dev/null +++ b/src/Umbraco.Infrastructure/Media/IImageDimensionExtractor.cs @@ -0,0 +1,9 @@ +using System.IO; + +namespace Umbraco.Web.Media +{ + public interface IImageDimensionExtractor + { + public ImageSize GetDimensions(Stream stream); + } +} diff --git a/src/Umbraco.Infrastructure/Media/ImageHelper.cs b/src/Umbraco.Infrastructure/Media/ImageDimensionExtractor.cs similarity index 58% rename from src/Umbraco.Infrastructure/Media/ImageHelper.cs rename to src/Umbraco.Infrastructure/Media/ImageDimensionExtractor.cs index ee01ec4a1c..538c559cf6 100644 --- a/src/Umbraco.Infrastructure/Media/ImageHelper.cs +++ b/src/Umbraco.Infrastructure/Media/ImageDimensionExtractor.cs @@ -2,11 +2,11 @@ using System.Drawing; using System.IO; using Umbraco.Core; -using Umbraco.Web.Media.Exif; +using Umbraco.Core.Media; namespace Umbraco.Web.Media { - public static class ImageHelper + internal class ImageDimensionExtractor : IImageDimensionExtractor { /// /// Gets the dimensions of an image. @@ -16,24 +16,14 @@ namespace Umbraco.Web.Media /// First try with EXIF as it is faster and does not load the entire image /// in memory. Fallback to GDI which means loading the image in memory and thus /// use potentially large amounts of memory. - public static Size GetDimensions(Stream stream) + public ImageSize GetDimensions(Stream stream) { //Try to load with exif try { - var jpgInfo = ImageFile.FromStream(stream); - - if (jpgInfo != null - && jpgInfo.Format != ImageFileFormat.Unknown - && jpgInfo.Properties.ContainsKey(ExifTag.PixelYDimension) - && jpgInfo.Properties.ContainsKey(ExifTag.PixelXDimension)) + if (ExifImageDimensionExtractor.TryGetDimensions(stream, out var width, out var height)) { - var height = Convert.ToInt32(jpgInfo.Properties[ExifTag.PixelYDimension].Value); - var width = Convert.ToInt32(jpgInfo.Properties[ExifTag.PixelXDimension].Value); - if (height > 0 && width > 0) - { - return new Size(width, height); - } + return new ImageSize(width, height); } } catch @@ -48,7 +38,7 @@ namespace Umbraco.Web.Media { var fileWidth = image.Width; var fileHeight = image.Height; - return new Size(fileWidth, fileHeight); + return new ImageSize(fileWidth, fileHeight); } } catch (Exception) @@ -56,7 +46,7 @@ namespace Umbraco.Web.Media //We will just swallow, just means we can't read via GDI, we don't want to log an error either } - return new Size(Constants.Conventions.Media.DefaultSize, Constants.Conventions.Media.DefaultSize); + return new ImageSize(Constants.Conventions.Media.DefaultSize, Constants.Conventions.Media.DefaultSize); } } } diff --git a/src/Umbraco.Infrastructure/Media/ImageSize.cs b/src/Umbraco.Infrastructure/Media/ImageSize.cs new file mode 100644 index 0000000000..6d073ac196 --- /dev/null +++ b/src/Umbraco.Infrastructure/Media/ImageSize.cs @@ -0,0 +1,15 @@ +namespace Umbraco.Web.Media +{ + public struct ImageSize + { + public int Width { get; } + public int Height { get; } + + + public ImageSize(int width, int height) + { + Width = width; + Height = height; + } + } +} diff --git a/src/Umbraco.Infrastructure/Media/UploadAutoFillProperties.cs b/src/Umbraco.Infrastructure/Media/UploadAutoFillProperties.cs index deeed7a07c..44d5f5c8c3 100644 --- a/src/Umbraco.Infrastructure/Media/UploadAutoFillProperties.cs +++ b/src/Umbraco.Infrastructure/Media/UploadAutoFillProperties.cs @@ -1,5 +1,4 @@ using System; -using System.Drawing; using System.IO; using Microsoft.Extensions.Logging; using Umbraco.Core; @@ -18,15 +17,18 @@ namespace Umbraco.Web.Media private readonly IMediaFileSystem _mediaFileSystem; private readonly ILogger _logger; private readonly IImageUrlGenerator _imageUrlGenerator; + private readonly IImageDimensionExtractor _imageDimensionExtractor; public UploadAutoFillProperties( IMediaFileSystem mediaFileSystem, ILogger logger, - IImageUrlGenerator imageUrlGenerator) + IImageUrlGenerator imageUrlGenerator, + IImageDimensionExtractor imageDimensionExtractor) { _mediaFileSystem = mediaFileSystem ?? throw new ArgumentNullException(nameof(mediaFileSystem)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _imageUrlGenerator = imageUrlGenerator ?? throw new ArgumentNullException(nameof(imageUrlGenerator)); + _imageDimensionExtractor = imageDimensionExtractor ?? throw new ArgumentNullException(nameof(imageDimensionExtractor)); } /// @@ -71,7 +73,7 @@ namespace Umbraco.Web.Media using (var filestream = _mediaFileSystem.OpenFile(filepath)) { var extension = (Path.GetExtension(filepath) ?? "").TrimStart('.'); - var size = _imageUrlGenerator.IsSupportedImageFormat(extension) ? (Size?)ImageHelper.GetDimensions(filestream) : null; + var size = _imageUrlGenerator.IsSupportedImageFormat(extension) ? (ImageSize?)_imageDimensionExtractor.GetDimensions(filestream) : null; SetProperties(content, autoFillConfig, size, filestream.Length, extension, culture, segment); } } @@ -105,12 +107,12 @@ namespace Umbraco.Web.Media else { var extension = (Path.GetExtension(filepath) ?? "").TrimStart('.'); - var size = _imageUrlGenerator.IsSupportedImageFormat(extension) ? (Size?)ImageHelper.GetDimensions(filestream) : null; + var size = _imageUrlGenerator.IsSupportedImageFormat(extension) ? (ImageSize?)_imageDimensionExtractor.GetDimensions(filestream) : null; SetProperties(content, autoFillConfig, size, filestream.Length, extension, culture, segment); } } - private static void SetProperties(IContentBase content, ImagingAutoFillUploadField autoFillConfig, Size? size, long length, string extension, string culture, string segment) + private static void SetProperties(IContentBase content, ImagingAutoFillUploadField autoFillConfig, ImageSize? size, long length, string extension, string culture, string segment) { if (content == null) throw new ArgumentNullException(nameof(content)); if (autoFillConfig == null) throw new ArgumentNullException(nameof(autoFillConfig)); diff --git a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs index 2a988a70a4..b199a7e8dc 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs @@ -1,6 +1,7 @@ using System; using Examine; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Umbraco.Core.Cache; using Umbraco.Core.Composing; @@ -9,6 +10,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Grid; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Dashboards; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Dictionary; using Umbraco.Core.Events; using Umbraco.Core.Hosting; @@ -25,6 +27,7 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.Validators; using Umbraco.Core.PropertyEditors.ValueConverters; using Umbraco.Core.Scoping; +using Umbraco.Core.Security; using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; @@ -56,11 +59,7 @@ using Umbraco.Web.Sections; using Umbraco.Web.Services; using Umbraco.Web.Templates; using Umbraco.Web.Trees; -using IntegerValidator = Umbraco.Core.PropertyEditors.Validators.IntegerValidator; using TextStringValueConverter = Umbraco.Core.PropertyEditors.ValueConverters.TextStringValueConverter; -using Microsoft.Extensions.Logging; -using Umbraco.Core.DependencyInjection; -using Umbraco.Core.Security; namespace Umbraco.Core.Runtime { @@ -379,6 +378,7 @@ namespace Umbraco.Core.Runtime builder.Services.AddUnique(); builder.Services.AddUnique(); builder.Services.AddUnique(); + builder.Services.AddUnique(); } } } From fb18317c0f67ec876c578148e65821a67645aa97 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Fri, 4 Dec 2020 19:01:52 +0100 Subject: [PATCH 04/27] Moved lots of property editors into core --- .../PropertyEditors/BlockListConfiguration.cs | 29 ++++++----- .../PropertyEditors/DataEditor.cs | 16 ++++-- .../PropertyEditors/DataValueEditor.cs | 39 +++++++++----- .../PropertyEditors/DateValueEditor.cs | 11 +++- .../PropertyEditors/DecimalPropertyEditor.cs | 6 ++- .../PropertyEditors/IntegerPropertyEditor.cs | 11 +++- .../MemberGroupPickerPropertyEditor.cs | 6 ++- .../MemberPickerPropertyEditor.cs | 6 ++- .../ContentTypeParameterEditor.cs | 6 ++- .../MultipleContentPickerParameterEditor.cs | 6 ++- .../MultipleContentTypeParameterEditor.cs | 6 ++- .../MultipleMediaPickerParameterEditor.cs | 10 ++-- .../MultiplePropertyGroupParameterEditor.cs | 6 ++- .../MultiplePropertyTypeParameterEditor.cs | 6 ++- .../PropertyGroupParameterEditor.cs | 6 ++- .../PropertyTypeParameterEditor.cs | 6 ++- .../PropertyEditors/RichTextConfiguration.cs | 5 +- .../PropertyEditors/TextOnlyValueEditor.cs | 11 +++- .../UserPickerPropertyEditor.cs | 6 ++- ...omplexEditorElementTypeValidationResult.cs | 0 ...mplexEditorPropertyTypeValidationResult.cs | 0 .../ComplexEditorValidationResult.cs | 0 .../MemberPickerValueConverter.cs | 0 .../PropertyEditors/VoidEditor.cs | 18 +++++-- .../Manifest/DataEditorConverter.cs | 18 +++++-- .../Manifest/ManifestParser.cs | 2 +- .../Packaging/PackageDataInstallation.cs | 6 ++- .../BlockEditorPropertyEditor.cs | 16 +++--- .../BlockListPropertyEditor.cs | 12 ++--- .../CheckBoxListPropertyEditor.cs | 7 +-- .../ColorPickerConfigurationEditor.cs | 19 ++++--- .../ColorPickerPropertyEditor.cs | 7 +-- .../ContentPickerPropertyEditor.cs | 11 ++-- .../PropertyEditors/DateTimePropertyEditor.cs | 5 +- .../DropDownFlexiblePropertyEditor.cs | 14 +++-- .../EmailAddressPropertyEditor.cs | 6 ++- .../FileUploadPropertyEditor.cs | 13 ++--- .../FileUploadPropertyValueEditor.cs | 6 ++- .../PropertyEditors/GridPropertyEditor.cs | 17 +++--- .../ImageCropperConfiguration.cs | 0 .../ImageCropperPropertyEditor.cs | 11 ++-- .../ImageCropperPropertyValueEditor.cs | 6 ++- .../PropertyEditors/LabelPropertyEditor.cs | 11 ++-- .../PropertyEditors/ListViewPropertyEditor.cs | 13 +++-- .../PropertyEditors/MarkdownPropertyEditor.cs | 6 ++- .../MediaPickerPropertyEditor.cs | 18 +++++-- .../MultiNodeTreePickerPropertyEditor.cs | 24 +++++++-- .../MultiUrlPickerPropertyEditor.cs | 18 +++++-- .../MultiUrlPickerValueEditor.cs | 18 +++++-- .../MultipleTextStringPropertyEditor.cs | 24 +++++++-- .../PropertyEditors/MultipleValueEditor.cs | 13 ++++- .../NestedContentPropertyEditor.cs | 13 +++-- .../RadioButtonsPropertyEditor.cs | 6 ++- .../PropertyEditors/RichTextPropertyEditor.cs | 13 +++-- .../PropertyEditors/SliderPropertyEditor.cs | 6 ++- .../PropertyEditors/TagsPropertyEditor.cs | 12 +++-- .../PropertyEditors/TextAreaPropertyEditor.cs | 14 +++-- .../PropertyEditors/TextboxPropertyEditor.cs | 14 +++-- .../TrueFalsePropertyEditor.cs | 12 ++++- .../Services/Implement/DataTypeService.cs | 10 ++-- .../Builders/DataEditorBuilder.cs | 5 +- .../Builders/DataValueEditorBuilder.cs | 4 +- .../TestHelpers/MockedValueEditors.cs | 2 + .../TestHelpers/SolidPublishedSnapshot.cs | 6 +-- .../DataTypeDefinitionRepositoryTest.cs | 25 ++++----- .../Services/CachedDataTypeServiceTests.cs | 3 +- .../Services/DataTypeServiceTests.cs | 5 +- .../Filters/ContentModelValidatorTests.cs | 24 +++++---- .../Umbraco.Core/Models/VariationTests.cs | 4 +- .../PropertyEditors/ColorListValidatorTest.cs | 11 ++-- ...ataValueReferenceFactoryCollectionTests.cs | 20 +++---- .../EnsureUniqueValuesValidatorTest.cs | 15 +++--- .../MultiValuePropertyEditorTests.cs | 5 +- .../Umbraco.Core/Published/ConvertersTests.cs | 5 +- .../Published/NestedContentTests.cs | 4 +- .../Published/PropertyCacheLevelTests.cs | 21 +++++--- .../Persistence/Querying/ExpressionTests.cs | 12 ++--- .../PropertyValidationServiceTests.cs | 12 ++++- src/Umbraco.Tests/Models/MediaXmlTest.cs | 3 +- .../Packaging/PackageDataInstallationTests.cs | 5 +- .../Packaging/PackageInstallationTest.cs | 6 +-- .../Published/ConvertersTests.cs | 4 +- .../PublishedContent/NuCacheChildrenTests.cs | 13 ++--- .../PublishedContent/NuCacheTests.cs | 7 +-- .../PublishedContentDataTableTests.cs | 6 +-- .../PublishedContentSnapshotTestBase.cs | 13 +++-- .../PublishedContentTestBase.cs | 31 ++++++----- .../PublishedContent/PublishedContentTests.cs | 32 ++++++------ .../SolidPublishedSnapshot.cs | 4 +- .../Routing/MediaUrlProviderTests.cs | 4 +- src/Umbraco.Tests/TestHelpers/BaseWebTest.cs | 5 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 22 ++++---- .../Controllers/ContentTypeController.cs | 52 ++++++++++++------- 93 files changed, 646 insertions(+), 381 deletions(-) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/BlockListConfiguration.cs (76%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/DataEditor.cs (92%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/DataValueEditor.cs (93%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/DateValueEditor.cs (70%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/DecimalPropertyEditor.cs (88%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/IntegerPropertyEditor.cs (72%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/MemberGroupPickerPropertyEditor.cs (81%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/MemberPickerPropertyEditor.cs (83%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/ParameterEditors/ContentTypeParameterEditor.cs (85%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/ParameterEditors/MultipleContentPickerParameterEditor.cs (86%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/ParameterEditors/MultipleContentTypeParameterEditor.cs (82%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/ParameterEditors/MultipleMediaPickerParameterEditor.cs (81%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/ParameterEditors/MultiplePropertyGroupParameterEditor.cs (84%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/ParameterEditors/MultiplePropertyTypeParameterEditor.cs (84%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/ParameterEditors/PropertyGroupParameterEditor.cs (84%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/ParameterEditors/PropertyTypeParameterEditor.cs (83%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/RichTextConfiguration.cs (92%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/TextOnlyValueEditor.cs (80%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/UserPickerPropertyEditor.cs (82%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/Validation/ComplexEditorElementTypeValidationResult.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/Validation/ComplexEditorPropertyTypeValidationResult.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/Validation/ComplexEditorValidationResult.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/VoidEditor.cs (73%) rename src/{Umbraco.Core => Umbraco.Infrastructure}/PropertyEditors/ImageCropperConfiguration.cs (100%) diff --git a/src/Umbraco.Infrastructure/PropertyEditors/BlockListConfiguration.cs b/src/Umbraco.Core/PropertyEditors/BlockListConfiguration.cs similarity index 76% rename from src/Umbraco.Infrastructure/PropertyEditors/BlockListConfiguration.cs rename to src/Umbraco.Core/PropertyEditors/BlockListConfiguration.cs index 1af3aa1303..f0aa1f0b77 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/BlockListConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/BlockListConfiguration.cs @@ -1,5 +1,5 @@ -using Newtonsoft.Json; -using System; +using System; +using System.Runtime.Serialization; using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors @@ -12,37 +12,38 @@ namespace Umbraco.Web.PropertyEditors [ConfigurationField("blocks", "Available Blocks", "views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.html", Description = "Define the available blocks.")] public BlockConfiguration[] Blocks { get; set; } + [DataContract] public class BlockConfiguration { - [JsonProperty("backgroundColor")] + [DataMember(Name ="backgroundColor")] public string BackgroundColor { get; set; } - [JsonProperty("iconColor")] + [DataMember(Name ="iconColor")] public string IconColor { get; set; } - [JsonProperty("thumbnail")] + [DataMember(Name ="thumbnail")] public string Thumbnail { get; set; } - [JsonProperty("contentElementTypeKey")] + [DataMember(Name ="contentElementTypeKey")] public Guid ContentElementTypeKey { get; set; } - [JsonProperty("settingsElementTypeKey")] + [DataMember(Name ="settingsElementTypeKey")] public Guid? SettingsElementTypeKey { get; set; } - [JsonProperty("view")] + [DataMember(Name ="view")] public string View { get; set; } - [JsonProperty("stylesheet")] + [DataMember(Name ="stylesheet")] public string Stylesheet { get; set; } - [JsonProperty("label")] + [DataMember(Name ="label")] public string Label { get; set; } - [JsonProperty("editorSize")] + [DataMember(Name ="editorSize")] public string EditorSize { get; set; } - [JsonProperty("forceHideContentEditorInOverlay")] + [DataMember(Name ="forceHideContentEditorInOverlay")] public bool ForceHideContentEditorInOverlay { get; set; } } @@ -51,10 +52,10 @@ namespace Umbraco.Web.PropertyEditors public class NumberRange { - [JsonProperty("min")] + [DataMember(Name ="min")] public int? Min { get; set; } - [JsonProperty("max")] + [DataMember(Name ="max")] public int? Max { get; set; } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/DataEditor.cs b/src/Umbraco.Core/PropertyEditors/DataEditor.cs similarity index 92% rename from src/Umbraco.Infrastructure/PropertyEditors/DataEditor.cs rename to src/Umbraco.Core/PropertyEditors/DataEditor.cs index d74f285553..ef533aa083 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/DataEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/DataEditor.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Runtime.Serialization; using Microsoft.Extensions.Logging; using Umbraco.Core.Composing; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -26,13 +27,21 @@ namespace Umbraco.Core.PropertyEditors /// /// Initializes a new instance of the class. /// - public DataEditor(ILoggerFactory loggerFactory, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, EditorType type = EditorType.PropertyValue) + public DataEditor( + ILoggerFactory loggerFactory, + IDataTypeService dataTypeService, + ILocalizationService localizationService, + ILocalizedTextService localizedTextService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer, + EditorType type = EditorType.PropertyValue) { LoggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); DataTypeService = dataTypeService ?? throw new ArgumentNullException(nameof(dataTypeService)); LocalizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService)); LocalizedTextService = localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService)); ShortStringHelper = shortStringHelper ?? throw new ArgumentNullException(nameof(shortStringHelper)); + JsonSerializer = jsonSerializer ?? throw new ArgumentNullException(nameof(jsonSerializer)); // defaults @@ -58,6 +67,7 @@ namespace Umbraco.Core.PropertyEditors protected DataEditorAttribute Attribute { get; } protected IShortStringHelper ShortStringHelper { get; } + public IJsonSerializer JsonSerializer { get; } protected ILocalizedTextService LocalizedTextService { get; } protected ILocalizationService LocalizationService { get; } protected ILoggerFactory LoggerFactory { get; } @@ -65,7 +75,7 @@ namespace Umbraco.Core.PropertyEditors /// [DataMember(Name = "alias", IsRequired = true)] - public string Alias { get; internal set; } + public string Alias { get; set; } /// [IgnoreDataMember] @@ -174,7 +184,7 @@ namespace Umbraco.Core.PropertyEditors if (Attribute == null) throw new InvalidOperationException($"The editor is not attributed with {nameof(DataEditorAttribute)}"); - return new DataValueEditor(DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, Attribute); + return new DataValueEditor(DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, JsonSerializer, Attribute); } /// diff --git a/src/Umbraco.Infrastructure/PropertyEditors/DataValueEditor.cs b/src/Umbraco.Core/PropertyEditors/DataValueEditor.cs similarity index 93% rename from src/Umbraco.Infrastructure/PropertyEditors/DataValueEditor.cs rename to src/Umbraco.Core/PropertyEditors/DataValueEditor.cs index fec245009f..237af042cf 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/DataValueEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/DataValueEditor.cs @@ -3,14 +3,13 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Linq; +using System.Runtime.Serialization; using System.Xml.Linq; using Microsoft.Extensions.Logging; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Core.Models.Editors; using Umbraco.Core.PropertyEditors.Validators; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -19,20 +18,28 @@ namespace Umbraco.Core.PropertyEditors /// /// Represents a value editor. /// + [DataContract] public class DataValueEditor : IDataValueEditor { private readonly ILocalizedTextService _localizedTextService; private readonly IShortStringHelper _shortStringHelper; + private readonly IJsonSerializer _jsonSerializer; protected IDataTypeService DataTypeService { get; } protected ILocalizationService LocalizationService { get; } /// /// Initializes a new instance of the class. /// - public DataValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper) // for tests, and manifest + public DataValueEditor( + IDataTypeService dataTypeService, + ILocalizationService localizationService, + ILocalizedTextService localizedTextService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) // for tests, and manifest { _localizedTextService = localizedTextService; _shortStringHelper = shortStringHelper; + _jsonSerializer = jsonSerializer; ValueType = ValueTypes.String; Validators = new List(); DataTypeService = dataTypeService; @@ -42,11 +49,18 @@ namespace Umbraco.Core.PropertyEditors /// /// Initializes a new instance of the class. /// - public DataValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, DataEditorAttribute attribute) + public DataValueEditor( + IDataTypeService dataTypeService, + ILocalizationService localizationService, + ILocalizedTextService localizedTextService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer, + DataEditorAttribute attribute) { if (attribute == null) throw new ArgumentNullException(nameof(attribute)); _localizedTextService = localizedTextService; _shortStringHelper = shortStringHelper; + _jsonSerializer = jsonSerializer; var view = attribute.View; if (string.IsNullOrWhiteSpace(view)) @@ -72,13 +86,14 @@ namespace Umbraco.Core.PropertyEditors /// The view can be three things: (1) the full virtual path, or (2) the relative path to the current Umbraco /// folder, or (3) a view name which maps to views/propertyeditors/{view}/{view}.html. /// - [JsonProperty("view", Required = Required.Always)] + [Required] + [DataMember(Name = "view")] public string View { get; set; } /// /// The value type which reflects how it is validated and stored in the database /// - [JsonProperty("valueType")] + [DataMember(Name = "valueType")] public string ValueType { get; set; } /// @@ -111,7 +126,7 @@ namespace Umbraco.Core.PropertyEditors /// /// A collection of validators for the pre value editor /// - [JsonProperty("validation")] + [DataMember(Name = "validation")] public List Validators { get; private set; } = new List(); /// @@ -127,7 +142,7 @@ namespace Umbraco.Core.PropertyEditors /// /// If this is true than the editor will be displayed full width without a label /// - [JsonProperty("hideLabel")] + [DataMember(Name = "hideLabel")] public bool HideLabel { get; set; } /// @@ -142,8 +157,8 @@ namespace Umbraco.Core.PropertyEditors /// internal Attempt TryConvertValueToCrlType(object value) { - if (value is JValue) - value = value.ToString(); + // if (value is JValue) + // value = value.ToString(); //this is a custom check to avoid any errors, if it's a string and it's empty just make it null if (value is string s && string.IsNullOrWhiteSpace(s)) @@ -250,7 +265,7 @@ namespace Umbraco.Core.PropertyEditors { try { - var json = JsonConvert.DeserializeObject(asString); + var json = _jsonSerializer.Deserialize(asString); return json; } catch diff --git a/src/Umbraco.Infrastructure/PropertyEditors/DateValueEditor.cs b/src/Umbraco.Core/PropertyEditors/DateValueEditor.cs similarity index 70% rename from src/Umbraco.Infrastructure/PropertyEditors/DateValueEditor.cs rename to src/Umbraco.Core/PropertyEditors/DateValueEditor.cs index 8973dd812b..b6208197c7 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/DateValueEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/DateValueEditor.cs @@ -2,6 +2,7 @@ using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -13,8 +14,14 @@ namespace Umbraco.Web.PropertyEditors /// internal class DateValueEditor : DataValueEditor { - public DateValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, DataEditorAttribute attribute) - : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, attribute) + public DateValueEditor( + IDataTypeService dataTypeService, + ILocalizationService localizationService, + ILocalizedTextService localizedTextService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer, + DataEditorAttribute attribute) + : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer, attribute) { Validators.Add(new DateTimeValidator()); } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/DecimalPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/DecimalPropertyEditor.cs similarity index 88% rename from src/Umbraco.Infrastructure/PropertyEditors/DecimalPropertyEditor.cs rename to src/Umbraco.Core/PropertyEditors/DecimalPropertyEditor.cs index 8d2280b23b..4aea9f944f 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/DecimalPropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/DecimalPropertyEditor.cs @@ -2,6 +2,7 @@ using Umbraco.Core; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.Validators; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -26,8 +27,9 @@ namespace Umbraco.Web.PropertyEditors IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, - IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { } /// diff --git a/src/Umbraco.Infrastructure/PropertyEditors/IntegerPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/IntegerPropertyEditor.cs similarity index 72% rename from src/Umbraco.Infrastructure/PropertyEditors/IntegerPropertyEditor.cs rename to src/Umbraco.Core/PropertyEditors/IntegerPropertyEditor.cs index 417ec112d7..43b988a49f 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/IntegerPropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/IntegerPropertyEditor.cs @@ -2,6 +2,7 @@ using Umbraco.Core; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.Validators; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -18,8 +19,14 @@ namespace Umbraco.Web.PropertyEditors ValueType = ValueTypes.Integer)] public class IntegerPropertyEditor : DataEditor { - public IntegerPropertyEditor(ILoggerFactory loggerFactory, IDataTypeService dataTypeService, ILocalizationService localizationService, IShortStringHelper shortStringHelper, ILocalizedTextService localizedTextService) - : base(loggerFactory, dataTypeService, localizationService,localizedTextService, shortStringHelper) + public IntegerPropertyEditor( + ILoggerFactory loggerFactory, + IDataTypeService dataTypeService, + ILocalizationService localizationService, + IShortStringHelper shortStringHelper, + ILocalizedTextService localizedTextService, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService,localizedTextService, shortStringHelper, jsonSerializer) { } /// diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MemberGroupPickerPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/MemberGroupPickerPropertyEditor.cs similarity index 81% rename from src/Umbraco.Infrastructure/PropertyEditors/MemberGroupPickerPropertyEditor.cs rename to src/Umbraco.Core/PropertyEditors/MemberGroupPickerPropertyEditor.cs index eb50d02284..34448b3816 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MemberGroupPickerPropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/MemberGroupPickerPropertyEditor.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.Logging; using Umbraco.Core; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -20,8 +21,9 @@ namespace Umbraco.Web.PropertyEditors IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, - IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { } } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MemberPickerPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/MemberPickerPropertyEditor.cs similarity index 83% rename from src/Umbraco.Infrastructure/PropertyEditors/MemberPickerPropertyEditor.cs rename to src/Umbraco.Core/PropertyEditors/MemberPickerPropertyEditor.cs index 3676340aee..b572f47cfd 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MemberPickerPropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/MemberPickerPropertyEditor.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.Logging; using Umbraco.Core; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -20,8 +21,9 @@ namespace Umbraco.Web.PropertyEditors IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, - IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { } protected override IConfigurationEditor CreateConfigurationEditor() => new MemberPickerConfiguration(); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/ContentTypeParameterEditor.cs b/src/Umbraco.Core/PropertyEditors/ParameterEditors/ContentTypeParameterEditor.cs similarity index 85% rename from src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/ContentTypeParameterEditor.cs rename to src/Umbraco.Core/PropertyEditors/ParameterEditors/ContentTypeParameterEditor.cs index 2da9e184c3..619fd89692 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/ContentTypeParameterEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/ParameterEditors/ContentTypeParameterEditor.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Logging; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -23,8 +24,9 @@ namespace Umbraco.Web.PropertyEditors.ParameterEditors IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, - IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { // configure DefaultConfiguration.Add("multiple", false); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultipleContentPickerParameterEditor.cs b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleContentPickerParameterEditor.cs similarity index 86% rename from src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultipleContentPickerParameterEditor.cs rename to src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleContentPickerParameterEditor.cs index d416cf111a..5110dfdc79 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultipleContentPickerParameterEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleContentPickerParameterEditor.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.Logging; using Umbraco.Core; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -24,8 +25,9 @@ namespace Umbraco.Web.PropertyEditors.ParameterEditors IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, - IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { // configure DefaultConfiguration.Add("multiPicker", "1"); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultipleContentTypeParameterEditor.cs b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleContentTypeParameterEditor.cs similarity index 82% rename from src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultipleContentTypeParameterEditor.cs rename to src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleContentTypeParameterEditor.cs index 613d6a6a5e..ff08420cd9 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultipleContentTypeParameterEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleContentTypeParameterEditor.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Logging; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -17,8 +18,9 @@ namespace Umbraco.Web.PropertyEditors.ParameterEditors IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, - IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { // configure DefaultConfiguration.Add("multiple", true); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultipleMediaPickerParameterEditor.cs b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleMediaPickerParameterEditor.cs similarity index 81% rename from src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultipleMediaPickerParameterEditor.cs rename to src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleMediaPickerParameterEditor.cs index 73a3b42610..a2750447a8 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultipleMediaPickerParameterEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleMediaPickerParameterEditor.cs @@ -1,6 +1,7 @@ -using Umbraco.Core; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; +using Umbraco.Core; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -25,8 +26,9 @@ namespace Umbraco.Web.PropertyEditors.ParameterEditors IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, - IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { DefaultConfiguration.Add("multiPicker", "1"); } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultiplePropertyGroupParameterEditor.cs b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultiplePropertyGroupParameterEditor.cs similarity index 84% rename from src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultiplePropertyGroupParameterEditor.cs rename to src/Umbraco.Core/PropertyEditors/ParameterEditors/MultiplePropertyGroupParameterEditor.cs index 16cd596fc8..22571db975 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultiplePropertyGroupParameterEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultiplePropertyGroupParameterEditor.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Logging; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -17,8 +18,9 @@ namespace Umbraco.Web.PropertyEditors.ParameterEditors IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, - IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { // configure DefaultConfiguration.Add("multiple", true); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultiplePropertyTypeParameterEditor.cs b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultiplePropertyTypeParameterEditor.cs similarity index 84% rename from src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultiplePropertyTypeParameterEditor.cs rename to src/Umbraco.Core/PropertyEditors/ParameterEditors/MultiplePropertyTypeParameterEditor.cs index e9576fab02..251d982777 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/MultiplePropertyTypeParameterEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultiplePropertyTypeParameterEditor.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Logging; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -17,8 +18,9 @@ namespace Umbraco.Web.PropertyEditors.ParameterEditors IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, - IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { // configure DefaultConfiguration.Add("multiple", "1"); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/PropertyGroupParameterEditor.cs b/src/Umbraco.Core/PropertyEditors/ParameterEditors/PropertyGroupParameterEditor.cs similarity index 84% rename from src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/PropertyGroupParameterEditor.cs rename to src/Umbraco.Core/PropertyEditors/ParameterEditors/PropertyGroupParameterEditor.cs index 345afa3b46..aabef3e1b0 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/PropertyGroupParameterEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/ParameterEditors/PropertyGroupParameterEditor.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Logging; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -17,8 +18,9 @@ namespace Umbraco.Web.PropertyEditors.ParameterEditors IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, - IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { // configure DefaultConfiguration.Add("multiple", "0"); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/PropertyTypeParameterEditor.cs b/src/Umbraco.Core/PropertyEditors/ParameterEditors/PropertyTypeParameterEditor.cs similarity index 83% rename from src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/PropertyTypeParameterEditor.cs rename to src/Umbraco.Core/PropertyEditors/ParameterEditors/PropertyTypeParameterEditor.cs index be682a35d3..c3178d3138 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ParameterEditors/PropertyTypeParameterEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/ParameterEditors/PropertyTypeParameterEditor.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Logging; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -17,8 +18,9 @@ namespace Umbraco.Web.PropertyEditors.ParameterEditors IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, - IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { // configure DefaultConfiguration.Add("multiple", "0"); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/RichTextConfiguration.cs b/src/Umbraco.Core/PropertyEditors/RichTextConfiguration.cs similarity index 92% rename from src/Umbraco.Infrastructure/PropertyEditors/RichTextConfiguration.cs rename to src/Umbraco.Core/PropertyEditors/RichTextConfiguration.cs index c6d4e3ce70..c1fb61bde8 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/RichTextConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/RichTextConfiguration.cs @@ -1,5 +1,4 @@ -using Newtonsoft.Json.Linq; -using Umbraco.Core; +using Umbraco.Core; using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors @@ -11,7 +10,7 @@ namespace Umbraco.Web.PropertyEditors { // TODO: Make these strongly typed, for now this works though [ConfigurationField("editor", "Editor", "views/propertyeditors/rte/rte.prevalues.html", HideLabel = true)] - public JObject Editor { get; set; } + public object Editor { get; set; } [ConfigurationField("hideLabel", "Hide Label", "boolean")] public bool HideLabel { get; set; } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/TextOnlyValueEditor.cs b/src/Umbraco.Core/PropertyEditors/TextOnlyValueEditor.cs similarity index 80% rename from src/Umbraco.Infrastructure/PropertyEditors/TextOnlyValueEditor.cs rename to src/Umbraco.Core/PropertyEditors/TextOnlyValueEditor.cs index ec48cf8b57..aeac87079c 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/TextOnlyValueEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/TextOnlyValueEditor.cs @@ -1,6 +1,7 @@ using System; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -12,8 +13,14 @@ namespace Umbraco.Web.PropertyEditors /// public class TextOnlyValueEditor : DataValueEditor { - public TextOnlyValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, DataEditorAttribute attribute, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper) - : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, attribute) + public TextOnlyValueEditor( + IDataTypeService dataTypeService, + ILocalizationService localizationService, + DataEditorAttribute attribute, + ILocalizedTextService localizedTextService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer, attribute) { } /// diff --git a/src/Umbraco.Infrastructure/PropertyEditors/UserPickerPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/UserPickerPropertyEditor.cs similarity index 82% rename from src/Umbraco.Infrastructure/PropertyEditors/UserPickerPropertyEditor.cs rename to src/Umbraco.Core/PropertyEditors/UserPickerPropertyEditor.cs index 891fb54ee3..f22c3d94dc 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/UserPickerPropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/UserPickerPropertyEditor.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.Logging; using Umbraco.Core; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -20,8 +21,9 @@ namespace Umbraco.Web.PropertyEditors IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, - IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { } protected override IConfigurationEditor CreateConfigurationEditor() => new UserPickerConfiguration(); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/Validation/ComplexEditorElementTypeValidationResult.cs b/src/Umbraco.Core/PropertyEditors/Validation/ComplexEditorElementTypeValidationResult.cs similarity index 100% rename from src/Umbraco.Infrastructure/PropertyEditors/Validation/ComplexEditorElementTypeValidationResult.cs rename to src/Umbraco.Core/PropertyEditors/Validation/ComplexEditorElementTypeValidationResult.cs diff --git a/src/Umbraco.Infrastructure/PropertyEditors/Validation/ComplexEditorPropertyTypeValidationResult.cs b/src/Umbraco.Core/PropertyEditors/Validation/ComplexEditorPropertyTypeValidationResult.cs similarity index 100% rename from src/Umbraco.Infrastructure/PropertyEditors/Validation/ComplexEditorPropertyTypeValidationResult.cs rename to src/Umbraco.Core/PropertyEditors/Validation/ComplexEditorPropertyTypeValidationResult.cs diff --git a/src/Umbraco.Infrastructure/PropertyEditors/Validation/ComplexEditorValidationResult.cs b/src/Umbraco.Core/PropertyEditors/Validation/ComplexEditorValidationResult.cs similarity index 100% rename from src/Umbraco.Infrastructure/PropertyEditors/Validation/ComplexEditorValidationResult.cs rename to src/Umbraco.Core/PropertyEditors/Validation/ComplexEditorValidationResult.cs diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs similarity index 100% rename from src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs rename to src/Umbraco.Core/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs diff --git a/src/Umbraco.Infrastructure/PropertyEditors/VoidEditor.cs b/src/Umbraco.Core/PropertyEditors/VoidEditor.cs similarity index 73% rename from src/Umbraco.Infrastructure/PropertyEditors/VoidEditor.cs rename to src/Umbraco.Core/PropertyEditors/VoidEditor.cs index e26cd4129a..d2e84b7952 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/VoidEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/VoidEditor.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Logging; using Umbraco.Core.Composing; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -14,6 +15,8 @@ namespace Umbraco.Core.PropertyEditors [HideFromTypeFinder] public class VoidEditor : DataEditor { + private readonly IJsonSerializer _jsonSerializer; + /// /// Initializes a new instance of the class. /// @@ -21,8 +24,15 @@ namespace Umbraco.Core.PropertyEditors /// A logger factory. /// The default alias of the editor is "Umbraco.Void". When a suffix is provided, /// it is appended to the alias. Eg if the suffix is "Foo" the alias is "Umbraco.Void.Foo". - public VoidEditor(string aliasSuffix, ILoggerFactory loggerFactory, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + public VoidEditor( + string aliasSuffix, + ILoggerFactory loggerFactory, + IDataTypeService dataTypeService, + ILocalizationService localizationService, + ILocalizedTextService localizedTextService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { Alias = "Umbraco.Void"; if (string.IsNullOrWhiteSpace(aliasSuffix)) return; @@ -34,8 +44,8 @@ namespace Umbraco.Core.PropertyEditors /// /// A logger factory. /// The alias of the editor is "Umbraco.Void". - public VoidEditor(ILoggerFactory loggerFactory, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper) - : this(null, loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + public VoidEditor(ILoggerFactory loggerFactory, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, IJsonSerializer jsonSerializer) + : this(null, loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { } } } diff --git a/src/Umbraco.Infrastructure/Manifest/DataEditorConverter.cs b/src/Umbraco.Infrastructure/Manifest/DataEditorConverter.cs index 94b868f145..1bbd9042b0 100644 --- a/src/Umbraco.Infrastructure/Manifest/DataEditorConverter.cs +++ b/src/Umbraco.Infrastructure/Manifest/DataEditorConverter.cs @@ -2,7 +2,6 @@ using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using Umbraco.Core.Composing; using Umbraco.Core.IO; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Serialization; @@ -22,11 +21,19 @@ namespace Umbraco.Core.Manifest private readonly ILocalizationService _localizationService; private readonly ILocalizedTextService _textService; private readonly IShortStringHelper _shortStringHelper; + private readonly IJsonSerializer _jsonSerializer; /// /// Initializes a new instance of the class. /// - public DataEditorConverter(ILoggerFactory loggerFactory, IIOHelper ioHelper, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService textService, IShortStringHelper shortStringHelper) + public DataEditorConverter( + ILoggerFactory loggerFactory, + IIOHelper ioHelper, + IDataTypeService dataTypeService, + ILocalizationService localizationService, + ILocalizedTextService textService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) { _loggerFactory = loggerFactory; _ioHelper = ioHelper; @@ -34,6 +41,7 @@ namespace Umbraco.Core.Manifest _localizationService = localizationService; _textService = textService; _shortStringHelper = shortStringHelper; + _jsonSerializer = jsonSerializer; } /// @@ -61,7 +69,7 @@ namespace Umbraco.Core.Manifest type = EditorType.MacroParameter; } - return new DataEditor(_loggerFactory, _dataTypeService, _localizationService, _textService, _shortStringHelper, type); + return new DataEditor(_loggerFactory, _dataTypeService, _localizationService, _textService, _shortStringHelper, _jsonSerializer, type); } /// @@ -88,7 +96,7 @@ namespace Umbraco.Core.Manifest // explicitly assign a value editor of type ValueEditor // (else the deserializer will try to read it before setting it) // (and besides it's an interface) - target.ExplicitValueEditor = new DataValueEditor(_dataTypeService, _localizationService, _textService, _shortStringHelper); + target.ExplicitValueEditor = new DataValueEditor(_dataTypeService, _localizationService, _textService, _shortStringHelper, _jsonSerializer); // in the manifest, validators are a simple dictionary eg // { @@ -160,7 +168,7 @@ namespace Umbraco.Core.Manifest if (jobject.Property("view") != null) { // explicitly assign a value editor of type ParameterValueEditor - target.ExplicitValueEditor = new DataValueEditor(_dataTypeService, _localizationService, _textService, _shortStringHelper); + target.ExplicitValueEditor = new DataValueEditor(_dataTypeService, _localizationService, _textService, _shortStringHelper, _jsonSerializer); // move the 'view' property jobject["editor"] = new JObject { ["view"] = jobject["view"] }; diff --git a/src/Umbraco.Infrastructure/Manifest/ManifestParser.cs b/src/Umbraco.Infrastructure/Manifest/ManifestParser.cs index eec83dffef..15ddcebb7e 100644 --- a/src/Umbraco.Infrastructure/Manifest/ManifestParser.cs +++ b/src/Umbraco.Infrastructure/Manifest/ManifestParser.cs @@ -196,7 +196,7 @@ namespace Umbraco.Core.Manifest if (string.IsNullOrWhiteSpace(text)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(text)); var manifest = JsonConvert.DeserializeObject(text, - new DataEditorConverter(_loggerFactory, _ioHelper, _dataTypeService, _localizationService, _localizedTextService, _shortStringHelper), + new DataEditorConverter(_loggerFactory, _ioHelper, _dataTypeService, _localizationService, _localizedTextService, _shortStringHelper, _jsonSerializer), new ValueValidatorConverter(_validators), new DashboardAccessRuleConverter()); diff --git a/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs b/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs index 5f5ee63642..f8bf6283f5 100644 --- a/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs +++ b/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs @@ -34,6 +34,7 @@ namespace Umbraco.Core.Packaging private readonly GlobalSettings _globalSettings; private readonly ILocalizedTextService _localizedTextService; private readonly IConfigurationEditorJsonSerializer _serializer; + private readonly IJsonSerializer _jsonSerializer; private readonly IEntityService _entityService; private readonly IContentTypeService _contentTypeService; private readonly IContentService _contentService; @@ -41,7 +42,7 @@ namespace Umbraco.Core.Packaging public PackageDataInstallation(ILogger logger, ILoggerFactory loggerFactory, IFileService fileService, IMacroService macroService, ILocalizationService localizationService, IDataTypeService dataTypeService, IEntityService entityService, IContentTypeService contentTypeService, IContentService contentService, PropertyEditorCollection propertyEditors, IScopeProvider scopeProvider, IShortStringHelper shortStringHelper, IOptions globalSettings, - ILocalizedTextService localizedTextService, IConfigurationEditorJsonSerializer serializer) + ILocalizedTextService localizedTextService, IConfigurationEditorJsonSerializer serializer, IJsonSerializer jsonSerializer) { _logger = logger; _loggerFactory = loggerFactory; @@ -55,6 +56,7 @@ namespace Umbraco.Core.Packaging _globalSettings = globalSettings.Value; _localizedTextService = localizedTextService; _serializer = serializer; + _jsonSerializer = jsonSerializer; _entityService = entityService; _contentTypeService = contentTypeService; _contentService = contentService; @@ -911,7 +913,7 @@ namespace Umbraco.Core.Packaging var editorAlias = dataTypeElement.Attribute("Id")?.Value?.Trim(); if (!_propertyEditors.TryGet(editorAlias, out var editor)) - editor = new VoidEditor(_loggerFactory, _dataTypeService, _localizationService, _localizedTextService, _shortStringHelper) { Alias = editorAlias }; + editor = new VoidEditor(_loggerFactory, _dataTypeService, _localizationService, _localizedTextService, _shortStringHelper, _jsonSerializer) { Alias = editorAlias }; var dataType = new DataType(editor, _serializer) { diff --git a/src/Umbraco.Infrastructure/PropertyEditors/BlockEditorPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/BlockEditorPropertyEditor.cs index b1e5fb0199..81281a3302 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/BlockEditorPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/BlockEditorPropertyEditor.cs @@ -1,14 +1,15 @@ -using Newtonsoft.Json; -using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using Microsoft.Extensions.Logging; +using Newtonsoft.Json; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Blocks; using Umbraco.Core.Models.Editors; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; using static Umbraco.Core.Models.Blocks.BlockItemData; @@ -35,8 +36,9 @@ namespace Umbraco.Web.PropertyEditors IContentTypeService contentTypeService, ILocalizedTextService localizedTextService, ILocalizationService localizationService, - IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService,localizationService,localizedTextService, shortStringHelper) + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService,localizationService,localizedTextService, shortStringHelper, jsonSerializer) { _localizedTextService = localizedTextService; _propertyEditors = propertyEditors; @@ -49,7 +51,7 @@ namespace Umbraco.Web.PropertyEditors #region Value Editor - protected override IDataValueEditor CreateValueEditor() => new BlockEditorPropertyValueEditor(Attribute, PropertyEditors, _dataTypeService, _contentTypeService, _localizedTextService, LoggerFactory.CreateLogger(), LocalizationService,ShortStringHelper); + protected override IDataValueEditor CreateValueEditor() => new BlockEditorPropertyValueEditor(Attribute, PropertyEditors, _dataTypeService, _contentTypeService, _localizedTextService, LoggerFactory.CreateLogger(), LocalizationService,ShortStringHelper, JsonSerializer); internal class BlockEditorPropertyValueEditor : DataValueEditor, IDataValueReference { @@ -58,8 +60,8 @@ namespace Umbraco.Web.PropertyEditors private readonly ILogger _logger; private readonly BlockEditorValues _blockEditorValues; - public BlockEditorPropertyValueEditor(DataEditorAttribute attribute, PropertyEditorCollection propertyEditors, IDataTypeService dataTypeService, IContentTypeService contentTypeService, ILocalizedTextService textService, ILogger logger, ILocalizationService localizationService, IShortStringHelper shortStringHelper) - : base(dataTypeService, localizationService, textService, shortStringHelper, attribute) + public BlockEditorPropertyValueEditor(DataEditorAttribute attribute, PropertyEditorCollection propertyEditors, IDataTypeService dataTypeService, IContentTypeService contentTypeService, ILocalizedTextService textService, ILogger logger, ILocalizationService localizationService, IShortStringHelper shortStringHelper, IJsonSerializer jsonSerializer) + : base(dataTypeService, localizationService, textService, shortStringHelper, jsonSerializer, attribute) { _propertyEditors = propertyEditors; _dataTypeService = dataTypeService; diff --git a/src/Umbraco.Infrastructure/PropertyEditors/BlockListPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/BlockListPropertyEditor.cs index 6a23d0da00..1657b4098d 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/BlockListPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/BlockListPropertyEditor.cs @@ -1,12 +1,9 @@ -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; -using System.Linq; +using System; using Microsoft.Extensions.Logging; using Umbraco.Core; using Umbraco.Core.IO; -using Umbraco.Core.Models.Blocks; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -34,8 +31,9 @@ namespace Umbraco.Web.PropertyEditors ILocalizedTextService localizedTextService, IIOHelper ioHelper, ILocalizationService localizationService, - IShortStringHelper shortStringHelper) - : base(loggerFactory, propertyEditors, dataTypeService, contentTypeService, localizedTextService, localizationService, shortStringHelper) + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, propertyEditors, dataTypeService, contentTypeService, localizedTextService, localizationService, shortStringHelper, jsonSerializer) { _ioHelper = ioHelper; } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/CheckBoxListPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/CheckBoxListPropertyEditor.cs index 09600d86ae..27d729e319 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/CheckBoxListPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/CheckBoxListPropertyEditor.cs @@ -2,6 +2,7 @@ using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -28,8 +29,8 @@ namespace Umbraco.Web.PropertyEditors /// /// The constructor will setup the property editor based on the attribute if one is found /// - public CheckBoxListPropertyEditor(ILoggerFactory loggerFactory, ILocalizedTextService textService, IDataTypeService dataTypeService, ILocalizationService localizationService, IShortStringHelper shortStringHelper, IIOHelper ioHelper, ILocalizedTextService localizedTextService) - : base(loggerFactory, dataTypeService, localizationService,localizedTextService, shortStringHelper) + public CheckBoxListPropertyEditor(ILoggerFactory loggerFactory, ILocalizedTextService textService, IDataTypeService dataTypeService, ILocalizationService localizationService, IShortStringHelper shortStringHelper, IIOHelper ioHelper, ILocalizedTextService localizedTextService, IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService,localizedTextService, shortStringHelper, jsonSerializer) { _textService = textService; _dataTypeService = dataTypeService; @@ -43,6 +44,6 @@ namespace Umbraco.Web.PropertyEditors protected override IConfigurationEditor CreateConfigurationEditor() => new ValueListConfigurationEditor(_textService, _ioHelper); /// - protected override IDataValueEditor CreateValueEditor() => new MultipleValueEditor(LoggerFactory.CreateLogger(), _dataTypeService, _localizationService, _localizedTextService, _shortStringHelper, Attribute); + protected override IDataValueEditor CreateValueEditor() => new MultipleValueEditor(LoggerFactory.CreateLogger(), _dataTypeService, _localizationService, _localizedTextService, _shortStringHelper, JsonSerializer, Attribute); } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ColorPickerConfigurationEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/ColorPickerConfigurationEditor.cs index e2cc93bd7c..f5776b7c28 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ColorPickerConfigurationEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ColorPickerConfigurationEditor.cs @@ -1,19 +1,23 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; +using System.Runtime.Serialization; using System.Text.RegularExpressions; -using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; namespace Umbraco.Web.PropertyEditors { internal class ColorPickerConfigurationEditor : ConfigurationEditor { - public ColorPickerConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) + private readonly IJsonSerializer _jsonSerializer; + + public ColorPickerConfigurationEditor(IIOHelper ioHelper, IJsonSerializer jsonSerializer) : base(ioHelper) { + _jsonSerializer = jsonSerializer; var items = Fields.First(x => x.Key == "items"); // customize the items field @@ -67,7 +71,7 @@ namespace Umbraco.Web.PropertyEditors { try { - var o = JsonConvert.DeserializeObject(item.Value); + var o = _jsonSerializer.Deserialize(item.Value); o.SortOrder = sortOrder; return o; } @@ -82,15 +86,16 @@ namespace Umbraco.Web.PropertyEditors } // represents an item we are exchanging with the editor + [DataContract] private class ItemValue { - [JsonProperty("value")] + [DataMember(Name ="value")] public string Color { get; set; } - [JsonProperty("label")] + [DataMember(Name ="label")] public string Label { get; set; } - [JsonProperty("sortOrder")] + [DataMember(Name ="sortOrder")] public int SortOrder { get; set; } } @@ -131,7 +136,7 @@ namespace Umbraco.Web.PropertyEditors if (id >= nextId) nextId = id + 1; var label = item.Property("label")?.Value?.Value(); - value = JsonConvert.SerializeObject(new { value, label }); + value = _jsonSerializer.Serialize(new { value, label }); output.Items.Add(new ValueListConfiguration.ValueListItem { Id = id, Value = value }); } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ColorPickerPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/ColorPickerPropertyEditor.cs index 575609a934..aec8e4b137 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ColorPickerPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ColorPickerPropertyEditor.cs @@ -2,6 +2,7 @@ using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -17,13 +18,13 @@ namespace Umbraco.Web.PropertyEditors { private readonly IIOHelper _ioHelper; - public ColorPickerPropertyEditor(ILoggerFactory loggerFactory, IDataTypeService dataTypeService, ILocalizationService localizationService, IIOHelper ioHelper, IShortStringHelper shortStringHelper, ILocalizedTextService localizedTextService) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + public ColorPickerPropertyEditor(ILoggerFactory loggerFactory, IDataTypeService dataTypeService, ILocalizationService localizationService, IIOHelper ioHelper, IShortStringHelper shortStringHelper, ILocalizedTextService localizedTextService, IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { _ioHelper = ioHelper; } /// - protected override IConfigurationEditor CreateConfigurationEditor() => new ColorPickerConfigurationEditor(_ioHelper); + protected override IConfigurationEditor CreateConfigurationEditor() => new ColorPickerConfigurationEditor(_ioHelper, JsonSerializer); } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ContentPickerPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/ContentPickerPropertyEditor.cs index 4c172ccb2e..c95f14e8e0 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ContentPickerPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ContentPickerPropertyEditor.cs @@ -4,6 +4,7 @@ using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.Models.Editors; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -32,8 +33,9 @@ namespace Umbraco.Web.PropertyEditors ILocalizedTextService localizedTextService, ILoggerFactory loggerFactory, IIOHelper ioHelper, - IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService,localizationService,localizedTextService, shortStringHelper) + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService,localizationService,localizedTextService, shortStringHelper, jsonSerializer) { _dataTypeService = dataTypeService; _localizationService = localizationService; @@ -46,11 +48,12 @@ namespace Umbraco.Web.PropertyEditors return new ContentPickerConfigurationEditor(_ioHelper); } - protected override IDataValueEditor CreateValueEditor() => new ContentPickerPropertyValueEditor(_dataTypeService, _localizationService, _localizedTextService, ShortStringHelper, Attribute); + protected override IDataValueEditor CreateValueEditor() => new ContentPickerPropertyValueEditor(_dataTypeService, _localizationService, _localizedTextService, ShortStringHelper, JsonSerializer, Attribute); internal class ContentPickerPropertyValueEditor : DataValueEditor, IDataValueReference { - public ContentPickerPropertyValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, DataEditorAttribute attribute) : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, attribute) + public ContentPickerPropertyValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, IJsonSerializer jsonSerializer, DataEditorAttribute attribute) + : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer, attribute) { } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/DateTimePropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/DateTimePropertyEditor.cs index db4c6734a8..40ece10a1e 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/DateTimePropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/DateTimePropertyEditor.cs @@ -2,6 +2,7 @@ using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -24,8 +25,8 @@ namespace Umbraco.Web.PropertyEditors /// Initializes a new instance of the class. /// /// - public DateTimePropertyEditor(ILoggerFactory loggerFactory, IIOHelper ioHelper, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService,localizedTextService, shortStringHelper) + public DateTimePropertyEditor(ILoggerFactory loggerFactory, IIOHelper ioHelper, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService,localizedTextService, shortStringHelper, jsonSerializer) { _ioHelper = ioHelper; } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/DropDownFlexiblePropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/DropDownFlexiblePropertyEditor.cs index 66f605bc36..186730775e 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/DropDownFlexiblePropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/DropDownFlexiblePropertyEditor.cs @@ -2,6 +2,7 @@ using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -21,8 +22,15 @@ namespace Umbraco.Web.PropertyEditors private readonly IShortStringHelper _shortStringHelper; private readonly IIOHelper _ioHelper; - public DropDownFlexiblePropertyEditor(ILocalizedTextService textService, ILoggerFactory loggerFactory, IDataTypeService dataTypeService, ILocalizationService localizationService, IShortStringHelper shortStringHelper, IIOHelper ioHelper) - : base(loggerFactory, dataTypeService, localizationService, textService, shortStringHelper) + public DropDownFlexiblePropertyEditor( + ILocalizedTextService textService, + ILoggerFactory loggerFactory, + IDataTypeService dataTypeService, + ILocalizationService localizationService, + IShortStringHelper shortStringHelper, + IIOHelper ioHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, textService, shortStringHelper, jsonSerializer) { _textService = textService; _dataTypeService = dataTypeService; @@ -33,7 +41,7 @@ namespace Umbraco.Web.PropertyEditors protected override IDataValueEditor CreateValueEditor() { - return new MultipleValueEditor(LoggerFactory.CreateLogger(), _dataTypeService, _localizationService, _textService, _shortStringHelper, Attribute); + return new MultipleValueEditor(LoggerFactory.CreateLogger(), _dataTypeService, _localizationService, _textService, _shortStringHelper, JsonSerializer, Attribute); } protected override IConfigurationEditor CreateConfigurationEditor() => new DropDownFlexibleConfigurationEditor(_textService, _ioHelper); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/EmailAddressPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/EmailAddressPropertyEditor.cs index 2cdfd4f7eb..120a522cd7 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/EmailAddressPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/EmailAddressPropertyEditor.cs @@ -3,6 +3,7 @@ using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.Validators; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -27,8 +28,9 @@ namespace Umbraco.Web.PropertyEditors IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, - IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { _ioHelper = ioHelper; } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyEditor.cs index 448e2043c0..b425432b01 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyEditor.cs @@ -7,9 +7,9 @@ using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; -using Umbraco.Core.Media; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Web.Media; @@ -39,8 +39,9 @@ namespace Umbraco.Web.PropertyEditors ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, - UploadAutoFillProperties uploadAutoFillProperties) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + UploadAutoFillProperties uploadAutoFillProperties, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { _mediaFileSystem = mediaFileSystem ?? throw new ArgumentNullException(nameof(mediaFileSystem)); _contentSettings = contentSettings.Value; @@ -56,7 +57,7 @@ namespace Umbraco.Web.PropertyEditors /// The corresponding property value editor. protected override IDataValueEditor CreateValueEditor() { - var editor = new FileUploadPropertyValueEditor(Attribute, _mediaFileSystem, _dataTypeService, _localizationService, _localizedTextService, ShortStringHelper, Options.Create(_contentSettings)); + var editor = new FileUploadPropertyValueEditor(Attribute, _mediaFileSystem, _dataTypeService, _localizationService, _localizedTextService, ShortStringHelper, Options.Create(_contentSettings), JsonSerializer); editor.Validators.Add(new UploadFileTypeValidator(_localizedTextService, Options.Create(_contentSettings))); return editor; } @@ -162,7 +163,7 @@ namespace Umbraco.Web.PropertyEditors /// /// The event sender. /// The event arguments. - internal void MediaServiceSaving(IMediaService sender, Core.Events.SaveEventArgs args) + public void MediaServiceSaving(IMediaService sender, Core.Events.SaveEventArgs args) { foreach (var entity in args.SavedEntities) AutoFillProperties(entity); @@ -173,7 +174,7 @@ namespace Umbraco.Web.PropertyEditors /// /// The event sender. /// The event arguments. - internal void ContentServiceSaving(IContentService sender, Core.Events.SaveEventArgs args) + public void ContentServiceSaving(IContentService sender, Core.Events.SaveEventArgs args) { foreach (var entity in args.SavedEntities) AutoFillProperties(entity); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyValueEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyValueEditor.cs index db675e2e42..8ccb59988d 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyValueEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyValueEditor.cs @@ -6,6 +6,7 @@ using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; using Umbraco.Core.Models.Editors; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -26,8 +27,9 @@ namespace Umbraco.Web.PropertyEditors ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, - IOptions contentSettings) - : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, attribute) + IOptions contentSettings, + IJsonSerializer jsonSerializer) + : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer, attribute) { _mediaFileSystem = mediaFileSystem ?? throw new ArgumentNullException(nameof(mediaFileSystem)); _contentSettings = contentSettings.Value ?? throw new ArgumentNullException(nameof(contentSettings)); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs index e6db6a4328..2bac76e6f9 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs @@ -10,6 +10,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Editors; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Security; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Web.Templates; @@ -47,8 +48,9 @@ namespace Umbraco.Web.PropertyEditors HtmlLocalLinkParser localLinkParser, IIOHelper ioHelper, IShortStringHelper shortStringHelper, - IImageUrlGenerator imageUrlGenerator) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + IImageUrlGenerator imageUrlGenerator, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { _backOfficeSecurityAccessor = backOfficeSecurityAccessor; _ioHelper = ioHelper; @@ -64,7 +66,7 @@ namespace Umbraco.Web.PropertyEditors /// Overridden to ensure that the value is validated /// /// - protected override IDataValueEditor CreateValueEditor() => new GridPropertyValueEditor(Attribute, _backOfficeSecurityAccessor, DataTypeService, LocalizationService, LocalizedTextService, _imageSourceParser, _pastedImages, _localLinkParser, ShortStringHelper, _imageUrlGenerator); + protected override IDataValueEditor CreateValueEditor() => new GridPropertyValueEditor(Attribute, _backOfficeSecurityAccessor, DataTypeService, LocalizationService, LocalizedTextService, _imageSourceParser, _pastedImages, _localLinkParser, ShortStringHelper, _imageUrlGenerator, JsonSerializer); protected override IConfigurationEditor CreateConfigurationEditor() => new GridConfigurationEditor(_ioHelper); @@ -87,14 +89,15 @@ namespace Umbraco.Web.PropertyEditors RichTextEditorPastedImages pastedImages, HtmlLocalLinkParser localLinkParser, IShortStringHelper shortStringHelper, - IImageUrlGenerator imageUrlGenerator) - : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, attribute) + IImageUrlGenerator imageUrlGenerator, + IJsonSerializer jsonSerializer) + : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer, attribute) { _backOfficeSecurityAccessor = backOfficeSecurityAccessor; _imageSourceParser = imageSourceParser; _pastedImages = pastedImages; - _richTextPropertyValueEditor = new RichTextPropertyEditor.RichTextPropertyValueEditor(attribute, backOfficeSecurityAccessor, dataTypeService, localizationService, localizedTextService, shortStringHelper, imageSourceParser, localLinkParser, pastedImages, imageUrlGenerator); - _mediaPickerPropertyValueEditor = new MediaPickerPropertyEditor.MediaPickerPropertyValueEditor(dataTypeService, localizationService, localizedTextService, shortStringHelper, attribute); + _richTextPropertyValueEditor = new RichTextPropertyEditor.RichTextPropertyValueEditor(attribute, backOfficeSecurityAccessor, dataTypeService, localizationService, localizedTextService, shortStringHelper, imageSourceParser, localLinkParser, pastedImages, imageUrlGenerator, jsonSerializer); + _mediaPickerPropertyValueEditor = new MediaPickerPropertyEditor.MediaPickerPropertyValueEditor(dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer, attribute); _imageUrlGenerator = imageUrlGenerator; } diff --git a/src/Umbraco.Core/PropertyEditors/ImageCropperConfiguration.cs b/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperConfiguration.cs similarity index 100% rename from src/Umbraco.Core/PropertyEditors/ImageCropperConfiguration.cs rename to src/Umbraco.Infrastructure/PropertyEditors/ImageCropperConfiguration.cs diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs index 3434ee5bcb..1f35b9d88a 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs @@ -1,17 +1,17 @@ using System; using System.Collections.Generic; using System.Linq; -using Microsoft.Extensions.Options; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; -using Umbraco.Core.Media; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Web.Media; @@ -50,8 +50,9 @@ namespace Umbraco.Web.PropertyEditors IIOHelper ioHelper, IShortStringHelper shortStringHelper, ILocalizedTextService localizedTextService, - UploadAutoFillProperties uploadAutoFillProperties) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + UploadAutoFillProperties uploadAutoFillProperties, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { _mediaFileSystem = mediaFileSystem ?? throw new ArgumentNullException(nameof(mediaFileSystem)); _contentSettings = contentSettings.Value ?? throw new ArgumentNullException(nameof(contentSettings)); @@ -76,7 +77,7 @@ namespace Umbraco.Web.PropertyEditors /// Creates the corresponding property value editor. /// /// The corresponding property value editor. - protected override IDataValueEditor CreateValueEditor() => new ImageCropperPropertyValueEditor(Attribute, LoggerFactory.CreateLogger(), _mediaFileSystem, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, _contentSettings); + protected override IDataValueEditor CreateValueEditor() => new ImageCropperPropertyValueEditor(Attribute, LoggerFactory.CreateLogger(), _mediaFileSystem, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, _contentSettings, JsonSerializer); /// /// Creates the corresponding preValue editor. diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyValueEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyValueEditor.cs index 6a1f3072d4..c058856ebd 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyValueEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyValueEditor.cs @@ -9,6 +9,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Editors; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.ValueConverters; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; using File = System.IO.File; @@ -32,8 +33,9 @@ namespace Umbraco.Web.PropertyEditors ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, - ContentSettings contentSettings) - : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, attribute) + ContentSettings contentSettings, + IJsonSerializer jsonSerializer) + : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer, attribute) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _mediaFileSystem = mediaFileSystem ?? throw new ArgumentNullException(nameof(mediaFileSystem)); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/LabelPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/LabelPropertyEditor.cs index 639a9c928d..78c5087c66 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/LabelPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/LabelPropertyEditor.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Logging; using Umbraco.Core.IO; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -21,14 +22,14 @@ namespace Umbraco.Core.PropertyEditors /// /// Initializes a new instance of the class. /// - public LabelPropertyEditor(ILoggerFactory loggerFactory, IIOHelper ioHelper, IDataTypeService dataTypeService, ILocalizedTextService localizedTextService, ILocalizationService localizationService, IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + public LabelPropertyEditor(ILoggerFactory loggerFactory, IIOHelper ioHelper, IDataTypeService dataTypeService, ILocalizedTextService localizedTextService, ILocalizationService localizationService, IShortStringHelper shortStringHelper, IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { _ioHelper = ioHelper; } /// - protected override IDataValueEditor CreateValueEditor() => new LabelPropertyValueEditor(DataTypeService, LocalizationService,LocalizedTextService, ShortStringHelper, Attribute); + protected override IDataValueEditor CreateValueEditor() => new LabelPropertyValueEditor(DataTypeService, LocalizationService,LocalizedTextService, ShortStringHelper, Attribute, JsonSerializer); /// protected override IConfigurationEditor CreateConfigurationEditor() => new LabelConfigurationEditor(_ioHelper); @@ -36,8 +37,8 @@ namespace Umbraco.Core.PropertyEditors // provides the property value editor internal class LabelPropertyValueEditor : DataValueEditor { - public LabelPropertyValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, DataEditorAttribute attribute) - : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, attribute) + public LabelPropertyValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, DataEditorAttribute attribute, IJsonSerializer jsonSerializer) + : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer, attribute) { } /// diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ListViewPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/ListViewPropertyEditor.cs index e01258eb80..d7fd2d9340 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ListViewPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ListViewPropertyEditor.cs @@ -2,6 +2,7 @@ using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -24,15 +25,21 @@ namespace Umbraco.Web.PropertyEditors /// /// Initializes a new instance of the class. /// - /// public ListViewPropertyEditor( ILoggerFactory loggerFactory, IIOHelper iioHelper, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, - IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base( + loggerFactory, + dataTypeService, + localizationService, + localizedTextService, + shortStringHelper, + jsonSerializer) { _iioHelper = iioHelper; } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MarkdownPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/MarkdownPropertyEditor.cs index ab4e6f3d97..97386de326 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MarkdownPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/MarkdownPropertyEditor.cs @@ -2,6 +2,7 @@ using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -30,8 +31,9 @@ namespace Umbraco.Web.PropertyEditors IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, - IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { _ioHelper = ioHelper; } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MediaPickerPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/MediaPickerPropertyEditor.cs index 476674b1ff..e69ff5be9d 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MediaPickerPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/MediaPickerPropertyEditor.cs @@ -4,6 +4,7 @@ using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.Models.Editors; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -33,8 +34,9 @@ namespace Umbraco.Web.PropertyEditors ILocalizationService localizationService, IIOHelper ioHelper, IShortStringHelper shortStringHelper, - ILocalizedTextService localizedTextService) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + ILocalizedTextService localizedTextService, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { _ioHelper = ioHelper; } @@ -42,12 +44,18 @@ namespace Umbraco.Web.PropertyEditors /// protected override IConfigurationEditor CreateConfigurationEditor() => new MediaPickerConfigurationEditor(_ioHelper); - protected override IDataValueEditor CreateValueEditor() => new MediaPickerPropertyValueEditor(DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, Attribute); + protected override IDataValueEditor CreateValueEditor() => new MediaPickerPropertyValueEditor(DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, JsonSerializer, Attribute); public class MediaPickerPropertyValueEditor : DataValueEditor, IDataValueReference { - public MediaPickerPropertyValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, DataEditorAttribute attribute) - : base(dataTypeService,localizationService, localizedTextService, shortStringHelper,attribute) + public MediaPickerPropertyValueEditor( + IDataTypeService dataTypeService, + ILocalizationService localizationService, + ILocalizedTextService localizedTextService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer, + DataEditorAttribute attribute) + : base(dataTypeService,localizationService, localizedTextService, shortStringHelper, jsonSerializer, attribute) { } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs index fc80aabdd9..b7ec4813b2 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs @@ -4,6 +4,7 @@ using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.Models.Editors; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -20,20 +21,33 @@ namespace Umbraco.Web.PropertyEditors { private readonly IIOHelper _ioHelper; - public MultiNodeTreePickerPropertyEditor(ILoggerFactory loggerFactory, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IIOHelper ioHelper, IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + public MultiNodeTreePickerPropertyEditor( + ILoggerFactory loggerFactory, + IDataTypeService dataTypeService, + ILocalizationService localizationService, + ILocalizedTextService localizedTextService, + IIOHelper ioHelper, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { _ioHelper = ioHelper; } protected override IConfigurationEditor CreateConfigurationEditor() => new MultiNodePickerConfigurationEditor(_ioHelper); - protected override IDataValueEditor CreateValueEditor() => new MultiNodeTreePickerPropertyValueEditor(DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, Attribute); + protected override IDataValueEditor CreateValueEditor() => new MultiNodeTreePickerPropertyValueEditor(DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, JsonSerializer, Attribute); public class MultiNodeTreePickerPropertyValueEditor : DataValueEditor, IDataValueReference { - public MultiNodeTreePickerPropertyValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, DataEditorAttribute attribute) - : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, attribute) + public MultiNodeTreePickerPropertyValueEditor( + IDataTypeService dataTypeService, + ILocalizationService localizationService, + ILocalizedTextService localizedTextService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer, + DataEditorAttribute attribute) + : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer, attribute) { } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerPropertyEditor.cs index afd749eed3..fdb908e2be 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerPropertyEditor.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.Logging; using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Web.PublishedCache; @@ -26,8 +27,19 @@ namespace Umbraco.Web.PropertyEditors private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly IPublishedUrlProvider _publishedUrlProvider; - public MultiUrlPickerPropertyEditor(ILoggerFactory loggerFactory, Lazy entityService, IPublishedSnapshotAccessor publishedSnapshotAccessor, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IIOHelper ioHelper, IShortStringHelper shortStringHelper, IUmbracoContextAccessor umbracoContextAccessor, IPublishedUrlProvider publishedUrlProvider) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, EditorType.PropertyValue) + public MultiUrlPickerPropertyEditor( + ILoggerFactory loggerFactory, + Lazy entityService, + IPublishedSnapshotAccessor publishedSnapshotAccessor, + IDataTypeService dataTypeService, + ILocalizationService localizationService, + ILocalizedTextService localizedTextService, + IIOHelper ioHelper, + IShortStringHelper shortStringHelper, + IUmbracoContextAccessor umbracoContextAccessor, + IPublishedUrlProvider publishedUrlProvider, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer, EditorType.PropertyValue) { _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); _publishedSnapshotAccessor = publishedSnapshotAccessor ?? throw new ArgumentNullException(nameof(publishedSnapshotAccessor)); @@ -38,6 +50,6 @@ namespace Umbraco.Web.PropertyEditors protected override IConfigurationEditor CreateConfigurationEditor() => new MultiUrlPickerConfigurationEditor(_ioHelper); - protected override IDataValueEditor CreateValueEditor() => new MultiUrlPickerValueEditor(_entityService.Value, _publishedSnapshotAccessor, LoggerFactory.CreateLogger(), DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, Attribute, _umbracoContextAccessor, _publishedUrlProvider); + protected override IDataValueEditor CreateValueEditor() => new MultiUrlPickerValueEditor(_entityService.Value, _publishedSnapshotAccessor, LoggerFactory.CreateLogger(), DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, Attribute, _umbracoContextAccessor, _publishedUrlProvider, JsonSerializer); } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerValueEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerValueEditor.cs index 380408c2b1..a4427cd26d 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerValueEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerValueEditor.cs @@ -1,14 +1,15 @@ -using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using Microsoft.Extensions.Logging; +using Newtonsoft.Json; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Editors; using Umbraco.Core.Models.Entities; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Web.Models.ContentEditing; @@ -25,8 +26,19 @@ namespace Umbraco.Web.PropertyEditors private readonly IPublishedUrlProvider _publishedUrlProvider; private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor; - public MultiUrlPickerValueEditor(IEntityService entityService, IPublishedSnapshotAccessor publishedSnapshotAccessor, ILogger logger, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, DataEditorAttribute attribute, IUmbracoContextAccessor umbracoContextAccessor, IPublishedUrlProvider publishedUrlProvider) - : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, attribute) + public MultiUrlPickerValueEditor( + IEntityService entityService, + IPublishedSnapshotAccessor publishedSnapshotAccessor, + ILogger logger, + IDataTypeService dataTypeService, + ILocalizationService localizationService, + ILocalizedTextService localizedTextService, + IShortStringHelper shortStringHelper, + DataEditorAttribute attribute, + IUmbracoContextAccessor umbracoContextAccessor, + IPublishedUrlProvider publishedUrlProvider, + IJsonSerializer jsonSerializer) + : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer, attribute) { _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); _publishedSnapshotAccessor = publishedSnapshotAccessor ?? throw new ArgumentNullException(nameof(publishedSnapshotAccessor)); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MultipleTextStringPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/MultipleTextStringPropertyEditor.cs index b4e1287315..c9aeb0e59a 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MultipleTextStringPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/MultipleTextStringPropertyEditor.cs @@ -11,6 +11,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Editors; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.Validators; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -36,8 +37,15 @@ namespace Umbraco.Web.PropertyEditors /// /// Initializes a new instance of the class. /// - public MultipleTextStringPropertyEditor(ILoggerFactory loggerFactory, IIOHelper ioHelper, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + public MultipleTextStringPropertyEditor( + ILoggerFactory loggerFactory, + IIOHelper ioHelper, + IDataTypeService dataTypeService, + ILocalizationService localizationService, + ILocalizedTextService localizedTextService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { _ioHelper = ioHelper; _dataTypeService = dataTypeService; @@ -46,7 +54,7 @@ namespace Umbraco.Web.PropertyEditors } /// - protected override IDataValueEditor CreateValueEditor() => new MultipleTextStringPropertyValueEditor(_dataTypeService, _localizationService, _localizedTextService, ShortStringHelper, Attribute); + protected override IDataValueEditor CreateValueEditor() => new MultipleTextStringPropertyValueEditor(_dataTypeService, _localizationService, _localizedTextService, ShortStringHelper, JsonSerializer, Attribute); /// protected override IConfigurationEditor CreateConfigurationEditor() => new MultipleTextStringConfigurationEditor(_ioHelper); @@ -58,8 +66,14 @@ namespace Umbraco.Web.PropertyEditors { private readonly ILocalizedTextService _localizedTextService; - public MultipleTextStringPropertyValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, DataEditorAttribute attribute) - : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, attribute) + public MultipleTextStringPropertyValueEditor( + IDataTypeService dataTypeService, + ILocalizationService localizationService, + ILocalizedTextService localizedTextService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer, + DataEditorAttribute attribute) + : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer, attribute) { _localizedTextService = localizedTextService; } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MultipleValueEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/MultipleValueEditor.cs index a960ac51ad..5f82ed940f 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MultipleValueEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/MultipleValueEditor.cs @@ -5,6 +5,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -20,8 +21,16 @@ namespace Umbraco.Web.PropertyEditors { private readonly ILogger _logger; - public MultipleValueEditor(ILogger logger, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, DataEditorAttribute attribute) - : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, attribute) + public MultipleValueEditor( + ILogger logger, + IDataTypeService dataTypeService, + ILocalizationService localizationService, + ILocalizedTextService localizedTextService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer, + DataEditorAttribute attribute + ) + : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer, attribute) { _logger = logger; } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyEditor.cs index 98f8771699..8afc08c423 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyEditor.cs @@ -9,6 +9,7 @@ using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.Models.Editors; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -42,8 +43,9 @@ namespace Umbraco.Web.PropertyEditors IContentTypeService contentTypeService, IIOHelper ioHelper, IShortStringHelper shortStringHelper, - ILocalizedTextService localizedTextService) - : base (loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + ILocalizedTextService localizedTextService, + IJsonSerializer jsonSerializer) + : base (loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { _propertyEditors = propertyEditors; _contentTypeService = contentTypeService; @@ -62,7 +64,7 @@ namespace Umbraco.Web.PropertyEditors #region Value Editor - protected override IDataValueEditor CreateValueEditor() => new NestedContentPropertyValueEditor(DataTypeService, LocalizationService, LocalizedTextService, _contentTypeService, ShortStringHelper, Attribute, PropertyEditors, LoggerFactory.CreateLogger()); + protected override IDataValueEditor CreateValueEditor() => new NestedContentPropertyValueEditor(DataTypeService, LocalizationService, LocalizedTextService, _contentTypeService, ShortStringHelper, Attribute, PropertyEditors, LoggerFactory.CreateLogger(), JsonSerializer); internal class NestedContentPropertyValueEditor : DataValueEditor, IDataValueReference { @@ -82,8 +84,9 @@ namespace Umbraco.Web.PropertyEditors IShortStringHelper shortStringHelper, DataEditorAttribute attribute, PropertyEditorCollection propertyEditors, - ILogger logger) - : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, attribute) + ILogger logger, + IJsonSerializer jsonSerializer) + : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer, attribute) { _propertyEditors = propertyEditors; _contentTypeService = contentTypeService; diff --git a/src/Umbraco.Infrastructure/PropertyEditors/RadioButtonsPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/RadioButtonsPropertyEditor.cs index 6a863b1dd1..444e99bd23 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/RadioButtonsPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/RadioButtonsPropertyEditor.cs @@ -2,6 +2,7 @@ using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -30,8 +31,9 @@ namespace Umbraco.Web.PropertyEditors IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, - IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService,localizedTextService, shortStringHelper) + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService,localizedTextService, shortStringHelper, jsonSerializer) { _ioHelper = ioHelper; } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/RichTextPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/RichTextPropertyEditor.cs index 049f020db4..e97b8c0520 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/RichTextPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/RichTextPropertyEditor.cs @@ -8,6 +8,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Editors; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Security; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Examine; @@ -50,8 +51,9 @@ namespace Umbraco.Web.PropertyEditors IShortStringHelper shortStringHelper, IIOHelper ioHelper, ILocalizedTextService localizedTextService, - IImageUrlGenerator imageUrlGenerator) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + IImageUrlGenerator imageUrlGenerator, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { _backOfficeSecurityAccessor = backOfficeSecurityAccessor; _imageSourceParser = imageSourceParser; @@ -65,7 +67,7 @@ namespace Umbraco.Web.PropertyEditors /// Create a custom value editor /// /// - protected override IDataValueEditor CreateValueEditor() => new RichTextPropertyValueEditor(Attribute, _backOfficeSecurityAccessor, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, _imageSourceParser, _localLinkParser, _pastedImages, _imageUrlGenerator); + protected override IDataValueEditor CreateValueEditor() => new RichTextPropertyValueEditor(Attribute, _backOfficeSecurityAccessor, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, _imageSourceParser, _localLinkParser, _pastedImages, _imageUrlGenerator, JsonSerializer); protected override IConfigurationEditor CreateConfigurationEditor() => new RichTextConfigurationEditor(_ioHelper); @@ -92,8 +94,9 @@ namespace Umbraco.Web.PropertyEditors HtmlImageSourceParser imageSourceParser, HtmlLocalLinkParser localLinkParser, RichTextEditorPastedImages pastedImages, - IImageUrlGenerator imageUrlGenerator) - : base(dataTypeService, localizationService,localizedTextService, shortStringHelper, attribute) + IImageUrlGenerator imageUrlGenerator, + IJsonSerializer jsonSerializer) + : base(dataTypeService, localizationService,localizedTextService, shortStringHelper, jsonSerializer, attribute) { _backOfficeSecurityAccessor = backOfficeSecurityAccessor; _imageSourceParser = imageSourceParser; diff --git a/src/Umbraco.Infrastructure/PropertyEditors/SliderPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/SliderPropertyEditor.cs index bb62c3461d..48197691a2 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/SliderPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/SliderPropertyEditor.cs @@ -2,6 +2,7 @@ using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -28,8 +29,9 @@ namespace Umbraco.Web.PropertyEditors IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, - IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { _ioHelper = ioHelper; } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/TagsPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/TagsPropertyEditor.cs index 708f4d8c9f..a2fb340d14 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/TagsPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/TagsPropertyEditor.cs @@ -8,6 +8,7 @@ using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.Models.Editors; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -34,21 +35,22 @@ namespace Umbraco.Web.PropertyEditors IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, - IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { _validators = validators; _ioHelper = ioHelper; } - protected override IDataValueEditor CreateValueEditor() => new TagPropertyValueEditor(DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, Attribute); + protected override IDataValueEditor CreateValueEditor() => new TagPropertyValueEditor(DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, JsonSerializer, Attribute); protected override IConfigurationEditor CreateConfigurationEditor() => new TagConfigurationEditor(_validators, _ioHelper, LocalizedTextService); internal class TagPropertyValueEditor : DataValueEditor { - public TagPropertyValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, DataEditorAttribute attribute) - : base(dataTypeService, localizationService,localizedTextService, shortStringHelper, attribute) + public TagPropertyValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, IJsonSerializer jsonSerializer, DataEditorAttribute attribute) + : base(dataTypeService, localizationService,localizedTextService, shortStringHelper, jsonSerializer, attribute) { } /// diff --git a/src/Umbraco.Infrastructure/PropertyEditors/TextAreaPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/TextAreaPropertyEditor.cs index 8d173e58bc..d65f6f3a1d 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/TextAreaPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/TextAreaPropertyEditor.cs @@ -2,6 +2,7 @@ using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -28,8 +29,15 @@ namespace Umbraco.Web.PropertyEditors /// /// Initializes a new instance of the class. /// - public TextAreaPropertyEditor(ILoggerFactory loggerFactory, IDataTypeService dataTypeService, ILocalizationService localizationService, IIOHelper ioHelper, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService,shortStringHelper) + public TextAreaPropertyEditor( + ILoggerFactory loggerFactory, + IDataTypeService dataTypeService, + ILocalizationService localizationService, + IIOHelper ioHelper, + ILocalizedTextService localizedTextService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { _dataTypeService = dataTypeService; _localizationService = localizationService; @@ -39,7 +47,7 @@ namespace Umbraco.Web.PropertyEditors } /// - protected override IDataValueEditor CreateValueEditor() => new TextOnlyValueEditor(_dataTypeService, _localizationService, Attribute, _localizedTextService, _shortStringHelper); + protected override IDataValueEditor CreateValueEditor() => new TextOnlyValueEditor(_dataTypeService, _localizationService, Attribute, _localizedTextService, _shortStringHelper, JsonSerializer); /// protected override IConfigurationEditor CreateConfigurationEditor() => new TextAreaConfigurationEditor(_ioHelper); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/TextboxPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/TextboxPropertyEditor.cs index 1ec87abe9b..350dd4a1ff 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/TextboxPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/TextboxPropertyEditor.cs @@ -2,6 +2,7 @@ using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -27,8 +28,15 @@ namespace Umbraco.Web.PropertyEditors /// /// Initializes a new instance of the class. /// - public TextboxPropertyEditor(ILoggerFactory loggerFactory, IDataTypeService dataTypeService, ILocalizationService localizationService, IIOHelper ioHelper, IShortStringHelper shortStringHelper, ILocalizedTextService localizedTextService) - : base(loggerFactory, dataTypeService, localizationService,localizedTextService, shortStringHelper) + public TextboxPropertyEditor( + ILoggerFactory loggerFactory, + IDataTypeService dataTypeService, + ILocalizationService localizationService, + IIOHelper ioHelper, + IShortStringHelper shortStringHelper, + ILocalizedTextService localizedTextService, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService,localizedTextService, shortStringHelper, jsonSerializer) { _dataTypeService = dataTypeService; _localizationService = localizationService; @@ -38,7 +46,7 @@ namespace Umbraco.Web.PropertyEditors } /// - protected override IDataValueEditor CreateValueEditor() => new TextOnlyValueEditor(_dataTypeService, _localizationService, Attribute, _localizedTextService, _shortStringHelper); + protected override IDataValueEditor CreateValueEditor() => new TextOnlyValueEditor(DataTypeService, LocalizationService, Attribute, LocalizedTextService, ShortStringHelper, JsonSerializer); /// protected override IConfigurationEditor CreateConfigurationEditor() => new TextboxConfigurationEditor(_ioHelper); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/TrueFalsePropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/TrueFalsePropertyEditor.cs index db72887fff..3c9599c643 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/TrueFalsePropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/TrueFalsePropertyEditor.cs @@ -2,6 +2,7 @@ using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -25,8 +26,15 @@ namespace Umbraco.Web.PropertyEditors /// /// Initializes a new instance of the class. /// - public TrueFalsePropertyEditor(ILoggerFactory loggerFactory, IDataTypeService dataTypeService, ILocalizationService localizationService, IIOHelper ioHelper, IShortStringHelper shortStringHelper, ILocalizedTextService localizedTextService) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + public TrueFalsePropertyEditor( + ILoggerFactory loggerFactory, + IDataTypeService dataTypeService, + ILocalizationService localizationService, + IIOHelper ioHelper, + IShortStringHelper shortStringHelper, + ILocalizedTextService localizedTextService, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { _ioHelper = ioHelper; } diff --git a/src/Umbraco.Infrastructure/Services/Implement/DataTypeService.cs b/src/Umbraco.Infrastructure/Services/Implement/DataTypeService.cs index eb6a94c4ee..042128558b 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/DataTypeService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/DataTypeService.cs @@ -6,11 +6,11 @@ using Umbraco.Core.Events; using Umbraco.Core.Exceptions; using Umbraco.Core.IO; using Umbraco.Core.Models; -using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; +using Umbraco.Core.Serialization; using Umbraco.Core.Strings; namespace Umbraco.Core.Services.Implement @@ -29,11 +29,14 @@ namespace Umbraco.Core.Services.Implement private readonly ILocalizedTextService _localizedTextService; private readonly ILocalizationService _localizationService; private readonly IShortStringHelper _shortStringHelper; + private readonly IJsonSerializer _jsonSerializer; public DataTypeService(IScopeProvider provider, ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, IDataTypeRepository dataTypeRepository, IDataTypeContainerRepository dataTypeContainerRepository, IAuditRepository auditRepository, IEntityRepository entityRepository, IContentTypeRepository contentTypeRepository, - IIOHelper ioHelper, ILocalizedTextService localizedTextService, ILocalizationService localizationService, IShortStringHelper shortStringHelper) + IIOHelper ioHelper, ILocalizedTextService localizedTextService, ILocalizationService localizationService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) : base(provider, loggerFactory, eventMessagesFactory) { _dataTypeRepository = dataTypeRepository; @@ -45,6 +48,7 @@ namespace Umbraco.Core.Services.Implement _localizedTextService = localizedTextService; _localizationService = localizationService; _shortStringHelper = shortStringHelper; + _jsonSerializer = jsonSerializer; } #region Containers @@ -324,7 +328,7 @@ namespace Umbraco.Core.Services.Implement .Where(x => x.Editor is MissingPropertyEditor); foreach (var dataType in dataTypesWithMissingEditors) { - dataType.Editor = new LabelPropertyEditor(LoggerFactory, _ioHelper, this, _localizedTextService, _localizationService, _shortStringHelper); + dataType.Editor = new LabelPropertyEditor(LoggerFactory, _ioHelper, this, _localizedTextService, _localizationService, _shortStringHelper, _jsonSerializer); } } diff --git a/src/Umbraco.Tests.Common/Builders/DataEditorBuilder.cs b/src/Umbraco.Tests.Common/Builders/DataEditorBuilder.cs index f7185d1620..4cc7b3ad8e 100644 --- a/src/Umbraco.Tests.Common/Builders/DataEditorBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/DataEditorBuilder.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using Microsoft.Extensions.Logging.Abstractions; using Moq; -using Umbraco.Core.Logging; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -43,7 +43,8 @@ namespace Umbraco.Tests.Common.Builders Mock.Of(), Mock.Of(), Mock.Of(), - Mock.Of() + Mock.Of(), + Mock.Of() ) { DefaultConfiguration = defaultConfiguration, diff --git a/src/Umbraco.Tests.Common/Builders/DataValueEditorBuilder.cs b/src/Umbraco.Tests.Common/Builders/DataValueEditorBuilder.cs index ecc2649c02..bd6966bbeb 100644 --- a/src/Umbraco.Tests.Common/Builders/DataValueEditorBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/DataValueEditorBuilder.cs @@ -1,6 +1,7 @@ using System; using Moq; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -52,7 +53,8 @@ namespace Umbraco.Tests.Common.Builders Mock.Of(), Mock.Of(), Mock.Of(), - Mock.Of() + Mock.Of(), + Mock.Of() ) { Configuration = configuration, diff --git a/src/Umbraco.Tests.Common/TestHelpers/MockedValueEditors.cs b/src/Umbraco.Tests.Common/TestHelpers/MockedValueEditors.cs index 78aa0c7bc6..b80a2996ca 100644 --- a/src/Umbraco.Tests.Common/TestHelpers/MockedValueEditors.cs +++ b/src/Umbraco.Tests.Common/TestHelpers/MockedValueEditors.cs @@ -1,5 +1,6 @@ using Moq; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -16,6 +17,7 @@ namespace Umbraco.Tests.TestHelpers.Entities Mock.Of(), Mock.Of(), Mock.Of(), + new JsonNetSerializer(), new DataEditorAttribute(name, name, name) { ValueType = valueType diff --git a/src/Umbraco.Tests.Common/TestHelpers/SolidPublishedSnapshot.cs b/src/Umbraco.Tests.Common/TestHelpers/SolidPublishedSnapshot.cs index 958b7e558b..e7f6cc4442 100644 --- a/src/Umbraco.Tests.Common/TestHelpers/SolidPublishedSnapshot.cs +++ b/src/Umbraco.Tests.Common/TestHelpers/SolidPublishedSnapshot.cs @@ -5,7 +5,6 @@ using Microsoft.Extensions.Logging; using Moq; using Umbraco.Core; using Umbraco.Core.Cache; -using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; @@ -412,11 +411,12 @@ namespace Umbraco.Tests.Common.PublishedContent static AutoPublishedContentType() { - var serializer = new ConfigurationEditorJsonSerializer(); + var configurationEditorJsonSerializer = new ConfigurationEditorJsonSerializer(); + var jsonSerializer = new JsonNetSerializer(); var dataTypeServiceMock = new Mock(); var dataType = new DataType(new VoidEditor(Mock.Of(), dataTypeServiceMock.Object, - Mock.Of(), Mock.Of(), Mock.Of()), serializer) + Mock.Of(), Mock.Of(), Mock.Of(), jsonSerializer), configurationEditorJsonSerializer) { Id = 666 }; dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield); diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs index ebfcd3e7de..c94b708ff9 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs @@ -3,11 +3,11 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories; -using Umbraco.Tests.Testing; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Tests.Integration.Testing; +using Umbraco.Tests.Testing; using Umbraco.Web.PropertyEditors; namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Persistence.Repositories @@ -23,15 +23,16 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Persistence.Repositor private IDataTypeContainerRepository DataTypeContainerRepository => GetRequiredService(); private IDataTypeRepository DataTypeRepository => GetRequiredService(); private IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer => GetRequiredService(); + private IJsonSerializer JsonSerializer => GetRequiredService(); [Test] public void Can_Find_Usages() { using (ScopeProvider.CreateScope()) { - IDataType dataType1 = new DataType(new RadioButtonsPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper), ConfigurationEditorJsonSerializer) { Name = "dt1" }; + IDataType dataType1 = new DataType(new RadioButtonsPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, JsonSerializer), ConfigurationEditorJsonSerializer) { Name = "dt1" }; DataTypeRepository.Save(dataType1); - IDataType dataType2 = new DataType(new RadioButtonsPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper), ConfigurationEditorJsonSerializer) { Name = "dt2" }; + IDataType dataType2 = new DataType(new RadioButtonsPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, JsonSerializer), ConfigurationEditorJsonSerializer) { Name = "dt2" }; DataTypeRepository.Save(dataType2); IContentType ct = new ContentType(ShortStringHelper, -1) @@ -94,14 +95,14 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Persistence.Repositor var container2 = new EntityContainer(Constants.ObjectTypes.DataType) { Name = "blah2", ParentId = container1.Id }; DataTypeContainerRepository.Save(container2); - var dataType = (IDataType) new DataType(new RadioButtonsPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper), ConfigurationEditorJsonSerializer, container2.Id) + var dataType = (IDataType) new DataType(new RadioButtonsPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, JsonSerializer), ConfigurationEditorJsonSerializer, container2.Id) { Name = "dt1" }; DataTypeRepository.Save(dataType); //create a - var dataType2 = (IDataType)new DataType(new RadioButtonsPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper), ConfigurationEditorJsonSerializer, dataType.Id) + var dataType2 = (IDataType)new DataType(new RadioButtonsPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, JsonSerializer), ConfigurationEditorJsonSerializer, dataType.Id) { Name = "dt2" }; @@ -160,7 +161,7 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Persistence.Repositor var container = new EntityContainer(Constants.ObjectTypes.DataType) { Name = "blah" }; DataTypeContainerRepository.Save(container); - var dataTypeDefinition = new DataType(new RadioButtonsPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper), ConfigurationEditorJsonSerializer, container.Id) { Name = "test" }; + var dataTypeDefinition = new DataType(new RadioButtonsPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, JsonSerializer), ConfigurationEditorJsonSerializer, container.Id) { Name = "test" }; DataTypeRepository.Save(dataTypeDefinition); Assert.AreEqual(container.Id, dataTypeDefinition.ParentId); @@ -175,7 +176,7 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Persistence.Repositor var container = new EntityContainer(Constants.ObjectTypes.DataType) { Name = "blah" }; DataTypeContainerRepository.Save(container); - IDataType dataType = new DataType(new RadioButtonsPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper), ConfigurationEditorJsonSerializer, container.Id) { Name = "test" }; + IDataType dataType = new DataType(new RadioButtonsPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, JsonSerializer), ConfigurationEditorJsonSerializer, container.Id) { Name = "test" }; DataTypeRepository.Save(dataType); // Act @@ -195,7 +196,7 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Persistence.Repositor { using (ScopeProvider.CreateScope()) { - IDataType dataType = new DataType(new RadioButtonsPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper), ConfigurationEditorJsonSerializer) {Name = "test"}; + IDataType dataType = new DataType(new RadioButtonsPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, JsonSerializer), ConfigurationEditorJsonSerializer) {Name = "test"}; DataTypeRepository.Save(dataType); @@ -295,7 +296,7 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Persistence.Repositor { using (ScopeProvider.CreateScope()) { - var dataTypeDefinition = new DataType(new LabelPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizedTextService, LocalizationService, ShortStringHelper), ConfigurationEditorJsonSerializer) + var dataTypeDefinition = new DataType(new LabelPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizedTextService, LocalizationService, ShortStringHelper, JsonSerializer), ConfigurationEditorJsonSerializer) { DatabaseType = ValueStorageType.Integer, Name = "AgeDataType", @@ -330,7 +331,7 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Persistence.Repositor { using (ScopeProvider.CreateScope()) { - var dataTypeDefinition = new DataType(new IntegerPropertyEditor(LoggerFactory, DataTypeService, LocalizationService, ShortStringHelper, LocalizedTextService), ConfigurationEditorJsonSerializer) + var dataTypeDefinition = new DataType(new IntegerPropertyEditor(LoggerFactory, DataTypeService, LocalizationService, ShortStringHelper, LocalizedTextService, JsonSerializer), ConfigurationEditorJsonSerializer) { DatabaseType = ValueStorageType.Integer, Name = "AgeDataType", @@ -341,7 +342,7 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Persistence.Repositor // Act var definition = DataTypeRepository.Get(dataTypeDefinition.Id); definition.Name = "AgeDataType Updated"; - definition.Editor = new LabelPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizedTextService, LocalizationService, ShortStringHelper); //change + definition.Editor = new LabelPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizedTextService, LocalizationService, ShortStringHelper, JsonSerializer); //change DataTypeRepository.Save(definition); var definitionUpdated = DataTypeRepository.Get(dataTypeDefinition.Id); @@ -358,7 +359,7 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Persistence.Repositor { using (ScopeProvider.CreateScope()) { - var dataTypeDefinition = new DataType(new LabelPropertyEditor(LoggerFactory, IOHelper, DataTypeService,LocalizedTextService, LocalizationService, ShortStringHelper), ConfigurationEditorJsonSerializer) + var dataTypeDefinition = new DataType(new LabelPropertyEditor(LoggerFactory, IOHelper, DataTypeService,LocalizedTextService, LocalizationService, ShortStringHelper, JsonSerializer), ConfigurationEditorJsonSerializer) { DatabaseType = ValueStorageType.Integer, Name = "AgeDataType", diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/CachedDataTypeServiceTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/CachedDataTypeServiceTests.cs index 4dbc7b3efc..3c03be2a95 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/CachedDataTypeServiceTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/CachedDataTypeServiceTests.cs @@ -21,6 +21,7 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services private ILocalizedTextService LocalizedTextService => GetRequiredService(); private ILocalizationService LocalizationService => GetRequiredService(); private IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer => GetRequiredService(); + private IJsonSerializer JsonSerializer => GetRequiredService(); /// /// This tests validates that with the new scope changes that the underlying cache policies work - in this case it tests that the cache policy @@ -29,7 +30,7 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services [Test] public void DataTypeService_Can_Get_All() { - IDataType dataType = new DataType(new LabelPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizedTextService, LocalizationService, ShortStringHelper), ConfigurationEditorJsonSerializer) { Name = "Testing Textfield", DatabaseType = ValueStorageType.Ntext }; + IDataType dataType = new DataType(new LabelPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizedTextService, LocalizationService, ShortStringHelper, JsonSerializer), ConfigurationEditorJsonSerializer) { Name = "Testing Textfield", DatabaseType = ValueStorageType.Ntext }; DataTypeService.Save(dataType); //Get all the first time (no cache) diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/DataTypeServiceTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/DataTypeServiceTests.cs index 0af3ae6fb5..2de7fb6b2a 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/DataTypeServiceTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/DataTypeServiceTests.cs @@ -26,12 +26,13 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services private ILocalizedTextService LocalizedTextService => GetRequiredService(); private ILocalizationService LocalizationService => GetRequiredService(); private IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer => GetRequiredService(); + private IJsonSerializer JsonSerializer => GetRequiredService(); [Test] public void DataTypeService_Can_Persist_New_DataTypeDefinition() { // Act - IDataType dataType = new DataType(new LabelPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizedTextService, LocalizationService, ShortStringHelper), ConfigurationEditorJsonSerializer) { Name = "Testing Textfield", DatabaseType = ValueStorageType.Ntext }; + IDataType dataType = new DataType(new LabelPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizedTextService, LocalizationService, ShortStringHelper, JsonSerializer), ConfigurationEditorJsonSerializer) { Name = "Testing Textfield", DatabaseType = ValueStorageType.Ntext }; DataTypeService.Save(dataType); // Assert @@ -74,7 +75,7 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services public void Cannot_Save_DataType_With_Empty_Name() { // Act - var dataTypeDefinition = new DataType(new LabelPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizedTextService,LocalizationService, ShortStringHelper), ConfigurationEditorJsonSerializer) { Name = string.Empty, DatabaseType = ValueStorageType.Ntext }; + var dataTypeDefinition = new DataType(new LabelPropertyEditor(LoggerFactory, IOHelper, DataTypeService, LocalizedTextService,LocalizationService, ShortStringHelper, JsonSerializer), ConfigurationEditorJsonSerializer) { Name = string.Empty, DatabaseType = ValueStorageType.Ntext }; // Act & Assert Assert.Throws(() => DataTypeService.Save(dataTypeDefinition)); diff --git a/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs index 2960455a70..dc88455d68 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs @@ -13,7 +13,6 @@ using Umbraco.Core.IO; using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Security; using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -273,8 +272,8 @@ namespace Umbraco.Tests.Integration.Umbraco.Web.Backoffice.Filters public class ComplexTestEditor : NestedContentPropertyEditor { public ComplexTestEditor(ILoggerFactory loggerFactory, Lazy propertyEditors, IDataTypeService dataTypeService, IContentTypeService contentTypeService, ILocalizationService localizationService, - IIOHelper ioHelper, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper) - : base(loggerFactory, propertyEditors, dataTypeService, localizationService, contentTypeService, ioHelper, shortStringHelper, localizedTextService) + IIOHelper ioHelper, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, IJsonSerializer jsonSerializer) + : base(loggerFactory, propertyEditors, dataTypeService, localizationService, contentTypeService, ioHelper, shortStringHelper, localizedTextService, jsonSerializer) { } @@ -290,17 +289,19 @@ namespace Umbraco.Tests.Integration.Umbraco.Web.Backoffice.Filters [DataEditor("test", "test", "test")] // This alias aligns with the prop editor alias for all properties created from MockedContentTypes.CreateTextPageContentType public class TestEditor : DataEditor { - public TestEditor(ILoggerFactory loggerFactory, - IDataTypeService dataTypeService, - ILocalizationService localizationService, - ILocalizedTextService localizedTextService, - IShortStringHelper shortStringHelper) - : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) + public TestEditor( + ILoggerFactory loggerFactory, + IDataTypeService dataTypeService, + ILocalizationService localizationService, + ILocalizedTextService localizedTextService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer) { } - protected override IDataValueEditor CreateValueEditor() => new TestValueEditor(DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, Attribute); + protected override IDataValueEditor CreateValueEditor() => new TestValueEditor(DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, JsonSerializer, Attribute); private class TestValueEditor : DataValueEditor { @@ -309,8 +310,9 @@ namespace Umbraco.Tests.Integration.Umbraco.Web.Backoffice.Filters ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer, DataEditorAttribute attribute) - : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, attribute) + : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, jsonSerializer, attribute) { Validators.Add(new NeverValidateValidator()); } diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Models/VariationTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Models/VariationTests.cs index 81c868656e..cab26fd7d2 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Models/VariationTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Models/VariationTests.cs @@ -585,6 +585,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Models var localizedTextService = Mock.Of(); var localizationService = Mock.Of(); var shortStringHelper = Mock.Of(); + var jsonSerializer = Mock.Of(); var textBoxEditor = new TextboxPropertyEditor( NullLoggerFactory.Instance, @@ -592,7 +593,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Models localizationService, ioHelper, shortStringHelper, - localizedTextService + localizedTextService, + jsonSerializer ); var serializer = new ConfigurationEditorJsonSerializer(); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/ColorListValidatorTest.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/ColorListValidatorTest.cs index 14aa628f88..98820ccac9 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/ColorListValidatorTest.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/ColorListValidatorTest.cs @@ -2,13 +2,12 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Moq; -using NUnit.Framework; using Newtonsoft.Json.Linq; +using NUnit.Framework; using Umbraco.Core.IO; -using NUnit.Framework.Internal; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; -using Umbraco.Tests.TestHelpers; using Umbraco.Web.PropertyEditors; namespace Umbraco.Tests.UnitTests.Umbraco.Core.PropertyEditors @@ -22,7 +21,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.PropertyEditors public void Only_Tests_On_JArray() { var validator = new ColorPickerConfigurationEditor.ColorListValidator(); - var result = validator.Validate("hello", null, new ColorPickerPropertyEditor(_loggerFactory, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of())); + var result = validator.Validate("hello", null, new ColorPickerPropertyEditor(_loggerFactory, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer())); Assert.AreEqual(0, result.Count()); } @@ -30,7 +29,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.PropertyEditors public void Only_Tests_On_JArray_Of_Item_JObject() { var validator = new ColorPickerConfigurationEditor.ColorListValidator(); - var result = validator.Validate(new JArray("hello", "world"), null, new ColorPickerPropertyEditor(_loggerFactory, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of())); + var result = validator.Validate(new JArray("hello", "world"), null, new ColorPickerPropertyEditor(_loggerFactory, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer())); Assert.AreEqual(0, result.Count()); } @@ -43,7 +42,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.PropertyEditors JObject.FromObject(new { value = "zxcvzxcvxzcv" }), JObject.FromObject(new { value = "ABC" }), JObject.FromObject(new { value = "1234567" })), - null, new ColorPickerPropertyEditor(_loggerFactory, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of())); + null, new ColorPickerPropertyEditor(_loggerFactory, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer())); Assert.AreEqual(2, result.Count()); } } diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollectionTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollectionTests.cs index 0fa864ae06..3229c3652c 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollectionTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollectionTests.cs @@ -1,21 +1,19 @@ -using Moq; -using NUnit.Framework; -using System; +using System; using System.Collections.Generic; using System.Linq; using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.IO; -using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Editors; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; -using Umbraco.Tests.TestHelpers; using Umbraco.Web.PropertyEditors; using static Umbraco.Core.Models.Property; -using Umbraco.Core.Serialization; namespace Umbraco.Tests.UnitTests.Umbraco.Core.PropertyEditors { @@ -27,6 +25,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.PropertyEditors ILocalizedTextService LocalizedTextService { get; } = Mock.Of(); ILocalizationService LocalizationService { get; } = Mock.Of(); IShortStringHelper ShortStringHelper { get; } = Mock.Of(); + IJsonSerializer JsonSerializer { get; } = new JsonNetSerializer(); [Test] public void GetAllReferences_All_Variants_With_IDataValueReferenceFactory() @@ -41,7 +40,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.PropertyEditors DataTypeService, LocalizedTextService, LocalizationService, - ShortStringHelper + ShortStringHelper, + JsonSerializer ); var propertyEditors = new PropertyEditorCollection(new DataEditorCollection(labelEditor.Yield())); var trackedUdi1 = Udi.Create(Constants.UdiEntityType.Media, Guid.NewGuid()).ToString(); @@ -110,7 +110,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.PropertyEditors LocalizationService, IOHelper, ShortStringHelper, - LocalizedTextService + LocalizedTextService, + JsonSerializer ); var propertyEditors = new PropertyEditorCollection(new DataEditorCollection(mediaPicker.Yield())); var trackedUdi1 = Udi.Create(Constants.UdiEntityType.Media, Guid.NewGuid()).ToString(); @@ -179,7 +180,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.PropertyEditors LocalizationService, IOHelper, ShortStringHelper, - LocalizedTextService + LocalizedTextService, + JsonSerializer ); var propertyEditors = new PropertyEditorCollection(new DataEditorCollection(mediaPicker.Yield())); var trackedUdi1 = Udi.Create(Constants.UdiEntityType.Media, Guid.NewGuid()).ToString(); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/EnsureUniqueValuesValidatorTest.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/EnsureUniqueValuesValidatorTest.cs index 44c53382d9..2b81620b27 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/EnsureUniqueValuesValidatorTest.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/EnsureUniqueValuesValidatorTest.cs @@ -2,13 +2,12 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Moq; -using NUnit.Framework; using Newtonsoft.Json.Linq; +using NUnit.Framework; using Umbraco.Core.IO; -using Umbraco.Core.Logging; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; -using Umbraco.Tests.TestHelpers; using Umbraco.Web.PropertyEditors; namespace Umbraco.Tests.UnitTests.Umbraco.Core.PropertyEditors @@ -21,7 +20,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.PropertyEditors public void Only_Tests_On_JArray() { var validator = new ValueListUniqueValueValidator(); - var result = validator.Validate("hello", null, new ColorPickerPropertyEditor(_loggerFactory, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of())); + var result = validator.Validate("hello", null, new ColorPickerPropertyEditor(_loggerFactory, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer())); Assert.AreEqual(0, result.Count()); } @@ -29,7 +28,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.PropertyEditors public void Only_Tests_On_JArray_Of_Item_JObject() { var validator = new ValueListUniqueValueValidator(); - var result = validator.Validate(new JArray("hello", "world"), null, new ColorPickerPropertyEditor(_loggerFactory, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of())); + var result = validator.Validate(new JArray("hello", "world"), null, new ColorPickerPropertyEditor(_loggerFactory, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer())); Assert.AreEqual(0, result.Count()); } @@ -37,7 +36,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.PropertyEditors public void Allows_Unique_Values() { var validator = new ValueListUniqueValueValidator(); - var result = validator.Validate(new JArray(JObject.FromObject(new { value = "hello" }), JObject.FromObject(new { value = "world" })), null, new ColorPickerPropertyEditor(_loggerFactory, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of())); + var result = validator.Validate(new JArray(JObject.FromObject(new { value = "hello" }), JObject.FromObject(new { value = "world" })), null, new ColorPickerPropertyEditor(_loggerFactory, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer())); Assert.AreEqual(0, result.Count()); } @@ -46,7 +45,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.PropertyEditors { var validator = new ValueListUniqueValueValidator(); var result = validator.Validate(new JArray(JObject.FromObject(new { value = "hello" }), JObject.FromObject(new { value = "hello" })), - null, new ColorPickerPropertyEditor(_loggerFactory, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of())); + null, new ColorPickerPropertyEditor(_loggerFactory, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer())); Assert.AreEqual(1, result.Count()); } @@ -59,7 +58,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.PropertyEditors JObject.FromObject(new { value = "hello" }), JObject.FromObject(new { value = "world" }), JObject.FromObject(new { value = "world" })), - null, new ColorPickerPropertyEditor(_loggerFactory, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of())); + null, new ColorPickerPropertyEditor(_loggerFactory, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer())); Assert.AreEqual(2, result.Count()); } } diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/MultiValuePropertyEditorTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/MultiValuePropertyEditorTests.cs index 5b3e3f1ff6..2952ac032d 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/MultiValuePropertyEditorTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/MultiValuePropertyEditorTests.cs @@ -5,7 +5,6 @@ using Moq; using Newtonsoft.Json; using NUnit.Framework; using Umbraco.Core.IO; -using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Serialization; @@ -30,7 +29,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.PropertyEditors public void DropDownMultipleValueEditor_Format_Data_For_Cache() { var serializer = new ConfigurationEditorJsonSerializer(); - var dataType = new DataType(new CheckBoxListPropertyEditor(NullLoggerFactory.Instance, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()), serializer) + var dataType = new DataType(new CheckBoxListPropertyEditor(NullLoggerFactory.Instance, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer()), serializer) { Configuration = new ValueListConfiguration { @@ -63,7 +62,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.PropertyEditors public void DropDownValueEditor_Format_Data_For_Cache() { var serializer = new ConfigurationEditorJsonSerializer(); - var dataType = new DataType(new CheckBoxListPropertyEditor(NullLoggerFactory.Instance, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()), serializer) + var dataType = new DataType(new CheckBoxListPropertyEditor(NullLoggerFactory.Instance, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer()), serializer) { Configuration = new ValueListConfiguration { diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Published/ConvertersTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Published/ConvertersTests.cs index a46662c3a1..13c4ae071c 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Published/ConvertersTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Published/ConvertersTests.cs @@ -5,7 +5,6 @@ using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; @@ -33,7 +32,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Published var serializer = new ConfigurationEditorJsonSerializer(); var dataTypeServiceMock = new Mock(); var dataType = new DataType(new VoidEditor(Mock.Of(), dataTypeServiceMock.Object, - Mock.Of(), Mock.Of(), Mock.Of()), serializer) + Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer()), serializer) { Id = 1 }; dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield); @@ -117,7 +116,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Published var serializer = new ConfigurationEditorJsonSerializer(); var dataTypeServiceMock = new Mock(); var dataType = new DataType(new VoidEditor(Mock.Of(), dataTypeServiceMock.Object, - Mock.Of(), Mock.Of(), Mock.Of()), serializer) + Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer()), serializer) { Id = 1 }; dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Published/NestedContentTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Published/NestedContentTests.cs index 67c294f5a9..7493d59d72 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Published/NestedContentTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Published/NestedContentTests.cs @@ -34,7 +34,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Published var localizationService = Mock.Of(); PropertyEditorCollection editors = null; - var editor = new NestedContentPropertyEditor(loggerFactory, new Lazy(() => editors), Mock.Of(),localizationService, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()); + var editor = new NestedContentPropertyEditor(loggerFactory, new Lazy(() => editors), Mock.Of(),localizationService, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer()); editors = new PropertyEditorCollection(new DataEditorCollection(new DataEditor[] { editor })); var serializer = new ConfigurationEditorJsonSerializer(); @@ -67,7 +67,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Published } }; - var dataType3 = new DataType(new TextboxPropertyEditor(loggerFactory, Mock.Of(), localizationService, Mock.Of(), Mock.Of(), Mock.Of()), serializer) + var dataType3 = new DataType(new TextboxPropertyEditor(loggerFactory, Mock.Of(), localizationService, Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer()), serializer) { Id = 3 }; diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Published/PropertyCacheLevelTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Published/PropertyCacheLevelTests.cs index b412ab1153..163020b6f6 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Published/PropertyCacheLevelTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Published/PropertyCacheLevelTests.cs @@ -5,7 +5,6 @@ using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; -using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; @@ -32,10 +31,11 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Published converter, }); - var serializer = new ConfigurationEditorJsonSerializer(); + var configurationEditorJsonSerializer = new ConfigurationEditorJsonSerializer(); + var jsonSerializer = new JsonNetSerializer(); var dataTypeServiceMock = new Mock(); var dataType = new DataType(new VoidEditor(NullLoggerFactory.Instance, dataTypeServiceMock.Object, - Mock.Of(), Mock.Of(), Mock.Of()), serializer) + Mock.Of(), Mock.Of(), Mock.Of(), jsonSerializer), configurationEditorJsonSerializer) { Id = 1 }; dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield); @@ -118,10 +118,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Published converter, }); - var serializer = new ConfigurationEditorJsonSerializer(); var dataTypeServiceMock = new Mock(); var dataType = new DataType(new VoidEditor(NullLoggerFactory.Instance, dataTypeServiceMock.Object, - Mock.Of(), Mock.Of(), Mock.Of()), serializer) + Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer()), new ConfigurationEditorJsonSerializer()) { Id = 1 }; dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield); @@ -199,10 +198,16 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Published converter, }); - var serializer = new ConfigurationEditorJsonSerializer(); var dataTypeServiceMock = new Mock(); - var dataType = new DataType(new VoidEditor(NullLoggerFactory.Instance, dataTypeServiceMock.Object, - Mock.Of(), Mock.Of(), Mock.Of()), serializer) + var dataType = new DataType( + new VoidEditor( + NullLoggerFactory.Instance, + dataTypeServiceMock.Object, + Mock.Of(), + Mock.Of(), + Mock.Of(), + new JsonNetSerializer()), + new ConfigurationEditorJsonSerializer()) { Id = 1 }; dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Persistence/Querying/ExpressionTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Persistence/Querying/ExpressionTests.cs index 436c202398..5d90d85f81 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Persistence/Querying/ExpressionTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Persistence/Querying/ExpressionTests.cs @@ -1,21 +1,21 @@ using System; using System.Diagnostics; +using System.Linq; using System.Linq.Expressions; +using Microsoft.Extensions.Logging.Abstractions; using Moq; using NUnit.Framework; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.SqlSyntax; -using Umbraco.Tests.TestHelpers; -using System.Linq; -using Microsoft.Extensions.Logging.Abstractions; -using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; +using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Persistence.Querying { @@ -25,8 +25,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Persistence.Querying [Test] public void Equals_Claus_With_Two_Entity_Values() { - var serializer = new ConfigurationEditorJsonSerializer(); - var dataType = new DataType(new VoidEditor(NullLoggerFactory.Instance, Mock.Of(), Mock.Of(),Mock.Of(), Mock.Of()), serializer) + + var dataType = new DataType(new VoidEditor(NullLoggerFactory.Instance, Mock.Of(), Mock.Of(),Mock.Of(), Mock.Of(), new JsonNetSerializer()), new ConfigurationEditorJsonSerializer()) { Id = 12345 }; diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Services/PropertyValidationServiceTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Services/PropertyValidationServiceTests.cs index 3acfce1781..abc1bb0c9d 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Services/PropertyValidationServiceTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Services/PropertyValidationServiceTests.cs @@ -5,6 +5,7 @@ using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.Validators; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Web.PropertyEditors; @@ -34,7 +35,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Services x => x.Type == EditorType.PropertyValue && x.Alias == Constants.PropertyEditors.Aliases.TextBox); Mock.Get(dataEditor).Setup(x => x.GetValueEditor(It.IsAny())) - .Returns(new CustomTextOnlyValueEditor(Mock.Of(), Mock.Of(), new DataEditorAttribute(Constants.PropertyEditors.Aliases.TextBox, "Test Textbox", "textbox"), textService.Object, Mock.Of())); + .Returns(new CustomTextOnlyValueEditor(Mock.Of(), Mock.Of(), new DataEditorAttribute(Constants.PropertyEditors.Aliases.TextBox, "Test Textbox", "textbox"), textService.Object, Mock.Of(), new JsonNetSerializer())); var propEditors = new PropertyEditorCollection(new DataEditorCollection(new[] { dataEditor })); @@ -166,7 +167,14 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Services { private readonly ILocalizedTextService _textService; - public CustomTextOnlyValueEditor(IDataTypeService dataTypeService, ILocalizationService localizationService, DataEditorAttribute attribute, ILocalizedTextService textService, IShortStringHelper shortStringHelper) : base(dataTypeService, localizationService, attribute, textService, shortStringHelper) + public CustomTextOnlyValueEditor( + IDataTypeService dataTypeService, + ILocalizationService localizationService, + DataEditorAttribute attribute, + ILocalizedTextService textService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) + : base(dataTypeService, localizationService, attribute, textService, shortStringHelper, jsonSerializer) { _textService = textService; } diff --git a/src/Umbraco.Tests/Models/MediaXmlTest.cs b/src/Umbraco.Tests/Models/MediaXmlTest.cs index 92fd58d23c..20c86d127f 100644 --- a/src/Umbraco.Tests/Models/MediaXmlTest.cs +++ b/src/Umbraco.Tests/Models/MediaXmlTest.cs @@ -8,7 +8,6 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; -using Umbraco.Core.Logging; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Tests.TestHelpers; @@ -36,7 +35,7 @@ namespace Umbraco.Tests.Models var contentSettings = new ContentSettings(); var mediaFileSystem = new MediaFileSystem(Mock.Of(), scheme, loggerFactory.CreateLogger(), ShortStringHelper); - var ignored = new FileUploadPropertyEditor(loggerFactory, mediaFileSystem, Microsoft.Extensions.Options.Options.Create(contentSettings), DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, UploadAutoFillProperties); + var ignored = new FileUploadPropertyEditor(loggerFactory, mediaFileSystem, Microsoft.Extensions.Options.Options.Create(contentSettings), DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, UploadAutoFillProperties, JsonNetSerializer); var media = MockedMedia.CreateMediaImage(mediaType, -1); media.WriterId = -1; // else it's zero and that's not a user and it breaks the tests diff --git a/src/Umbraco.Tests/Packaging/PackageDataInstallationTests.cs b/src/Umbraco.Tests/Packaging/PackageDataInstallationTests.cs index b48e3230f6..0383eb6ef8 100644 --- a/src/Umbraco.Tests/Packaging/PackageDataInstallationTests.cs +++ b/src/Umbraco.Tests/Packaging/PackageDataInstallationTests.cs @@ -15,6 +15,7 @@ using Umbraco.Core.Models.Packaging; using Umbraco.Core.Packaging; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Tests.Services; @@ -34,7 +35,7 @@ namespace Umbraco.Tests.Packaging public class Editor1 : DataEditor { public Editor1(ILoggerFactory loggerFactory) - : base(loggerFactory, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()) + : base(loggerFactory, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer()) { } } @@ -44,7 +45,7 @@ namespace Umbraco.Tests.Packaging public class Editor2 : DataEditor { public Editor2(ILoggerFactory loggerFactory) - : base(loggerFactory, Mock.Of(), Mock.Of(), Mock.Of(),Mock.Of()) + : base(loggerFactory, Mock.Of(), Mock.Of(), Mock.Of(),Mock.Of(), new JsonNetSerializer()) { } } diff --git a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs index 51d077d89f..2d238c9057 100644 --- a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs +++ b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs @@ -7,7 +7,6 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Moq; using NUnit.Framework; -using Umbraco.Core; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.Models.Packaging; @@ -19,7 +18,6 @@ using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; -using File = System.IO.File; namespace Umbraco.Tests.Packaging { @@ -62,7 +60,9 @@ namespace Umbraco.Tests.Packaging Factory.GetRequiredService(), Microsoft.Extensions.Options.Options.Create(new GlobalSettings()), Factory.GetRequiredService(), - Factory.GetRequiredService()); + Factory.GetRequiredService(), + Factory.GetRequiredService() + ); private IPackageInstallation PackageInstallation => new PackageInstallation( PackageDataInstallation, diff --git a/src/Umbraco.Tests/Published/ConvertersTests.cs b/src/Umbraco.Tests/Published/ConvertersTests.cs index 840ec58f13..8a9bdb99ca 100644 --- a/src/Umbraco.Tests/Published/ConvertersTests.cs +++ b/src/Umbraco.Tests/Published/ConvertersTests.cs @@ -62,10 +62,10 @@ namespace Umbraco.Tests.Published var serializer = new ConfigurationEditorJsonSerializer(); var dataTypeServiceMock = new Mock(); var dataType1 = new DataType(new VoidEditor(NullLoggerFactory.Instance, dataTypeServiceMock.Object, - Mock.Of(), Mock.Of(), Mock.Of()), serializer) + Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer()), serializer) { Id = 1 }; var dataType2 = new DataType(new VoidEditor("2", NullLoggerFactory.Instance, Mock.Of(), - Mock.Of(), Mock.Of(), Mock.Of()), serializer) + Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer()), serializer) { Id = 2 }; dataTypeServiceMock.Setup(x => x.GetAll()).Returns(new []{dataType1, dataType2 }); diff --git a/src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs b/src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs index a17eb71ab0..f9909408b8 100644 --- a/src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs +++ b/src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs @@ -2,14 +2,11 @@ using System.Collections.Generic; using System.Data; using System.Linq; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; using Moq; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.Composing; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Events; using Umbraco.Core.Hosting; @@ -19,20 +16,20 @@ using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Services.Changes; using Umbraco.Core.Strings; +using Umbraco.Net; using Umbraco.Tests.Common; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing.Objects; using Umbraco.Web; using Umbraco.Web.Cache; +using Umbraco.Web.Composing; using Umbraco.Web.PublishedCache; using Umbraco.Web.PublishedCache.NuCache; using Umbraco.Web.PublishedCache.NuCache.DataSource; -using Current = Umbraco.Web.Composing.Current; -using Umbraco.Core.Serialization; -using Umbraco.Net; namespace Umbraco.Tests.PublishedContent { @@ -70,7 +67,7 @@ namespace Umbraco.Tests.PublishedContent var serializer = new ConfigurationEditorJsonSerializer(); // create data types, property types and content types - var dataType = new DataType(new VoidEditor("Editor", NullLoggerFactory.Instance, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()), serializer) { Id = 3 }; + var dataType = new DataType(new VoidEditor("Editor", NullLoggerFactory.Instance, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer()), serializer) { Id = 3 }; var dataTypes = new[] { diff --git a/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs b/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs index d689215081..1d90984d04 100644 --- a/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs +++ b/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs @@ -2,13 +2,10 @@ using System.Collections.Generic; using System.Data; using System.Linq; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Moq; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.Composing; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Events; using Umbraco.Core.Logging; @@ -27,10 +24,10 @@ using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing.Objects; using Umbraco.Web; using Umbraco.Web.Cache; +using Umbraco.Web.Composing; using Umbraco.Web.PublishedCache; using Umbraco.Web.PublishedCache.NuCache; using Umbraco.Web.PublishedCache.NuCache.DataSource; -using Current = Umbraco.Web.Composing.Current; namespace Umbraco.Tests.PublishedContent { @@ -120,7 +117,7 @@ namespace Umbraco.Tests.PublishedContent var serializer = new ConfigurationEditorJsonSerializer(); // create data types, property types and content types - var dataType = new DataType(new VoidEditor("Editor", NullLoggerFactory.Instance, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()), serializer) { Id = 3 }; + var dataType = new DataType(new VoidEditor("Editor", NullLoggerFactory.Instance, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer()), serializer) { Id = 3 }; var dataTypes = new[] { diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs index 37cc8911b1..7cc5bae403 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs @@ -5,8 +5,6 @@ using System.Linq; using Microsoft.Extensions.Logging.Abstractions; using Moq; using NUnit.Framework; -using Umbraco.Web.Composing; -using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; @@ -14,9 +12,7 @@ using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Tests.TestHelpers; -using Umbraco.Tests.Testing; using Umbraco.Web; -using PublishedContentExtensions = Umbraco.Web.PublishedContentExtensions; namespace Umbraco.Tests.PublishedContent { @@ -130,7 +126,7 @@ namespace Umbraco.Tests.PublishedContent { var serializer = new ConfigurationEditorJsonSerializer(); var dataTypeService = new TestObjects.TestDataTypeService( - new DataType(new VoidEditor(NullLoggerFactory.Instance, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()), serializer) { Id = 1 }); + new DataType(new VoidEditor(NullLoggerFactory.Instance, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer()), serializer) { Id = 1 }); var factory = new PublishedContentTypeFactory(Mock.Of(), new PropertyValueConverterCollection(Array.Empty()), dataTypeService); var contentTypeAlias = createChildren ? "Parent" : "Child"; diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs index 75983ba41a..e4b3721892 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs @@ -7,23 +7,22 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Moq; using Umbraco.Core; -using Umbraco.Core.Models.PublishedContent; -using Umbraco.Web; -using Umbraco.Web.PublishedCache; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; +using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Security; using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; -using Umbraco.Tests.TestHelpers; -using Current = Umbraco.Web.Composing.Current; using Umbraco.Tests.Common; -using Umbraco.Core.Security; +using Umbraco.Tests.TestHelpers; +using Umbraco.Web; +using Umbraco.Web.PublishedCache; namespace Umbraco.Tests.PublishedContent { @@ -90,7 +89,7 @@ namespace Umbraco.Tests.PublishedContent { var serializer = new ConfigurationEditorJsonSerializer(); var dataTypeService = new TestObjects.TestDataTypeService( - new DataType(new VoidEditor(NullLoggerFactory.Instance, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()), serializer) { Id = 1 }); + new DataType(new VoidEditor(NullLoggerFactory.Instance, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer()), serializer) { Id = 1 }); var factory = new PublishedContentTypeFactory(Mock.Of(), new PropertyValueConverterCollection(Array.Empty()), dataTypeService); var caches = new SolidPublishedSnapshot(); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs index b55609858b..aa8fc26bd8 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs @@ -1,25 +1,23 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -using Umbraco.Core; +using Moq; +using Umbraco.Core.IO; +using Umbraco.Core.Media; +using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.ValueConverters; -using Umbraco.Tests.TestHelpers; -using Moq; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; -using Umbraco.Core.Models; -using Umbraco.Web.PropertyEditors; -using Umbraco.Core.Services; -using Umbraco.Web; -using Umbraco.Web.Templates; -using Umbraco.Web.Routing; -using Umbraco.Core.Media; -using System; -using Microsoft.Extensions.DependencyInjection; using Umbraco.Core.Security; using Umbraco.Core.Serialization; +using Umbraco.Core.Services; +using Umbraco.Tests.TestHelpers; +using Umbraco.Web; +using Umbraco.Web.PropertyEditors; +using Umbraco.Web.Routing; +using Umbraco.Web.Templates; namespace Umbraco.Tests.PublishedContent { @@ -67,7 +65,8 @@ namespace Umbraco.Tests.PublishedContent ShortStringHelper, IOHelper, LocalizedTextService, - Mock.Of()), + Mock.Of(), + new JsonNetSerializer()), serializer) { Id = 1 }); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index 2170da2f75..797b1c2be9 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -5,31 +5,31 @@ using System.Linq; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Moq; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.PropertyEditors; -using Umbraco.Web; -using Umbraco.Web.PublishedCache; -using Moq; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; +using Umbraco.Core.Media; using Umbraco.Core.Models; +using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Security; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; +using Umbraco.Web; +using Umbraco.Web.Composing; using Umbraco.Web.Models.PublishedContent; using Umbraco.Web.PropertyEditors; -using Umbraco.Web.Templates; +using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; -using Current = Umbraco.Web.Composing.Current; -using Umbraco.Core.Media; -using Umbraco.Core.Security; -using Umbraco.Core.Serialization; +using Umbraco.Web.Templates; namespace Umbraco.Tests.PublishedContent { @@ -64,12 +64,12 @@ namespace Umbraco.Tests.PublishedContent var localizationService = Mock.Of(); var dataTypeService = new TestObjects.TestDataTypeService( - new DataType(new VoidEditor(loggerFactory, Mock.Of(), localizationService, LocalizedTextService, ShortStringHelper), serializer) { Id = 1 }, - new DataType(new TrueFalsePropertyEditor(loggerFactory, Mock.Of(), localizationService, IOHelper, ShortStringHelper, LocalizedTextService), serializer) { Id = 1001 }, - new DataType(new RichTextPropertyEditor(loggerFactory,backOfficeSecurityAccessor, Mock.Of(), localizationService, imageSourceParser, linkParser, pastedImages, ShortStringHelper, IOHelper, LocalizedTextService, Mock.Of()), serializer) { Id = 1002 }, - new DataType(new IntegerPropertyEditor(loggerFactory, Mock.Of(), localizationService, ShortStringHelper, LocalizedTextService), serializer) { Id = 1003 }, - new DataType(new TextboxPropertyEditor(loggerFactory, Mock.Of(), localizationService, IOHelper, ShortStringHelper, LocalizedTextService), serializer) { Id = 1004 }, - new DataType(new MediaPickerPropertyEditor(loggerFactory, Mock.Of(), localizationService, IOHelper, ShortStringHelper, LocalizedTextService), serializer) { Id = 1005 }); + new DataType(new VoidEditor(loggerFactory, Mock.Of(), localizationService, LocalizedTextService, ShortStringHelper, JsonNetSerializer), serializer) { Id = 1 }, + new DataType(new TrueFalsePropertyEditor(loggerFactory, Mock.Of(), localizationService, IOHelper, ShortStringHelper, LocalizedTextService, JsonNetSerializer), serializer) { Id = 1001 }, + new DataType(new RichTextPropertyEditor(loggerFactory,backOfficeSecurityAccessor, Mock.Of(), localizationService, imageSourceParser, linkParser, pastedImages, ShortStringHelper, IOHelper, LocalizedTextService, Mock.Of(), JsonNetSerializer), serializer) { Id = 1002 }, + new DataType(new IntegerPropertyEditor(loggerFactory, Mock.Of(), localizationService, ShortStringHelper, LocalizedTextService, JsonNetSerializer), serializer) { Id = 1003 }, + new DataType(new TextboxPropertyEditor(loggerFactory, Mock.Of(), localizationService, IOHelper, ShortStringHelper, LocalizedTextService, JsonNetSerializer), serializer) { Id = 1004 }, + new DataType(new MediaPickerPropertyEditor(loggerFactory, Mock.Of(), localizationService, IOHelper, ShortStringHelper, LocalizedTextService, JsonNetSerializer), serializer) { Id = 1005 }); Builder.Services.AddUnique(f => dataTypeService); } diff --git a/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs b/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs index 6bdca6f0f6..58b6ea7c4d 100644 --- a/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs +++ b/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs @@ -5,13 +5,13 @@ using Microsoft.Extensions.Logging.Abstractions; using Moq; using Umbraco.Core; using Umbraco.Core.Cache; -using Umbraco.Web.Composing; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; +using Umbraco.Web.Composing; using Umbraco.Web.PublishedCache; namespace Umbraco.Tests.PublishedContent @@ -415,7 +415,7 @@ namespace Umbraco.Tests.PublishedContent var serializer = new ConfigurationEditorJsonSerializer(); var dataTypeServiceMock = new Mock(); var dataType = new DataType(new VoidEditor(NullLoggerFactory.Instance, dataTypeServiceMock.Object, - Mock.Of(), Mock.Of(), Mock.Of()), serializer) + Mock.Of(), Mock.Of(), Mock.Of(), new JsonNetSerializer()), serializer) { Id = 666 }; dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield); diff --git a/src/Umbraco.Tests/Routing/MediaUrlProviderTests.cs b/src/Umbraco.Tests/Routing/MediaUrlProviderTests.cs index 84d0ea17f6..047b7205bf 100644 --- a/src/Umbraco.Tests/Routing/MediaUrlProviderTests.cs +++ b/src/Umbraco.Tests/Routing/MediaUrlProviderTests.cs @@ -39,8 +39,8 @@ namespace Umbraco.Tests.Routing var dataTypeService = Mock.Of(); var propertyEditors = new MediaUrlGeneratorCollection(new IMediaUrlGenerator[] { - new FileUploadPropertyEditor(loggerFactory, mediaFileSystemMock, Microsoft.Extensions.Options.Options.Create(contentSettings), dataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, UploadAutoFillProperties), - new ImageCropperPropertyEditor(loggerFactory, mediaFileSystemMock, Microsoft.Extensions.Options.Options.Create(contentSettings), dataTypeService, LocalizationService, IOHelper, ShortStringHelper, LocalizedTextService, UploadAutoFillProperties), + new FileUploadPropertyEditor(loggerFactory, mediaFileSystemMock, Microsoft.Extensions.Options.Options.Create(contentSettings), dataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, UploadAutoFillProperties, JsonNetSerializer), + new ImageCropperPropertyEditor(loggerFactory, mediaFileSystemMock, Microsoft.Extensions.Options.Options.Create(contentSettings), dataTypeService, LocalizationService, IOHelper, ShortStringHelper, LocalizedTextService, UploadAutoFillProperties, JsonNetSerializer), }); _mediaUrlProvider = new DefaultMediaUrlProvider(propertyEditors, UriUtility); } diff --git a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs index c6587f6ad8..cab74e22e4 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs @@ -7,9 +7,7 @@ using Microsoft.Extensions.Logging.Abstractions; using Moq; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.Composing; using Umbraco.Core.Configuration.Models; -using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; @@ -18,7 +16,6 @@ using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Tests.Common; -using Umbraco.Tests.Common.Builders; using Umbraco.Tests.PublishedContent; using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Web; @@ -50,7 +47,7 @@ namespace Umbraco.Tests.TestHelpers var serializer = new ConfigurationEditorJsonSerializer(); var dataTypeService = new TestObjects.TestDataTypeService( - new DataType(new VoidEditor(NullLoggerFactory.Instance, Mock.Of(), Mock.Of(),Mock.Of(), Mock.Of()), serializer) { Id = 1 }); + new DataType(new VoidEditor(NullLoggerFactory.Instance, Mock.Of(), Mock.Of(),Mock.Of(), Mock.Of(), JsonNetSerializer), serializer) { Id = 1 }); var factory = new PublishedContentTypeFactory(Mock.Of(), new PropertyValueConverterCollection(Array.Empty()), dataTypeService); var type = new AutoPublishedContentType(Guid.NewGuid(), 0, "anything", new PublishedPropertyType[] { }); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 533966f5a9..bc697b9346 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -1,12 +1,4 @@ -using Examine; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using Moq; -using NUnit.Framework; -using Serilog; -using System; +using System; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -15,6 +7,14 @@ using System.Reflection; using System.Web.Routing; using System.Web.Security; using System.Xml.Linq; +using Examine; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using NUnit.Framework; +using Serilog; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; @@ -50,6 +50,7 @@ using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Web; using Umbraco.Web.Actions; using Umbraco.Web.AspNet; +using Umbraco.Web.Composing; using Umbraco.Web.ContentApps; using Umbraco.Web.Hosting; using Umbraco.Web.Install; @@ -63,7 +64,6 @@ using Umbraco.Web.Security.Providers; using Umbraco.Web.Services; using Umbraco.Web.Templates; using Umbraco.Web.Trees; -using Current = Umbraco.Web.Composing.Current; using FileSystems = Umbraco.Core.IO.FileSystems; using ILogger = Microsoft.Extensions.Logging.ILogger; @@ -315,6 +315,8 @@ namespace Umbraco.Tests.Testing Builder.Services.AddUnique(); Builder.Services.AddUnique(); Builder.Services.AddUnique(); + Builder.Services.AddUnique(); + Builder.Services.AddUnique(); Builder.SetCultureDictionaryFactory(); Builder.Services.AddSingleton(f => f.GetRequiredService().CreateDictionary()); // register back office sections in the order we want them rendered diff --git a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs index 8d6adee475..aa2a57b123 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs @@ -7,40 +7,38 @@ using System.Net.Mime; using System.Text; using System.Xml; using System.Xml.Linq; -using Microsoft.Extensions.Logging; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Umbraco.Core; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Dictionary; using Umbraco.Core.Hosting; +using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.Packaging; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; +using Umbraco.Core.Security; +using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; -using Umbraco.Web.Models; -using Umbraco.Web.Models.ContentEditing; -using Constants = Umbraco.Core.Constants; -using Umbraco.Core.Mapping; -using Umbraco.Core.Security; -using Umbraco.Web.BackOffice.Filters; using Umbraco.Web.Common.Attributes; +using Umbraco.Web.Common.Authorization; using Umbraco.Web.Common.Exceptions; using Umbraco.Web.Editors; +using Umbraco.Web.Models; +using Umbraco.Web.Models.ContentEditing; using ContentType = Umbraco.Core.Models.ContentType; -using Umbraco.Core.Configuration.Models; -using Microsoft.Extensions.Options; -using Umbraco.Core.Serialization; -using Microsoft.AspNetCore.Authorization; -using Umbraco.Web.Common.Authorization; namespace Umbraco.Web.BackOffice.Controllers { /// /// An API controller used for dealing with content types /// - [PluginController(Constants.Web.Mvc.BackOfficeApiArea)] + [PluginController(Constants.Web.Mvc.BackOfficeApiArea)] public class ContentTypeController : ContentTypeControllerBase { // TODO: Split this controller apart so that authz is consistent, currently we need to authz each action individually. @@ -65,7 +63,8 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly IMacroService _macroService; private readonly IEntityService _entityService; private readonly IHostingEnvironment _hostingEnvironment; - private readonly IConfigurationEditorJsonSerializer _jsonSerializer; + private readonly IConfigurationEditorJsonSerializer _configurationEditorJsonSerializer; + private readonly IJsonSerializer _jsonSerializer; public ContentTypeController( ICultureDictionary cultureDictionary, @@ -91,7 +90,8 @@ namespace Umbraco.Web.BackOffice.Controllers IEntityService entityService, IHostingEnvironment hostingEnvironment, EditorValidatorCollection editorValidatorCollection, - IConfigurationEditorJsonSerializer jsonSerializer) + IConfigurationEditorJsonSerializer configurationEditorJsonSerializer, + IJsonSerializer jsonSerializer) : base(cultureDictionary, editorValidatorCollection, contentTypeService, @@ -119,6 +119,7 @@ namespace Umbraco.Web.BackOffice.Controllers _macroService = macroService; _entityService = entityService; _hostingEnvironment = hostingEnvironment; + _configurationEditorJsonSerializer = configurationEditorJsonSerializer; _jsonSerializer = jsonSerializer; } @@ -220,7 +221,7 @@ namespace Umbraco.Web.BackOffice.Controllers /// Gets all user defined properties. /// /// - [Authorize(Policy = AuthorizationPolicies.TreeAccessAnyContentOrTypes)] + [Authorize(Policy = AuthorizationPolicies.TreeAccessAnyContentOrTypes)] public IEnumerable GetAllPropertyTypeAliases() { return _contentTypeService.GetAllPropertyTypeAliases(); @@ -626,8 +627,23 @@ namespace Umbraco.Web.BackOffice.Controllers return NotFound(); } - var dataInstaller = new PackageDataInstallation(_loggerFactory.CreateLogger(), _loggerFactory, _fileService, _macroService, _LocalizationService, - _dataTypeService, _entityService, _contentTypeService, _contentService, _propertyEditors, _scopeProvider, _shortStringHelper, Options.Create(_globalSettings), _localizedTextService, _jsonSerializer); + var dataInstaller = new PackageDataInstallation( + _loggerFactory.CreateLogger(), + _loggerFactory, + _fileService, + _macroService, + _LocalizationService, + _dataTypeService, + _entityService, + _contentTypeService, + _contentService, + _propertyEditors, + _scopeProvider, + _shortStringHelper, + Options.Create(_globalSettings), + _localizedTextService, + _configurationEditorJsonSerializer, + _jsonSerializer); var xd = new XmlDocument {XmlResolver = null}; xd.Load(filePath); From e79ed7a56b0edf68a400a62ff14f2fb9c376407c Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Mon, 7 Dec 2020 16:11:14 +0100 Subject: [PATCH 05/27] Post merge - Build fix --- .../Install/InstallSteps/NewInstallStep.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs b/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs index 234f414f5f..b7699b7d0e 100644 --- a/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs +++ b/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs @@ -6,9 +6,9 @@ using System.Threading.Tasks; using Microsoft.Extensions.Options; using Newtonsoft.Json; using Umbraco.Core; -using Umbraco.Core.BackOffice; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Migrations.Install; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Extensions; using Umbraco.Web.Install.Models; From ea55d2662ec48e72f09fe799b20603dcc53a85de Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 8 Dec 2020 10:42:26 +1100 Subject: [PATCH 06/27] no app_data paths, changing to constants, some linting updates --- .../Configuration/LocalTempStorage.cs | 1 - .../Constants-SystemDirectories.cs | 7 +-- .../FolderAndFilePermissionsCheck.cs | 3 +- .../Hosting/IHostingEnvironment.cs | 6 +- .../Diagnostics/MiniDump.cs | 22 +++++--- .../Migrations/Install/DatabaseBuilder.cs | 4 +- src/Umbraco.Tests.Common/TestHelperBase.cs | 4 +- .../Umbraco.Core/Components/ComponentTests.cs | 4 +- .../Composing/ComposingTestBase.cs | 5 +- .../Umbraco.Core/Composing/TypeLoaderTests.cs | 4 +- .../TestHelpers/BaseUsingSqlCeSyntax.cs | 4 +- .../Controllers/ContentTypeController.cs | 4 +- .../AspNetCoreHostingEnvironment.cs | 56 ++++++++++++------- .../AspNet/AspNetHostingEnvironment.cs | 8 +-- 14 files changed, 72 insertions(+), 60 deletions(-) diff --git a/src/Umbraco.Core/Configuration/LocalTempStorage.cs b/src/Umbraco.Core/Configuration/LocalTempStorage.cs index 0013fb68e4..50eab639d0 100644 --- a/src/Umbraco.Core/Configuration/LocalTempStorage.cs +++ b/src/Umbraco.Core/Configuration/LocalTempStorage.cs @@ -4,7 +4,6 @@ namespace Umbraco.Core.Configuration { Unknown = 0, Default, - AspNetTemp, EnvironmentTemp } } diff --git a/src/Umbraco.Core/Constants-SystemDirectories.cs b/src/Umbraco.Core/Constants-SystemDirectories.cs index d4ca2a3c57..a86e4171d6 100644 --- a/src/Umbraco.Core/Constants-SystemDirectories.cs +++ b/src/Umbraco.Core/Constants-SystemDirectories.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Core +namespace Umbraco.Core { public static partial class Constants { @@ -8,7 +8,7 @@ public const string Config = "~/config"; - public const string Data = "~/App_Data"; + public const string Data = "~/Umbraco/Data"; public const string TempData = Data + "/TEMP"; @@ -18,8 +18,6 @@ public const string Install = "~/install"; - public const string AppCode = "~/App_Code"; - public const string AppPlugins = "/App_Plugins"; public const string MvcViews = "~/Views"; @@ -32,6 +30,7 @@ public const string Preview = Data + "/preview"; + // TODO: This doesn't seem right? public const string LogFiles= "~/Logs"; } } diff --git a/src/Umbraco.Core/HealthCheck/Checks/Permissions/FolderAndFilePermissionsCheck.cs b/src/Umbraco.Core/HealthCheck/Checks/Permissions/FolderAndFilePermissionsCheck.cs index 9e279c98e2..a22748094a 100644 --- a/src/Umbraco.Core/HealthCheck/Checks/Permissions/FolderAndFilePermissionsCheck.cs +++ b/src/Umbraco.Core/HealthCheck/Checks/Permissions/FolderAndFilePermissionsCheck.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using Microsoft.Extensions.Options; @@ -71,7 +71,6 @@ namespace Umbraco.Core.HealthCheck.Checks.Permissions //so these need to be tested differently var pathsToCheckWithRestarts = new Dictionary { - { Constants.SystemDirectories.AppCode, PermissionCheckRequirement.Optional }, { Constants.SystemDirectories.Bin, PermissionCheckRequirement.Optional } }; diff --git a/src/Umbraco.Core/Hosting/IHostingEnvironment.cs b/src/Umbraco.Core/Hosting/IHostingEnvironment.cs index 188fb87b55..60d582c6c9 100644 --- a/src/Umbraco.Core/Hosting/IHostingEnvironment.cs +++ b/src/Umbraco.Core/Hosting/IHostingEnvironment.cs @@ -5,6 +5,7 @@ namespace Umbraco.Core.Hosting public interface IHostingEnvironment { string SiteName { get; } + string ApplicationId { get; } /// @@ -35,8 +36,6 @@ namespace Umbraco.Core.Hosting /// /// Maps a virtual path to a physical path to the application's web root /// - /// - /// /// /// Depending on the runtime 'web root', this result can vary. For example in Net Framework the web root and the content root are the same, however /// in netcore the web root is /www therefore this will Map to a physical path within www. @@ -46,8 +45,6 @@ namespace Umbraco.Core.Hosting /// /// Maps a virtual path to a physical path to the application's root (not always equal to the web root) /// - /// - /// /// /// Depending on the runtime 'web root', this result can vary. For example in Net Framework the web root and the content root are the same, however /// in netcore the web root is /www therefore this will Map to a physical path within www. @@ -58,7 +55,6 @@ namespace Umbraco.Core.Hosting /// Converts a virtual path to an absolute URL path based on the application's web root /// /// The virtual path. Must start with either ~/ or / else an exception is thrown. - /// /// /// This maps the virtual path syntax to the web root. For example when hosting in a virtual directory called "site" and the value "~/pages/test" is passed in, it will /// map to "/site/pages/test" where "/site" is the value of . diff --git a/src/Umbraco.Infrastructure/Diagnostics/MiniDump.cs b/src/Umbraco.Infrastructure/Diagnostics/MiniDump.cs index 57e9b5204b..f2f730078f 100644 --- a/src/Umbraco.Infrastructure/Diagnostics/MiniDump.cs +++ b/src/Umbraco.Infrastructure/Diagnostics/MiniDump.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; @@ -111,11 +111,14 @@ namespace Umbraco.Core.Diagnostics // filter everywhere in our code = not! var stacktrace = withException ? Environment.StackTrace : string.Empty; - var filepath = Path.Combine(hostingEnvironment.ApplicationPhysicalPath, "App_Data/MiniDump"); - if (Directory.Exists(filepath) == false) - Directory.CreateDirectory(filepath); + var directory = hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.Data + "/MiniDump"); - var filename = Path.Combine(filepath, $"{DateTime.UtcNow:yyyyMMddTHHmmss}.{Guid.NewGuid().ToString("N").Substring(0, 4)}.dmp"); + if (Directory.Exists(directory) == false) + { + Directory.CreateDirectory(directory); + } + + var filename = Path.Combine(directory, $"{DateTime.UtcNow:yyyyMMddTHHmmss}.{Guid.NewGuid().ToString("N").Substring(0, 4)}.dmp"); using (var stream = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite, FileShare.Write)) { return Write(marchal, stream.SafeFileHandle, options, withException); @@ -127,9 +130,12 @@ namespace Umbraco.Core.Diagnostics { lock (LockO) { - var filepath = Path.Combine(hostingEnvironment.ApplicationPhysicalPath, "App_Data/MiniDump"); - if (Directory.Exists(filepath) == false) return true; - var count = Directory.GetFiles(filepath, "*.dmp").Length; + var directory = hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.Data + "/MiniDump"); + if (Directory.Exists(directory) == false) + { + return true; + } + var count = Directory.GetFiles(directory, "*.dmp").Length; return count < 8; } } diff --git a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs index b27bc48c8e..98e9bcb4bb 100644 --- a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs +++ b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Linq; using System.Xml.Linq; @@ -462,7 +462,7 @@ namespace Umbraco.Core.Migrations.Install { Message = "The database configuration failed with the following message: " + ex.Message + - "\n Please check log file for additional information (can be found in '/App_Data/Logs/')", + $"\n Please check log file for additional information (can be found in '{Constants.SystemDirectories.LogFiles}')", Success = false, Percentage = "90" }; diff --git a/src/Umbraco.Tests.Common/TestHelperBase.cs b/src/Umbraco.Tests.Common/TestHelperBase.cs index 24759f9ffb..ed3e28ee21 100644 --- a/src/Umbraco.Tests.Common/TestHelperBase.cs +++ b/src/Umbraco.Tests.Common/TestHelperBase.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Reflection; using Microsoft.Extensions.DependencyInjection; @@ -48,7 +48,7 @@ namespace Umbraco.Tests.Common public TypeLoader GetMockedTypeLoader() { - return new TypeLoader(Mock.Of(), Mock.Of(), new DirectoryInfo(GetHostingEnvironment().MapPathContentRoot("~/App_Data/TEMP")), Mock.Of>(), Mock.Of()); + return new TypeLoader(Mock.Of(), Mock.Of(), new DirectoryInfo(GetHostingEnvironment().MapPathContentRoot(Constants.SystemDirectories.TempData)), Mock.Of>(), Mock.Of()); } // public Configs GetConfigs() => GetConfigsFactory().Create(); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Components/ComponentTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Components/ComponentTests.cs index 44aacab944..6d51603502 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Components/ComponentTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Components/ComponentTests.cs @@ -68,7 +68,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Components private static TypeLoader MockTypeLoader() { var ioHelper = IOHelper; - return new TypeLoader(Mock.Of(), Mock.Of(), new DirectoryInfo(TestHelper.GetHostingEnvironment().MapPathContentRoot("~/App_Data/TEMP")), Mock.Of>(), Mock.Of()); + return new TypeLoader(Mock.Of(), Mock.Of(), new DirectoryInfo(TestHelper.GetHostingEnvironment().MapPathContentRoot(Constants.SystemDirectories.TempData)), Mock.Of>(), Mock.Of()); } @@ -390,7 +390,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Components public void AllComposers() { var typeFinder = TestHelper.GetTypeFinder(); - var typeLoader = new TypeLoader(typeFinder, AppCaches.Disabled.RuntimeCache, new DirectoryInfo(TestHelper.GetHostingEnvironment().MapPathContentRoot("~/App_Data/TEMP")), Mock.Of>(), Mock.Of()); + var typeLoader = new TypeLoader(typeFinder, AppCaches.Disabled.RuntimeCache, new DirectoryInfo(TestHelper.GetHostingEnvironment().MapPathContentRoot(Constants.SystemDirectories.TempData)), Mock.Of>(), Mock.Of()); var register = MockRegister(); var builder = new UmbracoBuilder(register, Mock.Of(), TestHelper.GetMockedTypeLoader()); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/ComposingTestBase.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/ComposingTestBase.cs index 43760d1c6c..1c8bf139ac 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/ComposingTestBase.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/ComposingTestBase.cs @@ -1,9 +1,10 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Reflection; using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Logging; @@ -23,7 +24,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Composing ProfilingLogger = new ProfilingLogger(Mock.Of>(), Mock.Of()); var typeFinder = TestHelper.GetTypeFinder(); - TypeLoader = new TypeLoader(typeFinder, NoAppCache.Instance, new DirectoryInfo(TestHelper.GetHostingEnvironment().MapPathContentRoot("~/App_Data/TEMP")), Mock.Of>(), ProfilingLogger, false, AssembliesToScan); + TypeLoader = new TypeLoader(typeFinder, NoAppCache.Instance, new DirectoryInfo(TestHelper.GetHostingEnvironment().MapPathContentRoot(Constants.SystemDirectories.TempData)), Mock.Of>(), ProfilingLogger, false, AssembliesToScan); } protected virtual IEnumerable AssembliesToScan diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/TypeLoaderTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/TypeLoaderTests.cs index 20e9f8feef..36843ad1cc 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/TypeLoaderTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/TypeLoaderTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -28,7 +28,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Composing // this ensures it's reset var typeFinder = TestHelper.GetTypeFinder(); _typeLoader = new TypeLoader(typeFinder, NoAppCache.Instance, - new DirectoryInfo(TestHelper.GetHostingEnvironment().MapPathContentRoot("~/App_Data/TEMP")), + new DirectoryInfo(TestHelper.GetHostingEnvironment().MapPathContentRoot(Constants.SystemDirectories.TempData)), Mock.Of>(), new ProfilingLogger(Mock.Of>(), Mock.Of()), false, // for testing, we'll specify which assemblies are scanned for the PluginTypeResolver diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index 6e27bdd07c..adc076caec 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -43,7 +43,7 @@ namespace Umbraco.Tests.TestHelpers var logger = new ProfilingLogger(Mock.Of>(), Mock.Of()); var typeFinder = TestHelper.GetTypeFinder(); var typeLoader = new TypeLoader(typeFinder, NoAppCache.Instance, - new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), + new DirectoryInfo(ioHelper.MapPath(Constants.SystemDirectories.TempData)), Mock.Of>(), logger, false); diff --git a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs index 8d6adee475..f11ed373cd 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -643,7 +643,7 @@ namespace Umbraco.Web.BackOffice.Controllers } catch (Exception ex) { - _logger.LogError(ex, "Error cleaning up temporary udt file in App_Data: {File}", filePath); + _logger.LogError(ex, "Error cleaning up temporary udt file in {File}", filePath); } return Ok(); diff --git a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreHostingEnvironment.cs b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreHostingEnvironment.cs index f67e062847..6b06db315c 100644 --- a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreHostingEnvironment.cs +++ b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreHostingEnvironment.cs @@ -10,7 +10,7 @@ namespace Umbraco.Web.Common.AspNetCore { public class AspNetCoreHostingEnvironment : Core.Hosting.IHostingEnvironment { - private IOptionsMonitor _hostingSettings; + private IOptionsMonitor _hostingSettings; private readonly IWebHostEnvironment _webHostEnvironment; private string _localTempPath; @@ -27,59 +27,67 @@ namespace Umbraco.Web.Common.AspNetCore IISVersion = new Version(0, 0); // TODO not necessary IIS } + /// public bool IsHosted { get; } = true; + + /// public string SiteName { get; } + + /// public string ApplicationId { get; } + + /// public string ApplicationPhysicalPath { get; } + public string ApplicationServerAddress { get; } - //TODO how to find this, This is a server thing, not application thing. + // TODO how to find this, This is a server thing, not application thing. public string ApplicationVirtualPath => _hostingSettings.CurrentValue.ApplicationVirtualPath?.EnsureStartsWith('/') ?? "/"; + + /// public bool IsDebugMode => _hostingSettings.CurrentValue.Debug; public Version IISVersion { get; } + public string LocalTempPath { get { if (_localTempPath != null) + { return _localTempPath; + } switch (_hostingSettings.CurrentValue.LocalTempStorageLocation) { - case LocalTempStorage.AspNetTemp: - - // TODO: I don't think this is correct? but also we probably can remove AspNetTemp as an option entirely - // since this is legacy and we shouldn't use it - return _localTempPath = System.IO.Path.Combine(Path.GetTempPath(), ApplicationId, "UmbracoData"); - case LocalTempStorage.EnvironmentTemp: // environment temp is unique, we need a folder per site // use a hash // combine site name and application id - // site name is a Guid on Cloud - // application id is eg /LM/W3SVC/123456/ROOT + // site name is a Guid on Cloud + // application id is eg /LM/W3SVC/123456/ROOT // the combination is unique on one server // and, if a site moves from worker A to B and then back to A... - // hopefully it gets a new Guid or new application id? - - var hashString = SiteName + "::" + ApplicationId; - var hash = hashString.GenerateHash(); - var siteTemp = System.IO.Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData", hash); + // hopefully it gets a new Guid or new application id? + string hashString = SiteName + "::" + ApplicationId; + string hash = hashString.GenerateHash(); + string siteTemp = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData", hash); return _localTempPath = siteTemp; - //case LocalTempStorage.Default: - //case LocalTempStorage.Unknown: default: - return _localTempPath = MapPathContentRoot("~/App_Data/TEMP"); + + return _localTempPath = MapPathContentRoot(Core.Constants.SystemDirectories.TempData); } } } + /// public string MapPathWebRoot(string path) => MapPath(_webHostEnvironment.WebRootPath, path); + + /// public string MapPathContentRoot(string path) => MapPath(_webHostEnvironment.ContentRootPath, path); private string MapPath(string root, string path) @@ -91,21 +99,29 @@ namespace Umbraco.Web.Common.AspNetCore // however if you are requesting a path be mapped, it should always assume the path is relative to the root, not // absolute in the file system. This error will help us find and fix improper uses, and should be removed once // all those uses have been found and fixed - if (newPath.StartsWith(root)) throw new ArgumentException("The path appears to already be fully qualified. Please remove the call to MapPath"); + if (newPath.StartsWith(root)) + { + throw new ArgumentException("The path appears to already be fully qualified. Please remove the call to MapPath"); + } return Path.Combine(root, newPath.TrimStart('~', '/', '\\')); } + /// public string ToAbsolute(string virtualPath) { if (!virtualPath.StartsWith("~/") && !virtualPath.StartsWith("/")) + { throw new InvalidOperationException($"The value {virtualPath} for parameter {nameof(virtualPath)} must start with ~/ or /"); + } // will occur if it starts with "/" if (Uri.IsWellFormedUriString(virtualPath, UriKind.Absolute)) + { return virtualPath; + } - var fullPath = ApplicationVirtualPath.EnsureEndsWith('/') + virtualPath.TrimStart('~', '/'); + string fullPath = ApplicationVirtualPath.EnsureEndsWith('/') + virtualPath.TrimStart('~', '/'); return fullPath; } diff --git a/src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs b/src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs index cc8fc975d2..ec9d66859e 100644 --- a/src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs +++ b/src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs @@ -11,6 +11,7 @@ using Umbraco.Core.Hosting; namespace Umbraco.Web.Hosting { + // TODO: This has been migrated to netcore public class AspNetHostingEnvironment : IHostingEnvironment { @@ -67,9 +68,6 @@ namespace Umbraco.Web.Hosting switch (_hostingSettings.LocalTempStorageLocation) { - case LocalTempStorage.AspNetTemp: - return _localTempPath = System.IO.Path.Combine(HttpRuntime.CodegenDir, "UmbracoData"); - case LocalTempStorage.EnvironmentTemp: // environment temp is unique, we need a folder per site @@ -88,10 +86,8 @@ namespace Umbraco.Web.Hosting return _localTempPath = siteTemp; - //case LocalTempStorage.Default: - //case LocalTempStorage.Unknown: default: - return _localTempPath = MapPathContentRoot("~/App_Data/TEMP"); + return _localTempPath = MapPathContentRoot(Constants.SystemDirectories.TempData); } } } From 30bfa3f0037f03cb4a1ab2cdfde0db43341e8fea Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 8 Dec 2020 11:08:14 +1100 Subject: [PATCH 07/27] more cleanup of system dirs --- .gitignore | 1 + .../Constants-SystemDirectories.cs | 26 ++++++++++++++++--- .../Logging/ILoggingConfiguration.cs | 4 +-- .../Logging/Serilog/LoggerConfigExtensions.cs | 12 ++++----- .../Builder/UmbracoBuilderExtensions.cs | 17 ++++++++---- 5 files changed, 44 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index b87d1df346..022acb5db7 100644 --- a/.gitignore +++ b/.gitignore @@ -196,3 +196,4 @@ src/Umbraco.Tests.Integration/umbraco/logs/ src/Umbraco.Tests.Integration/Views/ src/Umbraco.Tests/TEMP/ +/src/Umbraco.Web.UI.NetCore/Umbraco/Data/* diff --git a/src/Umbraco.Core/Constants-SystemDirectories.cs b/src/Umbraco.Core/Constants-SystemDirectories.cs index a86e4171d6..6145f4190b 100644 --- a/src/Umbraco.Core/Constants-SystemDirectories.cs +++ b/src/Umbraco.Core/Constants-SystemDirectories.cs @@ -4,12 +4,30 @@ namespace Umbraco.Core { public static class SystemDirectories { + /// + /// The aspnet bin folder + /// public const string Bin = "~/bin"; + // TODO: Shouldn't this exist underneath /Umbraco in the content root? public const string Config = "~/config"; - public const string Data = "~/Umbraco/Data"; + /// + /// The Umbraco folder that exists at the content root. + /// + /// + /// This is not the same as the Umbraco web folder which is configurable for serving front-end files. + /// + public const string Umbraco = "~/Umbraco"; + /// + /// The Umbraco data folder in the content root + /// + public const string Data = Umbraco + "/Data"; + + /// + /// The Umbraco temp data folder in the content root + /// public const string TempData = Data + "/TEMP"; public const string TempFileUploads = TempData + "/FileUploads"; @@ -30,8 +48,10 @@ namespace Umbraco.Core public const string Preview = Data + "/preview"; - // TODO: This doesn't seem right? - public const string LogFiles= "~/Logs"; + /// + /// The default folder where Umbraco log files are stored + /// + public const string LogFiles = Umbraco + "/Logs"; } } } diff --git a/src/Umbraco.Core/Logging/ILoggingConfiguration.cs b/src/Umbraco.Core/Logging/ILoggingConfiguration.cs index d21a08e688..6590f9fc65 100644 --- a/src/Umbraco.Core/Logging/ILoggingConfiguration.cs +++ b/src/Umbraco.Core/Logging/ILoggingConfiguration.cs @@ -1,10 +1,10 @@ -namespace Umbraco.Core.Logging +namespace Umbraco.Core.Logging { public interface ILoggingConfiguration { /// - /// The physical path where logs are stored + /// Gets the physical path where logs are stored /// string LogDirectory { get; } } diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs b/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs index 84270b95bf..5481f22cb6 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Text; using Serilog; @@ -127,7 +127,7 @@ namespace Umbraco.Core.Logging.Serilog /// Outputs a CLEF format JSON log at /App_Data/Logs/ /// /// A Serilog LoggerConfiguration - /// + /// The logging configuration /// The log level you wish the JSON file to collect - default is Verbose (highest) /// The number of days to keep log files. Default is set to null which means all logs are kept public static LoggerConfiguration OutputDefaultJsonFile( @@ -135,13 +135,13 @@ namespace Umbraco.Core.Logging.Serilog IHostingEnvironment hostingEnvironment, ILoggingConfiguration loggingConfiguration, LogEventLevel minimumLevel = LogEventLevel.Verbose, int? retainedFileCount = null) { - //.clef format (Compact log event format, that can be imported into local SEQ & will make searching/filtering logs easier) - //Ends with ..txt as Date is inserted before file extension substring + // .clef format (Compact log event format, that can be imported into local SEQ & will make searching/filtering logs easier) + // Ends with ..txt as Date is inserted before file extension substring logConfig.WriteTo.File(new CompactJsonFormatter(), Path.Combine(hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.LogFiles) ,$"UmbracoTraceLog.{Environment.MachineName}..json"), shared: true, - rollingInterval: RollingInterval.Day, //Create a new JSON file every day - retainedFileCountLimit: retainedFileCount, //Setting to null means we keep all files - default is 31 days + rollingInterval: RollingInterval.Day, // Create a new JSON file every day + retainedFileCountLimit: retainedFileCount, // Setting to null means we keep all files - default is 31 days restrictedToMinimumLevel: minimumLevel); return logConfig; diff --git a/src/Umbraco.Web.Common/Builder/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Common/Builder/UmbracoBuilderExtensions.cs index f346e0dd79..e72089b8fe 100644 --- a/src/Umbraco.Web.Common/Builder/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Common/Builder/UmbracoBuilderExtensions.cs @@ -53,13 +53,20 @@ namespace Umbraco.Core.DependencyInjection IConfiguration config) { if (services is null) + { throw new ArgumentNullException(nameof(services)); + } + if (config is null) + { throw new ArgumentNullException(nameof(config)); + } - var loggingConfig = new LoggingConfiguration(Path.Combine(webHostEnvironment.ContentRootPath, "umbraco", "logs")); + IHostingEnvironment tempHostingEnvironment = GetTemporaryHostingEnvironment(webHostEnvironment, config); + + var loggingDir = tempHostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.LogFiles); + var loggingConfig = new LoggingConfiguration(loggingDir); - var tempHostingEnvironment = GetTemporaryHostingEnvironment(webHostEnvironment, config); services.AddLogger(tempHostingEnvironment, loggingConfig, config); IHttpContextAccessor httpContextAccessor = new HttpContextAccessor(); @@ -69,11 +76,11 @@ namespace Umbraco.Core.DependencyInjection var appCaches = AppCaches.Create(requestCache); services.AddUnique(appCaches); - var profiler = GetWebProfiler(config); + IProfiler profiler = GetWebProfiler(config); services.AddUnique(profiler); - var loggerFactory = LoggerFactory.Create(cfg => cfg.AddSerilog(Log.Logger, false)); - var typeLoader = services.AddTypeLoader(Assembly.GetEntryAssembly(), webHostEnvironment, tempHostingEnvironment, loggerFactory, appCaches, config, profiler); + ILoggerFactory loggerFactory = LoggerFactory.Create(cfg => cfg.AddSerilog(Log.Logger, false)); + TypeLoader typeLoader = services.AddTypeLoader(Assembly.GetEntryAssembly(), webHostEnvironment, tempHostingEnvironment, loggerFactory, appCaches, config, profiler); return new UmbracoBuilder(services, config, typeLoader, loggerFactory); } From 40a6fa2b898226a8e6c82d695f6bef0bcdaa2632 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 8 Dec 2020 09:19:51 +0100 Subject: [PATCH 08/27] NetCore: Migrate more tests (#9494) * Migrate tests * Cleanup * Migrate tests * post merge fix Signed-off-by: Bjarke Berg --- .../Umbraco.PublishedCache.NuCache.csproj | 11 +- .../TestHelpers}/TestDatabase.cs | 5 +- .../Migrations/AdvancedMigrationTests.cs | 6 +- .../Services/RedirectUrlServiceTests.cs | 49 +- .../Cache/DefaultCachePolicyTests.cs | 11 +- .../Cache/FullDataSetCachePolicyTests.cs | 3 +- .../Umbraco.Core}/Cache/RefresherTests.cs | 2 +- .../Cache/SingleItemsOnlyCachePolicyTests.cs | 3 +- .../PropertyEditors}/ConvertersTests.cs | 108 +- .../Migrations/AlterMigrationTests.cs | 62 +- .../Migrations/MigrationPlanTests.cs | 50 +- .../Migrations/MigrationTests.cs | 69 +- .../Migrations/PostMigrationTests.cs | 54 +- .../Stubs/AlterUserTableMigrationStub.cs | 0 .../Stubs/DropForeignKeyMigrationStub.cs | 0 .../Migrations/Stubs/Dummy.cs | 0 .../Migrations/Stubs/FiveZeroMigration.cs | 0 .../Migrations/Stubs/FourElevenMigration.cs | 0 .../Migrations/Stubs/SixZeroMigration1.cs | 0 .../Migrations/Stubs/SixZeroMigration2.cs | 0 .../SnapDictionaryTests.cs | 5 +- .../Umbraco.Tests.UnitTests.csproj | 1 + .../SqlScripts/SqlCe-SchemaAndData-4110.sql | Bin 422888 -> 0 bytes .../Migrations/SqlScripts/SqlCeTotal-480.sql | 638 ------- .../SqlScripts/SqlResources.Designer.cs | 143 -- .../Migrations/SqlScripts/SqlResources.resx | 130 -- .../SqlScripts/SqlServerTotal-480.sql | 1671 ----------------- src/Umbraco.Tests/Umbraco.Tests.csproj | 31 +- .../Macros/PartialViewMacroPage.cs | 11 - src/Umbraco.Web/Umbraco.Web.csproj | 1 + 30 files changed, 227 insertions(+), 2837 deletions(-) rename src/{Umbraco.Tests/Testing => Umbraco.Tests.Common/TestHelpers}/TestDatabase.cs (99%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration/Umbraco.Infrastructure}/Migrations/AdvancedMigrationTests.cs (97%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration/Umbraco.Infrastructure}/Services/RedirectUrlServiceTests.cs (55%) rename src/{Umbraco.Tests => Umbraco.Tests.UnitTests/Umbraco.Core}/Cache/DefaultCachePolicyTests.cs (91%) rename src/{Umbraco.Tests => Umbraco.Tests.UnitTests/Umbraco.Core}/Cache/FullDataSetCachePolicyTests.cs (99%) rename src/{Umbraco.Tests => Umbraco.Tests.UnitTests/Umbraco.Core}/Cache/RefresherTests.cs (98%) rename src/{Umbraco.Tests => Umbraco.Tests.UnitTests/Umbraco.Core}/Cache/SingleItemsOnlyCachePolicyTests.cs (97%) rename src/{Umbraco.Tests/Published => Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors}/ConvertersTests.cs (62%) rename src/{Umbraco.Tests => Umbraco.Tests.UnitTests/Umbraco.Infrastructure}/Migrations/AlterMigrationTests.cs (61%) rename src/{Umbraco.Tests => Umbraco.Tests.UnitTests/Umbraco.Infrastructure}/Migrations/MigrationPlanTests.cs (83%) rename src/{Umbraco.Tests => Umbraco.Tests.UnitTests/Umbraco.Infrastructure}/Migrations/MigrationTests.cs (55%) rename src/{Umbraco.Tests => Umbraco.Tests.UnitTests/Umbraco.Infrastructure}/Migrations/PostMigrationTests.cs (71%) rename src/{Umbraco.Tests => Umbraco.Tests.UnitTests/Umbraco.Infrastructure}/Migrations/Stubs/AlterUserTableMigrationStub.cs (100%) rename src/{Umbraco.Tests => Umbraco.Tests.UnitTests/Umbraco.Infrastructure}/Migrations/Stubs/DropForeignKeyMigrationStub.cs (100%) rename src/{Umbraco.Tests => Umbraco.Tests.UnitTests/Umbraco.Infrastructure}/Migrations/Stubs/Dummy.cs (100%) rename src/{Umbraco.Tests => Umbraco.Tests.UnitTests/Umbraco.Infrastructure}/Migrations/Stubs/FiveZeroMigration.cs (100%) rename src/{Umbraco.Tests => Umbraco.Tests.UnitTests/Umbraco.Infrastructure}/Migrations/Stubs/FourElevenMigration.cs (100%) rename src/{Umbraco.Tests => Umbraco.Tests.UnitTests/Umbraco.Infrastructure}/Migrations/Stubs/SixZeroMigration1.cs (100%) rename src/{Umbraco.Tests => Umbraco.Tests.UnitTests/Umbraco.Infrastructure}/Migrations/Stubs/SixZeroMigration2.cs (100%) rename src/{Umbraco.Tests/Cache => Umbraco.Tests.UnitTests/Umbraco.PublishedCache.NuCache}/SnapDictionaryTests.cs (99%) delete mode 100644 src/Umbraco.Tests/Migrations/SqlScripts/SqlCe-SchemaAndData-4110.sql delete mode 100644 src/Umbraco.Tests/Migrations/SqlScripts/SqlCeTotal-480.sql delete mode 100644 src/Umbraco.Tests/Migrations/SqlScripts/SqlResources.Designer.cs delete mode 100644 src/Umbraco.Tests/Migrations/SqlScripts/SqlResources.resx delete mode 100644 src/Umbraco.Tests/Migrations/SqlScripts/SqlServerTotal-480.sql delete mode 100644 src/Umbraco.Web/Macros/PartialViewMacroPage.cs diff --git a/src/Umbraco.PublishedCache.NuCache/Umbraco.PublishedCache.NuCache.csproj b/src/Umbraco.PublishedCache.NuCache/Umbraco.PublishedCache.NuCache.csproj index edb68c6b93..9f63604b0e 100644 --- a/src/Umbraco.PublishedCache.NuCache/Umbraco.PublishedCache.NuCache.csproj +++ b/src/Umbraco.PublishedCache.NuCache/Umbraco.PublishedCache.NuCache.csproj @@ -21,12 +21,15 @@ - - <_Parameter1>Umbraco.Tests - + + <_Parameter1>Umbraco.Tests + + + <_Parameter1>Umbraco.Tests.UnitTests + <_Parameter1>Umbraco.Tests.Integration - + <_Parameter1>Umbraco.Tests.Benchmarks diff --git a/src/Umbraco.Tests/Testing/TestDatabase.cs b/src/Umbraco.Tests.Common/TestHelpers/TestDatabase.cs similarity index 99% rename from src/Umbraco.Tests/Testing/TestDatabase.cs rename to src/Umbraco.Tests.Common/TestHelpers/TestDatabase.cs index 7d58433a52..d1e5669100 100644 --- a/src/Umbraco.Tests/Testing/TestDatabase.cs +++ b/src/Umbraco.Tests.Common/TestHelpers/TestDatabase.cs @@ -11,7 +11,6 @@ using NPoco.DatabaseTypes; using NPoco.Linq; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.SqlSyntax; -using Umbraco.Persistance.SqlCe; namespace Umbraco.Tests.Testing { @@ -33,8 +32,8 @@ namespace Umbraco.Tests.Testing /// public TestDatabase(DatabaseType databaseType = null, ISqlSyntaxProvider syntaxProvider = null) { - DatabaseType = databaseType ?? new SqlServerCEDatabaseType(); - SqlContext = new SqlContext(syntaxProvider ?? new SqlCeSyntaxProvider(), DatabaseType, Mock.Of()); + DatabaseType = databaseType ?? new SqlServerDatabaseType(); + SqlContext = new SqlContext(syntaxProvider ?? new SqlServerSyntaxProvider(), DatabaseType, Mock.Of()); } /// diff --git a/src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Migrations/AdvancedMigrationTests.cs similarity index 97% rename from src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs rename to src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Migrations/AdvancedMigrationTests.cs index 474528a8ec..ac502ddf80 100644 --- a/src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Migrations/AdvancedMigrationTests.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.Logging.Abstractions; using Moq; using NUnit.Framework; using Microsoft.Extensions.Logging; +using Umbraco.Core.Configuration; using Umbraco.Core.Migrations; using Umbraco.Core.Migrations.Install; using Umbraco.Core.Migrations.Upgrade; @@ -12,6 +13,7 @@ using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Services; using Umbraco.Tests.Common.Builders; +using Umbraco.Tests.Integration.Testing; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; @@ -19,10 +21,12 @@ namespace Umbraco.Tests.Migrations { [TestFixture] [UmbracoTest(Database = UmbracoTestOptions.Database.NewEmptyPerTest)] - public class AdvancedMigrationTests : TestWithDatabaseBase + public class AdvancedMigrationTests : UmbracoIntegrationTest { private ILoggerFactory _loggerFactory = NullLoggerFactory.Instance; + private IUmbracoVersion UmbracoVersion => GetRequiredService(); + [Test] public void CreateTableOfTDto() { diff --git a/src/Umbraco.Tests/Services/RedirectUrlServiceTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/RedirectUrlServiceTests.cs similarity index 55% rename from src/Umbraco.Tests/Services/RedirectUrlServiceTests.cs rename to src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/RedirectUrlServiceTests.cs index 8f38bd67eb..89cde051e3 100644 --- a/src/Umbraco.Tests/Services/RedirectUrlServiceTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/RedirectUrlServiceTests.cs @@ -1,81 +1,72 @@ -using System; -using System.Linq; +using System.Linq; using System.Threading; using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; using Umbraco.Core.Cache; -using Umbraco.Core.Logging; using Umbraco.Core.Models; - -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Scoping; +using Umbraco.Core.Services; +using Umbraco.Tests.Integration.Testing; using Umbraco.Tests.Testing; -namespace Umbraco.Tests.Services +namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services { [TestFixture] [Apartment(ApartmentState.STA)] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] - public class RedirectUrlServiceTests : TestWithSomeContentBase + public class RedirectUrlServiceTests : UmbracoIntegrationTestWithContent { private IContent _testPage; private IContent _altTestPage; - private string _url = "blah"; - private string _cultureA = "en"; - private string _cultureB = "de"; + private const string Url = "blah"; + private const string CultureA = "en"; + private const string CultureB = "de"; + + private IRedirectUrlService RedirectUrlService => GetRequiredService(); + public override void CreateTestData() { base.CreateTestData(); - using (var scope = ScopeProvider.CreateScope()) + using (IScope scope = ScopeProvider.CreateScope()) { var repository = new RedirectUrlRepository((IScopeAccessor)ScopeProvider, AppCaches.Disabled, Mock.Of>()); - var rootContent = ServiceContext.ContentService.GetRootContent().FirstOrDefault(); - var subPages = ServiceContext.ContentService.GetPagedChildren(rootContent.Id, 0, 2, out _).ToList(); + IContent rootContent = ContentService.GetRootContent().First(); + var subPages = ContentService.GetPagedChildren(rootContent.Id, 0, 2, out _).ToList(); _testPage = subPages[0]; _altTestPage = subPages[1]; repository.Save(new RedirectUrl { ContentKey = _testPage.Key, - Url = _url, - Culture = _cultureA + Url = Url, + Culture = CultureA }); repository.Save(new RedirectUrl { ContentKey = _altTestPage.Key, - Url = _url, - Culture = _cultureB + Url = Url, + Culture = CultureB }); scope.Complete(); } } - [TearDown] - public override void TearDown() - { - base.TearDown(); - } [Test] public void Can_Get_Most_Recent_RedirectUrl() { - var redirectUrlService = ServiceContext.RedirectUrlService; - var redirect = redirectUrlService.GetMostRecentRedirectUrl(_url); + IRedirectUrl redirect = RedirectUrlService.GetMostRecentRedirectUrl(Url); Assert.AreEqual(redirect.ContentId, _altTestPage.Id); - } [Test] public void Can_Get_Most_Recent_RedirectUrl_With_Culture() { - var redirectUrlService = ServiceContext.RedirectUrlService; - var redirect = redirectUrlService.GetMostRecentRedirectUrl(_url, _cultureA); + IRedirectUrl redirect = RedirectUrlService.GetMostRecentRedirectUrl(Url, CultureA); Assert.AreEqual(redirect.ContentId, _testPage.Id); - } - } } diff --git a/src/Umbraco.Tests/Cache/DefaultCachePolicyTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/DefaultCachePolicyTests.cs similarity index 91% rename from src/Umbraco.Tests/Cache/DefaultCachePolicyTests.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/DefaultCachePolicyTests.cs index 74aba2b824..a8592356e9 100644 --- a/src/Umbraco.Tests/Cache/DefaultCachePolicyTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/DefaultCachePolicyTests.cs @@ -1,13 +1,12 @@ using System; using System.Collections.Generic; -using System.Web.Caching; using Moq; using NUnit.Framework; using Umbraco.Core.Cache; using Umbraco.Core.Models; using Umbraco.Core.Scoping; -namespace Umbraco.Tests.Cache +namespace Umbraco.Tests.UnitTests.Umbraco.Core.Cache { [TestFixture] public class DefaultCachePolicyTests @@ -37,7 +36,7 @@ namespace Umbraco.Tests.Cache var defaultPolicy = new DefaultRepositoryCachePolicy(cache.Object, DefaultAccessor, new RepositoryCachePolicyOptions()); - var unused = defaultPolicy.Get(1, id => new AuditItem(1, AuditType.Copy, 123, "test", "blah"), o => null); + AuditItem unused = defaultPolicy.Get(1, id => new AuditItem(1, AuditType.Copy, 123, "test", "blah"), o => null); Assert.IsTrue(isCached); } @@ -49,7 +48,7 @@ namespace Umbraco.Tests.Cache var defaultPolicy = new DefaultRepositoryCachePolicy(cache.Object, DefaultAccessor, new RepositoryCachePolicyOptions()); - var found = defaultPolicy.Get(1, id => null, ids => null); + AuditItem found = defaultPolicy.Get(1, id => null, ids => null); Assert.IsNotNull(found); } @@ -67,7 +66,7 @@ namespace Umbraco.Tests.Cache var defaultPolicy = new DefaultRepositoryCachePolicy(cache.Object, DefaultAccessor, new RepositoryCachePolicyOptions()); - var unused = defaultPolicy.GetAll(new object[] {}, ids => new[] + AuditItem[] unused = defaultPolicy.GetAll(new object[] {}, ids => new[] { new AuditItem(1, AuditType.Copy, 123, "test", "blah"), new AuditItem(2, AuditType.Copy, 123, "test", "blah2") @@ -88,7 +87,7 @@ namespace Umbraco.Tests.Cache var defaultPolicy = new DefaultRepositoryCachePolicy(cache.Object, DefaultAccessor, new RepositoryCachePolicyOptions()); - var found = defaultPolicy.GetAll(new object[] {}, ids => new[] { (AuditItem)null }); + AuditItem[] found = defaultPolicy.GetAll(new object[] {}, ids => new[] { (AuditItem)null }); Assert.AreEqual(2, found.Length); } diff --git a/src/Umbraco.Tests/Cache/FullDataSetCachePolicyTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/FullDataSetCachePolicyTests.cs similarity index 99% rename from src/Umbraco.Tests/Cache/FullDataSetCachePolicyTests.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/FullDataSetCachePolicyTests.cs index 027f6d2d69..e904f9104e 100644 --- a/src/Umbraco.Tests/Cache/FullDataSetCachePolicyTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/FullDataSetCachePolicyTests.cs @@ -2,7 +2,6 @@ using System.Collections; using System.Collections.Generic; using System.Linq; -using System.Web.Caching; using Moq; using NUnit.Framework; using Umbraco.Core.Cache; @@ -10,7 +9,7 @@ using Umbraco.Core.Collections; using Umbraco.Core.Models; using Umbraco.Core.Scoping; -namespace Umbraco.Tests.Cache +namespace Umbraco.Tests.UnitTests.Umbraco.Core.Cache { [TestFixture] public class FullDataSetCachePolicyTests diff --git a/src/Umbraco.Tests/Cache/RefresherTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/RefresherTests.cs similarity index 98% rename from src/Umbraco.Tests/Cache/RefresherTests.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/RefresherTests.cs index eb8580c9e2..59d2f010d2 100644 --- a/src/Umbraco.Tests/Cache/RefresherTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/RefresherTests.cs @@ -4,7 +4,7 @@ using NUnit.Framework; using Umbraco.Core.Services.Changes; using Umbraco.Web.Cache; -namespace Umbraco.Tests.Cache +namespace Umbraco.Tests.UnitTests.Umbraco.Core.Cache { [TestFixture] public class RefreshersTests diff --git a/src/Umbraco.Tests/Cache/SingleItemsOnlyCachePolicyTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/SingleItemsOnlyCachePolicyTests.cs similarity index 97% rename from src/Umbraco.Tests/Cache/SingleItemsOnlyCachePolicyTests.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/SingleItemsOnlyCachePolicyTests.cs index 335335e391..323b83699c 100644 --- a/src/Umbraco.Tests/Cache/SingleItemsOnlyCachePolicyTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Cache/SingleItemsOnlyCachePolicyTests.cs @@ -1,13 +1,12 @@ using System; using System.Collections.Generic; -using System.Web.Caching; using Moq; using NUnit.Framework; using Umbraco.Core.Cache; using Umbraco.Core.Models; using Umbraco.Core.Scoping; -namespace Umbraco.Tests.Cache +namespace Umbraco.Tests.UnitTests.Umbraco.Core.Cache { [TestFixture] public class SingleItemsOnlyCachePolicyTests diff --git a/src/Umbraco.Tests/Published/ConvertersTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/ConvertersTests.cs similarity index 62% rename from src/Umbraco.Tests/Published/ConvertersTests.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/ConvertersTests.cs index 840ec58f13..6db561dfe9 100644 --- a/src/Umbraco.Tests/Published/ConvertersTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/ConvertersTests.cs @@ -14,9 +14,9 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; -using Umbraco.Tests.PublishedContent; +using Umbraco.Tests.Common.PublishedContent; using Umbraco.Tests.TestHelpers; -using Umbraco.Web; +using Umbraco.Tests.UnitTests.TestHelpers; using Umbraco.Web.PublishedCache; namespace Umbraco.Tests.Published @@ -24,13 +24,10 @@ namespace Umbraco.Tests.Published [TestFixture] public class ConvertersTests { - #region SimpleConverter3 - [Test] public void SimpleConverter3Test() { - // Current.Reset(); - var register = TestHelper.GetRegister(); + var register = new ServiceCollection(); var composition = new UmbracoBuilder(register, Mock.Of(), TestHelper.GetMockedTypeLoader()); @@ -38,37 +35,41 @@ namespace Umbraco.Tests.Published .Append() .Append(); - IPublishedModelFactory factory = new PublishedModelFactory(new[] - { - typeof (PublishedSnapshotTestObjects.TestElementModel1), typeof (PublishedSnapshotTestObjects.TestElementModel2), - typeof (PublishedSnapshotTestObjects.TestContentModel1), typeof (PublishedSnapshotTestObjects.TestContentModel2), - }, Mock.Of()); + IPublishedModelFactory factory = new PublishedModelFactory( + new[] + { + typeof(PublishedSnapshotTestObjects.TestElementModel1), + typeof(PublishedSnapshotTestObjects.TestElementModel2), + typeof(PublishedSnapshotTestObjects.TestContentModel1), + typeof(PublishedSnapshotTestObjects.TestContentModel2) + }, Mock.Of()); register.AddTransient(f => factory); - var cacheMock = new Mock(); var cacheContent = new Dictionary(); - cacheMock.Setup(x => x.GetById(It.IsAny())).Returns(id => cacheContent.TryGetValue(id, out IPublishedContent content) ? content : null); + cacheMock.Setup(x => x.GetById(It.IsAny())).Returns(id => + cacheContent.TryGetValue(id, out IPublishedContent content) ? content : null); var publishedSnapshotMock = new Mock(); publishedSnapshotMock.Setup(x => x.Content).Returns(cacheMock.Object); var publishedSnapshotAccessorMock = new Mock(); publishedSnapshotAccessorMock.Setup(x => x.PublishedSnapshot).Returns(publishedSnapshotMock.Object); register.AddTransient(f => publishedSnapshotAccessorMock.Object); - var registerFactory = composition.CreateServiceProvider(); - var converters = registerFactory.GetRequiredService(); + IServiceProvider registerFactory = composition.CreateServiceProvider(); + PropertyValueConverterCollection converters = + registerFactory.GetRequiredService(); var serializer = new ConfigurationEditorJsonSerializer(); var dataTypeServiceMock = new Mock(); var dataType1 = new DataType(new VoidEditor(NullLoggerFactory.Instance, dataTypeServiceMock.Object, - Mock.Of(), Mock.Of(), Mock.Of()), serializer) - { Id = 1 }; + Mock.Of(), Mock.Of(), Mock.Of()), + serializer) { Id = 1 }; var dataType2 = new DataType(new VoidEditor("2", NullLoggerFactory.Instance, Mock.Of(), - Mock.Of(), Mock.Of(), Mock.Of()), serializer) - { Id = 2 }; + Mock.Of(), Mock.Of(), Mock.Of()), + serializer) { Id = 2 }; - dataTypeServiceMock.Setup(x => x.GetAll()).Returns(new []{dataType1, dataType2 }); + dataTypeServiceMock.Setup(x => x.GetAll()).Returns(new[] { dataType1, dataType2 }); var contentTypeFactory = new PublishedContentTypeFactory(factory, converters, dataTypeServiceMock.Object); @@ -77,52 +78,69 @@ namespace Umbraco.Tests.Published yield return contentTypeFactory.CreatePropertyType(contentType, "prop" + i, i); } - var elementType1 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "element1", t => CreatePropertyTypes(t, 1)); - var elementType2 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1001, "element2", t => CreatePropertyTypes(t, 2)); - var contentType1 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1002, "content1", t => CreatePropertyTypes(t, 1)); - var contentType2 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1003, "content2", t => CreatePropertyTypes(t, 2)); + IPublishedContentType elementType1 = + contentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "element1", t => CreatePropertyTypes(t, 1)); + IPublishedContentType elementType2 = + contentTypeFactory.CreateContentType(Guid.NewGuid(), 1001, "element2", t => CreatePropertyTypes(t, 2)); + IPublishedContentType contentType1 = + contentTypeFactory.CreateContentType(Guid.NewGuid(), 1002, "content1", t => CreatePropertyTypes(t, 1)); + IPublishedContentType contentType2 = + contentTypeFactory.CreateContentType(Guid.NewGuid(), 1003, "content2", t => CreatePropertyTypes(t, 2)); - var element1 = new PublishedElement(elementType1, Guid.NewGuid(), new Dictionary { { "prop1", "val1" } }, false); - var element2 = new PublishedElement(elementType2, Guid.NewGuid(), new Dictionary { { "prop2", "1003" } }, false); + var element1 = new PublishedElement(elementType1, Guid.NewGuid(), + new Dictionary { { "prop1", "val1" } }, false); + var element2 = new PublishedElement(elementType2, Guid.NewGuid(), + new Dictionary { { "prop2", "1003" } }, false); var cnt1 = new SolidPublishedContent(contentType1) { Id = 1003, - Properties = new[] { new SolidPublishedProperty { Alias = "prop1", SolidHasValue = true, SolidValue = "val1" } } + Properties = new[] + { + new SolidPublishedProperty { Alias = "prop1", SolidHasValue = true, SolidValue = "val1" } + } }; var cnt2 = new SolidPublishedContent(contentType1) { Id = 1004, - Properties = new[] { new SolidPublishedProperty { Alias = "prop2", SolidHasValue = true, SolidValue = "1003" } } + Properties = new[] + { + new SolidPublishedProperty { Alias = "prop2", SolidHasValue = true, SolidValue = "1003" } + } }; - var publishedModelFactory = registerFactory.GetRequiredService(); + IPublishedModelFactory publishedModelFactory = registerFactory.GetRequiredService(); cacheContent[cnt1.Id] = cnt1.CreateModel(publishedModelFactory); cacheContent[cnt2.Id] = cnt2.CreateModel(publishedModelFactory); // can get the actual property Clr type // ie ModelType gets properly mapped by IPublishedContentModelFactory // must test ModelClrType with special equals 'cos they are not ref-equals - Assert.IsTrue(ModelType.Equals(typeof(IEnumerable<>).MakeGenericType(ModelType.For("content1")), contentType2.GetPropertyType("prop2").ModelClrType)); - Assert.AreEqual(typeof(IEnumerable), contentType2.GetPropertyType("prop2").ClrType); + Assert.IsTrue(ModelType.Equals(typeof(IEnumerable<>).MakeGenericType(ModelType.For("content1")), + contentType2.GetPropertyType("prop2").ModelClrType)); + Assert.AreEqual(typeof(IEnumerable), + contentType2.GetPropertyType("prop2").ClrType); // can create a model for an element - var model1 = factory.CreateModel(element1); + IPublishedElement model1 = factory.CreateModel(element1); Assert.IsInstanceOf(model1); Assert.AreEqual("val1", ((PublishedSnapshotTestObjects.TestElementModel1)model1).Prop1); // can create a model for a published content - var model2 = factory.CreateModel(element2); + IPublishedElement model2 = factory.CreateModel(element2); Assert.IsInstanceOf(model2); var mmodel2 = (PublishedSnapshotTestObjects.TestElementModel2)model2; // and get direct property - Assert.IsInstanceOf(model2.Value(Mock.Of(), "prop2")); - Assert.AreEqual(1, ((PublishedSnapshotTestObjects.TestContentModel1[])model2.Value(Mock.Of(), "prop2")).Length); + Assert.IsInstanceOf( + model2.Value(Mock.Of(), "prop2")); + Assert.AreEqual(1, + ((PublishedSnapshotTestObjects.TestContentModel1[])model2.Value(Mock.Of(), + "prop2")).Length); // and get model property Assert.IsInstanceOf>(mmodel2.Prop2); Assert.IsInstanceOf(mmodel2.Prop2); - var mmodel1 = mmodel2.Prop2.First(); + PublishedSnapshotTestObjects.TestContentModel1 mmodel1 = mmodel2.Prop2.First(); // and we get what we want Assert.AreSame(cacheContent[mmodel1.Id], mmodel1); @@ -144,10 +162,8 @@ namespace Umbraco.Tests.Published { private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor; - public SimpleConverter3B(IPublishedSnapshotAccessor publishedSnapshotAccessor) - { + public SimpleConverter3B(IPublishedSnapshotAccessor publishedSnapshotAccessor) => _publishedSnapshotAccessor = publishedSnapshotAccessor; - } public override bool IsConverter(IPublishedPropertyType propertyType) => propertyType.EditorAlias == "Umbraco.Void.2"; @@ -158,18 +174,18 @@ namespace Umbraco.Tests.Published public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Elements; - public override object ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object source, bool preview) + public override object ConvertSourceToIntermediate(IPublishedElement owner, + IPublishedPropertyType propertyType, object source, bool preview) { var s = source as string; return s?.Split(',').Select(int.Parse).ToArray() ?? Array.Empty(); } - public override object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview) - { - return ((int[])inter).Select(x => (PublishedSnapshotTestObjects.TestContentModel1)_publishedSnapshotAccessor.PublishedSnapshot.Content.GetById(x)).ToArray(); - } + public override object ConvertIntermediateToObject(IPublishedElement owner, + IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, + bool preview) => ((int[])inter).Select(x => + (PublishedSnapshotTestObjects.TestContentModel1)_publishedSnapshotAccessor.PublishedSnapshot.Content + .GetById(x)).ToArray(); } - - #endregion } } diff --git a/src/Umbraco.Tests/Migrations/AlterMigrationTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/AlterMigrationTests.cs similarity index 61% rename from src/Umbraco.Tests/Migrations/AlterMigrationTests.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/AlterMigrationTests.cs index 2d8dd7d18e..23ee3e143a 100644 --- a/src/Umbraco.Tests/Migrations/AlterMigrationTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/AlterMigrationTests.cs @@ -1,39 +1,20 @@ using System; using System.Diagnostics; -using System.Data.Common; using System.Linq; using Microsoft.Extensions.Logging; using Moq; -using NPoco; using NUnit.Framework; -using Umbraco.Core; using Umbraco.Core.Migrations; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.SqlSyntax; -using Umbraco.Persistance.SqlCe; using Umbraco.Tests.Migrations.Stubs; -using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; -namespace Umbraco.Tests.Migrations +namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Migrations { [TestFixture] public class AlterMigrationTests { - private ILogger _logger; - private ISqlSyntaxProvider _sqlSyntax; - private IUmbracoDatabase _database; + private readonly ILogger _logger = Mock.Of>(); - [SetUp] - public void Setup() - { - _logger = Mock.Of>(); - _sqlSyntax = new SqlCeSyntaxProvider(); - - var dbProviderFactory = DbProviderFactories.GetFactory(Constants.DbProviderNames.SqlServer); - var sqlContext = new SqlContext(_sqlSyntax, DatabaseType.SqlServer2008, Mock.Of()); - _database = new UmbracoDatabase("cstr", sqlContext, dbProviderFactory, Mock.Of>(), TestHelper.BulkSqlInsertProvider); - } [Test] public void Drop_Foreign_Key() @@ -46,13 +27,15 @@ namespace Umbraco.Tests.Migrations // Act stub.Migrate(); - foreach (var op in database.Operations) + foreach (TestDatabase.Operation op in database.Operations) + { Console.WriteLine("{0}\r\n\t{1}", op.Text, op.Sql); + } // Assert Assert.That(database.Operations.Count, Is.EqualTo(1)); - Assert.That(database.Operations[0].Sql, Is.EqualTo("ALTER TABLE [umbracoUser2app] DROP CONSTRAINT [FK_umbracoUser2app_umbracoUser_id]")); - + Assert.That(database.Operations[0].Sql, + Is.EqualTo("ALTER TABLE [umbracoUser2app] DROP CONSTRAINT [FK_umbracoUser2app_umbracoUser_id]")); } [Test] @@ -64,23 +47,24 @@ namespace Umbraco.Tests.Migrations migration.Migrate(); - foreach (var op in database.Operations) + foreach (TestDatabase.Operation op in database.Operations) + { Console.WriteLine("{0}\r\n\t{1}", op.Text, op.Sql); + } Assert.That(database.Operations.Count, Is.EqualTo(1)); - Assert.That(database.Operations[0].Sql, Is.EqualTo("ALTER TABLE [bar] ADD [foo] UniqueIdentifier NOT NULL")); + Assert.That(database.Operations[0].Sql, + Is.EqualTo("ALTER TABLE [bar] ADD [foo] UniqueIdentifier NOT NULL")); } public class CreateColumnMigration : MigrationBase { public CreateColumnMigration(IMigrationContext context) : base(context) - { } - - public override void Migrate() { - Alter.Table("bar").AddColumn("foo").AsGuid().Do(); } + + public override void Migrate() => Alter.Table("bar").AddColumn("foo").AsGuid().Do(); } [Test] @@ -92,28 +76,30 @@ namespace Umbraco.Tests.Migrations migration.Migrate(); - foreach (var op in database.Operations) + foreach (TestDatabase.Operation op in database.Operations) + { Console.WriteLine("{0}\r\n\t{1}", op.Text, op.Sql); + } Assert.That(database.Operations.Count, Is.EqualTo(1)); - Assert.That(database.Operations[0].Sql, Is.EqualTo("ALTER TABLE [bar] ALTER COLUMN [foo] UniqueIdentifier NOT NULL")); + Assert.That(database.Operations[0].Sql, + Is.EqualTo("ALTER TABLE [bar] ALTER COLUMN [foo] UniqueIdentifier NOT NULL")); } public class AlterColumnMigration : MigrationBase { public AlterColumnMigration(IMigrationContext context) : base(context) - { } - - public override void Migrate() { + } + + public override void Migrate() => // bad/good syntax... //Alter.Column("foo").OnTable("bar").AsGuid().NotNullable(); Alter.Table("bar").AlterColumn("foo").AsGuid().NotNullable().Do(); - } } - [NUnit.Framework.Ignore("this doesn't actually test anything")] + [Ignore("this doesn't actually test anything")] [Test] public void Can_Get_Up_Migration_From_MigrationStub() { @@ -131,7 +117,7 @@ namespace Umbraco.Tests.Migrations //Console output Debug.Print("Number of expressions in context: {0}", database.Operations.Count); Debug.Print(""); - foreach (var expression in database.Operations) + foreach (TestDatabase.Operation expression in database.Operations) { Debug.Print(expression.ToString()); } diff --git a/src/Umbraco.Tests/Migrations/MigrationPlanTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/MigrationPlanTests.cs similarity index 83% rename from src/Umbraco.Tests/Migrations/MigrationPlanTests.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/MigrationPlanTests.cs index 0a8c6cfb3f..0511ee6290 100644 --- a/src/Umbraco.Tests/Migrations/MigrationPlanTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/MigrationPlanTests.cs @@ -10,14 +10,13 @@ using Umbraco.Core; using Umbraco.Core.Migrations; using Umbraco.Core.Migrations.Upgrade; using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Scoping; using Umbraco.Core.Services; -using Umbraco.Persistance.SqlCe; -using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; -namespace Umbraco.Tests.Migrations +namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Migrations { [TestFixture] public class MigrationPlanTests @@ -25,18 +24,19 @@ namespace Umbraco.Tests.Migrations [Test] public void CanExecute() { - var loggerFactory = NullLoggerFactory.Instance; + NullLoggerFactory loggerFactory = NullLoggerFactory.Instance; var database = new TestDatabase(); - var scope = Mock.Of(); + IScope scope = Mock.Of(); Mock.Get(scope) .Setup(x => x.Database) .Returns(database); - var sqlContext = new SqlContext(new SqlCeSyntaxProvider(), DatabaseType.SQLCe, Mock.Of()); + var sqlContext = new SqlContext(new SqlServerSyntaxProvider(), DatabaseType.SQLCe, + Mock.Of()); var scopeProvider = new MigrationTests.TestScopeProvider(scope) { SqlContext = sqlContext }; - var migrationBuilder = Mock.Of(); + IMigrationBuilder migrationBuilder = Mock.Of(); Mock.Get(migrationBuilder) .Setup(x => x.Build(It.IsAny(), It.IsAny())) .Returns((t, c) => @@ -52,22 +52,24 @@ namespace Umbraco.Tests.Migrations } }); - var plan = new MigrationPlan("default") + MigrationPlan plan = new MigrationPlan("default") .From(string.Empty) .To("{4A9A1A8F-0DA1-4BCF-AD06-C19D79152E35}") .To("VERSION.33"); - var kvs = Mock.Of(); - Mock.Get(kvs).Setup(x => x.GetValue(It.IsAny())).Returns(k => k == "Umbraco.Tests.MigrationPlan" ? string.Empty : null); + IKeyValueService kvs = Mock.Of(); + Mock.Get(kvs).Setup(x => x.GetValue(It.IsAny())) + .Returns(k => k == "Umbraco.Tests.MigrationPlan" ? string.Empty : null); string state; - using (var s = scopeProvider.CreateScope()) + using (IScope s = scopeProvider.CreateScope()) { // read current state var sourceState = kvs.GetValue("Umbraco.Tests.MigrationPlan") ?? string.Empty; // execute plan - state = plan.Execute(s, sourceState, migrationBuilder, loggerFactory.CreateLogger(), loggerFactory); + state = plan.Execute(s, sourceState, migrationBuilder, loggerFactory.CreateLogger(), + loggerFactory); // save new state kvs.SetValue("Umbraco.Tests.MigrationPlan", sourceState, state); @@ -178,11 +180,11 @@ namespace Umbraco.Tests.Migrations .From(string.Empty) .To("aaa") .Merge() - .To("bbb") - .To("ccc") + .To("bbb") + .To("ccc") .With() - .To("ddd") - .To("eee") + .To("ddd") + .To("eee") .As("fff") .To("ggg"); @@ -198,8 +200,12 @@ namespace Umbraco.Tests.Migrations { Assert.AreEqual(expected.Length, states.Count, string.Join(", ", states)); for (var i = 0; i < expected.Length; i++) + { if (expected[i] != "*") + { Assert.AreEqual(expected[i], states[i], "at:" + i); + } + } } private void WritePlanToConsole(MigrationPlan plan) @@ -207,21 +213,23 @@ namespace Umbraco.Tests.Migrations var final = plan.Transitions.First(x => x.Value == null).Key; Console.WriteLine("plan \"{0}\" to final state \"{1}\":", plan.Name, final); - foreach (var (_, transition) in plan.Transitions) + foreach ((var _, MigrationPlan.Transition transition) in plan.Transitions) + { if (transition != null) + { Console.WriteLine(transition); + } + } } public class DeleteRedirectUrlTable : MigrationBase { public DeleteRedirectUrlTable(IMigrationContext context) : base(context) - { } - - public override void Migrate() { - Delete.Table("umbracoRedirectUrl").Do(); } + + public override void Migrate() => Delete.Table("umbracoRedirectUrl").Do(); } } } diff --git a/src/Umbraco.Tests/Migrations/MigrationTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/MigrationTests.cs similarity index 55% rename from src/Umbraco.Tests/Migrations/MigrationTests.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/MigrationTests.cs index 46d9b04b1b..34093d0bce 100644 --- a/src/Umbraco.Tests/Migrations/MigrationTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/MigrationTests.cs @@ -1,18 +1,14 @@ using System; -using System.Collections.Generic; using System.Data; using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; -using Semver; using Umbraco.Core.Events; using Umbraco.Core.Migrations; -using Umbraco.Core.Migrations.Upgrade; using Umbraco.Core.Persistence; using Umbraco.Core.Scoping; -using Umbraco.Core.Services; -namespace Umbraco.Tests.Migrations +namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Migrations { [TestFixture] public class MigrationTests @@ -21,35 +17,30 @@ namespace Umbraco.Tests.Migrations { private readonly IScope _scope; - public TestScopeProvider(IScope scope) - { - _scope = scope; - } + public TestScopeProvider(IScope scope) => _scope = scope; - public IScope CreateScope(IsolationLevel isolationLevel = IsolationLevel.Unspecified, RepositoryCacheMode repositoryCacheMode = RepositoryCacheMode.Unspecified, IEventDispatcher eventDispatcher = null, bool? scopeFileSystems = null, bool callContext = false, bool autoComplete = false) - { - return _scope; - } + public IScope CreateScope( + IsolationLevel isolationLevel = IsolationLevel.Unspecified, + RepositoryCacheMode repositoryCacheMode = RepositoryCacheMode.Unspecified, + IEventDispatcher eventDispatcher = null, + bool? scopeFileSystems = null, + bool callContext = false, + bool autoComplete = false) => _scope; - public IScope CreateDetachedScope(IsolationLevel isolationLevel = IsolationLevel.Unspecified, RepositoryCacheMode repositoryCacheMode = RepositoryCacheMode.Unspecified, IEventDispatcher eventDispatcher = null, bool? scopeFileSystems = null) - { - throw new NotImplementedException(); - } + public IScope CreateDetachedScope( + IsolationLevel isolationLevel = IsolationLevel.Unspecified, + RepositoryCacheMode repositoryCacheMode = RepositoryCacheMode.Unspecified, + IEventDispatcher eventDispatcher = null, + bool? scopeFileSystems = null) => throw new NotImplementedException(); - public void AttachScope(IScope scope, bool callContext = false) - { - throw new NotImplementedException(); - } - - public IScope DetachScope() - { - throw new NotImplementedException(); - } + public void AttachScope(IScope scope, bool callContext = false) => throw new NotImplementedException(); + public IScope DetachScope() => throw new NotImplementedException(); public IScopeContext Context { get; set; } - public ISqlContext SqlContext { get; set; } + + public ISqlContext SqlContext { get; set; } #if DEBUG_SCOPES public ScopeInfo GetScopeInfo(IScope scope) @@ -63,7 +54,8 @@ namespace Umbraco.Tests.Migrations [Test] public void RunGoodMigration() { - var migrationContext = new MigrationContext(Mock.Of(), Mock.Of>()); + var migrationContext = + new MigrationContext(Mock.Of(), Mock.Of>()); IMigration migration = new GoodMigration(migrationContext); migration.Migrate(); } @@ -71,7 +63,8 @@ namespace Umbraco.Tests.Migrations [Test] public void DetectBadMigration1() { - var migrationContext = new MigrationContext(Mock.Of(), Mock.Of>()); + var migrationContext = + new MigrationContext(Mock.Of(), Mock.Of>()); IMigration migration = new BadMigration1(migrationContext); Assert.Throws(() => migration.Migrate()); } @@ -79,7 +72,8 @@ namespace Umbraco.Tests.Migrations [Test] public void DetectBadMigration2() { - var migrationContext = new MigrationContext(Mock.Of(), Mock.Of>()); + var migrationContext = + new MigrationContext(Mock.Of(), Mock.Of>()); IMigration migration = new BadMigration2(migrationContext); Assert.Throws(() => migration.Migrate()); } @@ -88,31 +82,28 @@ namespace Umbraco.Tests.Migrations { public GoodMigration(IMigrationContext context) : base(context) - { } - - public override void Migrate() { - Execute.Sql("").Do(); } + + public override void Migrate() => Execute.Sql("").Do(); } public class BadMigration1 : MigrationBase { public BadMigration1(IMigrationContext context) : base(context) - { } - - public override void Migrate() { - Alter.Table("foo"); // stop here, don't Do it } + + public override void Migrate() => Alter.Table("foo"); // stop here, don't Do it } public class BadMigration2 : MigrationBase { public BadMigration2(IMigrationContext context) : base(context) - { } + { + } public override void Migrate() { diff --git a/src/Umbraco.Tests/Migrations/PostMigrationTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/PostMigrationTests.cs similarity index 71% rename from src/Umbraco.Tests/Migrations/PostMigrationTests.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/PostMigrationTests.cs index ba265b3fd2..2b3e626d03 100644 --- a/src/Umbraco.Tests/Migrations/PostMigrationTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/PostMigrationTests.cs @@ -1,6 +1,6 @@ using System; -using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Moq; using NPoco; using NUnit.Framework; @@ -10,19 +10,19 @@ using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Scoping; using Umbraco.Core.Services; -using Umbraco.Persistance.SqlCe; using Umbraco.Tests.Testing; -namespace Umbraco.Tests.Migrations +namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Migrations { [TestFixture] public class PostMigrationTests { - private static ILoggerFactory _loggerFactory = NullLoggerFactory.Instance; + private static readonly ILoggerFactory s_loggerFactory = NullLoggerFactory.Instance; + [Test] public void ExecutesPlanPostMigration() { - var builder = Mock.Of(); + IMigrationBuilder builder = Mock.Of(); Mock.Get(builder) .Setup(x => x.Build(It.IsAny(), It.IsAny())) .Returns((t, c) => @@ -39,22 +39,30 @@ namespace Umbraco.Tests.Migrations }); var database = new TestDatabase(); - var scope = Mock.Of(); + IScope scope = Mock.Of(); Mock.Get(scope) .Setup(x => x.Database) .Returns(database); - var sqlContext = new SqlContext(new SqlCeSyntaxProvider(), DatabaseType.SQLCe, Mock.Of()); + var sqlContext = new SqlContext( + new SqlServerSyntaxProvider(), + DatabaseType.SQLCe, + Mock.Of()); var scopeProvider = new MigrationTests.TestScopeProvider(scope) { SqlContext = sqlContext }; - var plan = new MigrationPlan("Test") + MigrationPlan plan = new MigrationPlan("Test") .From(string.Empty).To("done"); plan.AddPostMigration(); TestPostMigration.MigrateCount = 0; var upgrader = new Upgrader(plan); - upgrader.Execute(scopeProvider, builder, Mock.Of(), _loggerFactory.CreateLogger(), _loggerFactory); + upgrader.Execute( + scopeProvider, + builder, + Mock.Of(), + s_loggerFactory.CreateLogger(), + s_loggerFactory); Assert.AreEqual(1, TestPostMigration.MigrateCount); } @@ -62,7 +70,7 @@ namespace Umbraco.Tests.Migrations [Test] public void MigrationCanAddPostMigration() { - var builder = Mock.Of(); + IMigrationBuilder builder = Mock.Of(); Mock.Get(builder) .Setup(x => x.Build(It.IsAny(), It.IsAny())) .Returns((t, c) => @@ -81,24 +89,32 @@ namespace Umbraco.Tests.Migrations }); var database = new TestDatabase(); - var scope = Mock.Of(); + IScope scope = Mock.Of(); Mock.Get(scope) .Setup(x => x.Database) .Returns(database); - var sqlContext = new SqlContext(new SqlCeSyntaxProvider(), DatabaseType.SQLCe, Mock.Of()); + var sqlContext = new SqlContext( + new SqlServerSyntaxProvider(), + DatabaseType.SQLCe, + Mock.Of()); var scopeProvider = new MigrationTests.TestScopeProvider(scope) { SqlContext = sqlContext }; - var plan = new MigrationPlan("Test") + MigrationPlan plan = new MigrationPlan("Test") .From(string.Empty).To("done"); TestMigration.MigrateCount = 0; TestPostMigration.MigrateCount = 0; - new MigrationContext(database, _loggerFactory.CreateLogger()); + new MigrationContext(database, s_loggerFactory.CreateLogger()); var upgrader = new Upgrader(plan); - upgrader.Execute(scopeProvider, builder, Mock.Of(), _loggerFactory.CreateLogger(), _loggerFactory); + upgrader.Execute( + scopeProvider, + builder, + Mock.Of(), + s_loggerFactory.CreateLogger(), + s_loggerFactory); Assert.AreEqual(1, TestMigration.MigrateCount); Assert.AreEqual(1, TestPostMigration.MigrateCount); @@ -108,7 +124,8 @@ namespace Umbraco.Tests.Migrations { public TestMigration(IMigrationContext context) : base(context) - { } + { + } public static int MigrateCount { get; set; } @@ -124,10 +141,7 @@ namespace Umbraco.Tests.Migrations { public static int MigrateCount { get; set; } - public void Migrate() - { - MigrateCount++; - } + public void Migrate() => MigrateCount++; } } } diff --git a/src/Umbraco.Tests/Migrations/Stubs/AlterUserTableMigrationStub.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/Stubs/AlterUserTableMigrationStub.cs similarity index 100% rename from src/Umbraco.Tests/Migrations/Stubs/AlterUserTableMigrationStub.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/Stubs/AlterUserTableMigrationStub.cs diff --git a/src/Umbraco.Tests/Migrations/Stubs/DropForeignKeyMigrationStub.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/Stubs/DropForeignKeyMigrationStub.cs similarity index 100% rename from src/Umbraco.Tests/Migrations/Stubs/DropForeignKeyMigrationStub.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/Stubs/DropForeignKeyMigrationStub.cs diff --git a/src/Umbraco.Tests/Migrations/Stubs/Dummy.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/Stubs/Dummy.cs similarity index 100% rename from src/Umbraco.Tests/Migrations/Stubs/Dummy.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/Stubs/Dummy.cs diff --git a/src/Umbraco.Tests/Migrations/Stubs/FiveZeroMigration.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/Stubs/FiveZeroMigration.cs similarity index 100% rename from src/Umbraco.Tests/Migrations/Stubs/FiveZeroMigration.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/Stubs/FiveZeroMigration.cs diff --git a/src/Umbraco.Tests/Migrations/Stubs/FourElevenMigration.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/Stubs/FourElevenMigration.cs similarity index 100% rename from src/Umbraco.Tests/Migrations/Stubs/FourElevenMigration.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/Stubs/FourElevenMigration.cs diff --git a/src/Umbraco.Tests/Migrations/Stubs/SixZeroMigration1.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/Stubs/SixZeroMigration1.cs similarity index 100% rename from src/Umbraco.Tests/Migrations/Stubs/SixZeroMigration1.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/Stubs/SixZeroMigration1.cs diff --git a/src/Umbraco.Tests/Migrations/Stubs/SixZeroMigration2.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/Stubs/SixZeroMigration2.cs similarity index 100% rename from src/Umbraco.Tests/Migrations/Stubs/SixZeroMigration2.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Migrations/Stubs/SixZeroMigration2.cs diff --git a/src/Umbraco.Tests/Cache/SnapDictionaryTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.PublishedCache.NuCache/SnapDictionaryTests.cs similarity index 99% rename from src/Umbraco.Tests/Cache/SnapDictionaryTests.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.PublishedCache.NuCache/SnapDictionaryTests.cs index 739268b451..91317848c6 100644 --- a/src/Umbraco.Tests/Cache/SnapDictionaryTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.PublishedCache.NuCache/SnapDictionaryTests.cs @@ -1,4 +1,5 @@ -using System; + +using System; using System.Linq; using System.Threading.Tasks; using Moq; @@ -6,7 +7,7 @@ using NUnit.Framework; using Umbraco.Core.Scoping; using Umbraco.Web.PublishedCache.NuCache; -namespace Umbraco.Tests.Cache +namespace Umbraco.Tests.UnitTests.Umbraco.Umbraco.PublishedCache { [TestFixture] public class SnapDictionaryTests diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj index 76764d0483..1e774f4b00 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj @@ -8,6 +8,7 @@ + diff --git a/src/Umbraco.Tests/Migrations/SqlScripts/SqlCe-SchemaAndData-4110.sql b/src/Umbraco.Tests/Migrations/SqlScripts/SqlCe-SchemaAndData-4110.sql deleted file mode 100644 index 4aeb066f54bf983c0963f09efb9a5e1f39e468b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 422888 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�iNxuBjq(dgYeaR}OnBOkaWTz5kC7 zTg_d@^2*oz>5RB>;H`eVmG?0@dfxIGXw&2Q-zK^IQoG@hX&5@6(v_xY-%fm2$4YV2w6AYwoHA??KA5#2Gk4%Co^M<|;c&KGlDE%Omi0 zb{@@pBz}{i!|toR%kQ^(d-veGC8h58upR+p0sd6ORZ(x`S0KEF@! zFqG(p=&R$`#2CD<1rVeLFN?vY5%W zgkiYqf_~c)xa`#shVPJ!(9UFDY3l>71bv4r>_g3eNj(8~XC!P_Ax{`f%!S%eXca2p zIa72g!)tlt{d99%C4JED{=sg)z^lf8EgO(w=CNh<9(#Oj9MDR%Vi}I)wr0wjjrYqv zi0jtrz0GZK*X@e0ntb7$lPMZ4YiX5d#TBkc)hn6}sKMjb&~K9VWzXZ1V#p1#yF|zX zC}AgQiQt~Vl6UJynuLVQSgGL|FtR)cQt^gmV$cfX2%f5~k)z#<9?3M1?ZgazOykO25xZUk4=g?JjZOPVqkyM15pDcYcdlv#f7kyEee|T^ z=u@QI91dJVm%(x4ED|WHAAf)$_;wz<2aS?7$TZ0hY}zxLhxU0V+sQ*@wO_0**SQ~u z=SXy7n&&t~R{Q(;xtjSnu;nPiWQ+~D!RfidHAPb*Dt8=ssx!I&l8QSjPF_5 z_-Ex=^7m_9KdYZ_ioYxAGx72N?Bvb?!+kKE&*%XgX9RDbv%@N(vx=TAORIV94_+60 zvV#%U46z?O@wf}R?;Jj>hRzCmk9F1SgNVrwa`UHT<5`b+@5T9|0d@9{;&7XA@l1knX*G4Y*uL0Gn|J!=Go$C>u+u_mORWxQp--*L|mr;D&9Q6!n zQgh1)1EVpT@O8UjL8Tw}fsQj6x!r)Jqx94V5*ekw(SCibc85lxHRLYx78rF=%|?3D zls6qllc|z1Jx%TTxqwwOGP$nNS@YaleGZ#lb%|*0KEQ0v0w+^VMj1)Bc zrJA+LUF!#N$}YIEQXbewyq10fR$Rrm_DOzS)X-N(5YczWDMy8ZTdg&~8zUzphCFhF z$FW(YBK-AK|3gj!8Djdb)dx4oW8>$QAVr<=uI`f^pmx{!gW!F?ZOY(|_;+7#!btX2h7SbSlR~`WhTcE*gcRJz}=F^nUfen9n0;a0OG3MaU*BT-fA>CXS<@& z?Fo;o2eGi_M61Ck+o=M8Ilj?&cT)E4JN*ad>-w9YL(YXPt6}aql;1&CT5kgBz-gwT zh&KW8oR19ZuSXt|HN#+tHGz?P!po#Ht2kjQtnlNo>#)M{yC?ZggKyghPf-!}b%H0S zi*b&uJ=?RwF@7u_>yu=EpObXq#4%1ETho)azp=g7lDB(KcxQi%wK?qXkhtsO@#*K! zqPZ*$*=rtI_eTG*V32CT&Ft;Jr?F$*U|m^;$GMbIp8X|JT%#vktkR zeq#>#iVS0vO%DSr(c?$DmS^T61DTyI67OJR8OKbSJDLjlN4t@6%W%xu@|b&Mbn??- zBWGEc^J+h)p0Ocoxf^c-NoVh!-OIWPOOMepBQz0nw5O3hh=2<-;(oRk!X^qS9y%Ji zT%IV*tg*42a|M%IhgX6YY8>%Q*jmwlb8dAGsHv|@OVfJT_AE3<#u+Wd%&CUpWRK_K z7Q99>bJWl{OWm9Y8XCI1>ber|5t^x{vNC?7`PHI5GZ4%jN_@YX3(R=I>p-sdikwC%Nn?oys2({ z1vfv|JMatAiMLtxMlZ#=AQ&y-$Gg~69iuB$l$jP&sq zZ)irjrU$rp`8~D2Sk5%lDpzy$VTLCoDZN0T1#OI*scmc9Y7` zfNz>-eP?P6?lvz$v9x4M2JQqOa3okj1_z|_7?2aLg@CGSKQidG8E2S>%R;7lEX=Xl z>I021*CKYuVvy)aM*73Q>53HOJgOY~h2!A6+VdpV zWeX*=p<|27x@s-oYzHnhuHkc_wVe1aIOYq@yY{lLiZhWp=-I5TL#{RDa!Gq|W9dD& z-!7jHo`ez{aSHls_EF3JE{@vJ9HAj9XP|G}8qpr|6&|iFhq@O=5f+5G*fmPFU!x`B z%ves)7OmMnnqHqn>$bswqhVS0XxquUQi=&MsX1GmRLOG zEU~oCOLDL>pX?<+WG}f3W|wt`wfmf(#OeS}OJWazi)x9TL;F+)ME24;G20qQ9xP4t zJ&^$$bB^6YvCwKsaWKr^Po$$o$$F$+~{L#%P8t)&~}C)}5x7@N7dz z0tfCy?QHmi83(2P<PfHxoLlcQ%Dwp}y__irw2F_(7U zaakSHJy7uFb%w`fJ;UoI#<9x-<87;`w4IxBbrS7hCpCLQu0&6ne!3_nEGnMDDh*DW z4=?RmZ5&wF%^BgxZi@0v<;u&n!xJ>z*-+&Ft2O^w#XvldX|Sxi67X$ zF73Ror_hP-lXge`hZg-_bGWNWDbQ=cI0&lY(d0pe61&@XZ z6?}8I7-6^MtRcs^@UFeaGxzqr;E9H4S~45DhV7FzoNJb_B!D{C9e3tR8$vnHVFr?&(S0yt&H{p9kv4!$zqrWfBIVn#ZcD)?WrNMSS}1cH^c6e^_d3^t zglzYe-`Wz!Y)7!}F=+U$ddXE2O&Q<3TT9$7Nqb+|ciz)hVU-r_TBVQNDMXLtiQOV@7@cAvs$Q9 zAriADZemvy)^YG0pDsxHZ0Qcw=NI+fMLi#9xb%(0JX5QG&^|bv8-uTgcDEcv?uN|w zQ`z$;dVqdGYa@~G=@V8(S*eVkp$+s)&fl}Lg!=dL$s40TX+Ff0m@j!{~wnrTk zX^yXrwX5pcmOOAIi@})PyFFA}3RtiEf+`kq4G~6PMsna6w*f4?qX5vwLNMHTBR}Q$ z!-5LPHtE&2(ntT`$*mmzFNlJRZ zrEhy`i(ZHQyRsg`?jLVac>hpVZXS=O8Z3&8iA8cd-YL{OTROLMNjmks^cN?=QSpi{ zLlX0eb)FaWjca6Z&~#h+^hBSqDcGNlx>_s@=XR!5FH_qbxg9hPGHG3WIlVHLeLu)$ zqkAk3ke0-hELpL2th;%lmRF_ZM&gwb*SbaP4d-Z(;6#>KA3=M>^_DeXXU~b5p~bA* z7#Z#6yhY?0a-Bo?G}gvV&!!%6m*3kBull|46d8{zWq=Pp?v}=CX`l5uBVi7XRhFy1 zqJl26^kKu59&<$9#{0iZf|uhv_Va4oxkjmszo88cZ=j0SMGxW$UlYzf{v7R#jy}ZG*diXS+l}i@sssS*CqFKQU5)S#2HXm17#@?d(=3VS!WPxn#lMg zo&qg^&)^xj*ATQ6h`J9`oMWwUOF8ozUU}R@9HLJg0v|8d(;SC3qRsBLG-o7H0*`P4 z92V4pCX2U*)i%?kN#|uh948k0?UsFCdKyigHF&wwB=hjVnf*93uXF>uX9QbfM?{lc z&*Lhe$GVE0cv0~tEJnU_W-$BldT(C*0ahvzeL^eRPNdD?v2mZyC}xQ-hR=tL_6`Mn z#@oY_wf}7yZtZ7}+BO-s13or(9JT~Hh*}d?r?R>#bP$#uZD42IP^(yWTd7B+J$4;> z!ROsz1)wA1WO~{o$4ZOH51wPa2_B>^LLw8*mWg89B61B0HUqJ6EHLyVWA*A9*G9O` zq}d8jpy^*|w7|moWcmlrc>IitU*|3zkFYheuF)|&RxO1M%UsG)181xp`u#!w@jF=c zV{61`8|Rn?dC9kGwX1(xxR++cc)F1!fpa1u~vmQ(9=MR+z+F6 zT+b^Sw$j_idW?c6OG;r3WF7Wosj-(cHeEo(-@qfIi}R9zJ+TYs>$ZV_$H%pJu8Rh+ z#-KB3fKf0b<^wGZ5~!a9iZz_v)~2>CW$0_AA-Jz*5?9w%E$YVmpuXavmry)G(g zQx#O2We~mBRGm4;909LD@#ZUgq0k(6&G~I3J#-3``eLUwsc39T8=Ra%UN3DoUjaCW^^mHyOI9QC zi0oJ!(9T_bLt6#*m?_?=@$H!bWyZ00kgqTd8EYwZ_{N)A%5`Bc(`v}GeEJ;Yxt`zv zErTomT6Slupoi@FaGhW8%X2;9*!DGJ11i7be_3{I5Uu(%=1MYUv^0TirflQ|++q0AujLPKQPt>} z4ipl1c-QAu(sSs{T9+_B+ghgbQUV5jj?=RA4_DI%;|3$NlAnhXjd!4B2|_dt3ik<@ znF8Cksz)7Aw{=|dCD6*W99DFRSs=scpqP;U?%i6>(#b0tv6pQ@14&u|j?gO_5==lv zjH%WNncMJHEDtl*GH;u1YI$UeX8$pdFlHRSMA!J+{z`L>v~o4INY&uWG>pu$?? zIfiWO0G>wXyEjw!IK6U1aIuCA*fUG`84CcOwFV8?m_D$Q?IN|a|><9k^6wMMAN2Sw2<_{7Tu2ae2|v%t9fK_+bJNuFTTz^-e2Z65WAY@-mt zroYlUvV=!Bpqb1`&>DQmta$zh_1ok#M$op8N^AlD@Z~%TJX%H=_EnZ>UAoD7*8P|M zCO!Y6(X!f`(bG1(60!y;A%kj8t#Q)Slk`$ktVc{6Aupm`%M|0Fl$NpngPxjE081ZB z5Jn4sh2+1kPhc4?vW?nhh3EM(fBNmRAe(cx1&DM6r@siF^y`{k$2huhYv~c(lI69} zX>QAU#tj9Vf1%-!W48ahuxt31HYzyiAL9WEVTIQ+f7U2Z7yQG#d>gR;4X`s$j#mNDo|J7@M$taJWmkF@ zi`jJpulD2BSS5TsygF-qZiqAtk%l4C;FBXyQWs&R4UvW+(m<3PKYWNZIO{h=8iq(i z#Kwk5!w_kx5j$DSN__E@4af}9z#Rif;H zCn6rMiy>a+$TSf*u9a8l9WR+)$zPGhbH2in8{TwWv(C*@f$NAP9yW0yqV&#vG_#y# z%$uwpak1tc8An9wiAvTv24>~xF?;VYUuSm8*i@NQDC0{Wn=>sr>rg%sQBY?b8A*<( zanJdZh-Bfb0&nl?;20l$bj7HMr0(h-5RPhOO8(-;TD(lKZ)YxfL%s6^y9MNjC z4ae4j0&D-Ey&S16XAOTc@*H=J8AIPx7(~Ri&ilE-%28C}u+9;{1<)P5VBQ>u@eFsc z9=ygV+VOisgjSn5i=aAV#O=6^Cgni^QTH7D!`QBB{v{sa>A+>CxFP0A9K3mw6g)9$ zcUJh z&vCqSoVvnt3@SQFO_4LYmP)xAr>qz{em#LKp!UHvlpjt@bk#gHb;J-6?H3V^)%wT7 z$+Jd8ha5RN%URH79g96MXN`v(Ikq^}SVN8+y1?EUa^zk9$MNRKu}%li6)1$|eXuQ&3Qlgmc zHDf@3H$kMX)~qYt=yzO%F>rybHZJKWM|1+(HQy3nqDqL0NThqcLW4GMrV&Hy^j^n| znpMNi`ZL~-dDDZ}H@HvmKR)W#h9OkXT1dyP%Bn~F^~@7x#akUq3`!(&NbkA!({$Js zCvLuzV@p7z=9W69o1dgFTlS`Y@Zzd@{DEBCNncR2KDq37=0NP=Cdo+7!7gb zW;HKYb7fo2i%?1(rKXjd7Kw8L3t-5zKrHJ0GwtD9@$R@tIZ$uQ3Mkg6>2+~0HMR7d zC2zTd*AT1d6RWtOn#fqQPt7GKWS&*bkh)1~E{QPiXf5}SqKiZwFX;-`Sl{hE28lwl z(wj3Lw)OX{{-4v+R9X_PoW8p9k!pYMXn)GzC2W4D{RP45ZBfy>q~ODJo*mydbZ2Sw zlX^q;TgRF^*#GZ_#>9+&)-zw~DX7B{SkoLF3?JW1^s=M&<33!$4l~}fCtrW9t9c*# z_j=d6nCF(!%JgXoQOA2do}E?{*y}pxJCWmpAbXtHB5pN(E$otTJ78=2ei(4k@nOq5 ztxd<)w@EI))J{QY>tQFm;MsfP+)4Qub{;)W?2X@(#_}+8;=pTtc#WvI_p>{CJ?8z1 zrt=!>3kGcU!B*bW;W)4b=T67gAQ|ViLh|aIBCp@Z~SNX`9VMaB&*mq?R5Q^*M0B_&tWrJ{yrV%Z|s%$O@d6`tDIG$v2!~9e0=7KjYD`6*Pus6X4v5?kz2*b!jrzg$QvYDiVx0??=FS8oU=i98m;+#$V%^fN(ww zmZ(DBlbf-yYqy_fR)Nbr{_^ygxa*xl!5)2Zinl8xSFf==FWL%eK_t<< z;B$}QaPwz9gP_GsX-&Aq2x&d@Dtp43#(0yy%qgaG_{dyRSKT>-x;T|N3i3DgOU>fG za2^~$Jg9lDGt}0U#@}iD0jrq7wS-l;=YoFQ(iPZ8pF~$fR(NOG$(+$mwL#BW)=j3~ zza$I*YiAk8ogu(ELr@QVPksUXl+wADDBd$Sw^h;vZ*uOlab07)mI25pa}?1zxCOnl zaX=l>h9xv|83;D@Rk_P>v-LJ-(SCh`XOjz@Lox-UIW3dQ8JT;ck`;Xg#NZZd-8V^t zv8QpCPh@(0N`jyCu8e4a;FZ7+dc$%f4aoEkab<~Z}cCsIAb-Q03SdX{PLHbw!mArezu-)JjN7_&PBUr zEzD@FMSLe{-tUG~vQBeus?;#pAJ7M!>XS?S-BO?Y4-^YEG`Ru!?s*^!83T3+obG%U z+H2grf;z1uGKFI`GX5Xas4@?PU53TSc!D>g7MpR{ill`<>i$)YqU0E7O$|ezH`(T9 zU`n6U<>>M90@|X~4wJ_dwq~jE=cDvh%^W*-h}J+&(>=XhnSLCe9x;UJ(VCho2h8=u zT&_eu4$L_MFd2J8JajsTT~zEOqSwcPr#cJ!Psx7t+!;k&&Ze08a?0BB_iJ4z1N=?# zcO`u$w*8--oH}5*4~BE*7Hpi6Z;mBFMxEFfYkIcz{j6|;U&X09Uh%`O$6Vtsr|+!k z>9hJ}rO!FpAl}iaPqb{vv-gc{5{nFeJPvI2(Rc&4`eQ3+YSDL`QSewi#I9h}rEH6P zSV2cc3%qqc-RIh7;yC0Uxq2#FSZDV{|2fMd&M4@^TXB}vqbgQM+>+`fqOSHxu*>lY ze1-wlR(M8uNJJ6Xg%Q7LOIN%u8#(Q00+BsxM;v1yhDt1$ZxJQ+YAwgX@WO24<1Nqw zF$yBH_6cYWh|o?m=3Sp8)fH8`e=rKXKjOXEB6v`=hmSW63NfbAKeO#$M*ux$M=J2K zhz8Ibb*s-u|48$yV|&e*g5l3IWxNA#%uzrhXGAL^@|WWmZHy2vV1`r$mM4-r;ty6C z9kA{@f5+CSzYAP|Q9d)K@TBi5^0J}t#8-h25T}=jfCM!0{1{2G_~jF0#?n~ z#6>SoCGpN`(4`# z)R4!<52vD1BfP8o#Qmweb!H%V-)}q882K+^la338B=K1<8;Kjtxj;6{^7fpj!NXB5 z&N3n{#5{?f6OUrofo+W#-VK`d(?}#R!3-UA(%#v}_vgHBvf}DX*42v>D zV+iaX$O~X?$>W?zjG&I(c2U6i+=TOAZ#9~nb6wHs_B7{J{le4BiB^M8wo~?=Ild7j zc2cJQyYw8D@R^^OX+GPphPk6rv~9g@y$PgEZvjQpJ4JZBbz`sj7?NZ0j#S(C0T()CUcHNWY2iy z-5dSKib1jkN3%1hp4M!WzteL(AC($jmxEr3+{HLqL+t;WT5{GQ_tS68A!Ctt zjI!xvU@3b1XsGi1JLDy^vsHo}!n|xVhR1;Xbh}{*W;o_tc+5TWIoWOuJ2}fb>iM0I z{xS889a+oXcpFGMH}8C2)>l}2NM>tpYzwp=x+r@Q0T*V({cJIKC!9Bjl05V@vYDEr zumyl7c9t`&T-`dn60}g`DBdjXg67=nEKpNtll2N~)4JF;Ei^}V8NFwn+mu}JagMM=sfHGRkh8YHH;a&LKn2`5n^3I5qXCs zZse>s(r?CrkPgF3vdm2+zd}fQhI_w3)&br)6zDNxgy>0D7s|qUj!#k&I+l640Vn= zA_DVT-e^V6-dH}MDs1plMy)1ai}=MWJ%ermL&OO@hOphS)0uPAhF=w=cs@?GHs3L4 zJ|U-pBGTx&q!RVIwZ;Eq^>#^>5B1(Z(p{|lyLvz51e!c+@cdl1@b`ro=&pLU zYJ`u>uZ#xmN=vq6;7;%XM}mdY*2!Z)=3*7G&a~-E2E8_84fAjre8WgR7UtM&^?^p1 z>kPZ&F^-n`46-Jt#aOp>YkL1BK;6dbv)%=DVxv51C_X;|*IHmTOJ9 zT+$xgSbES|*E36`V)^v{-`=}6S9K)ox_mwn=Raum7rJ9vAjG|wk9)~nY+{+qwuIe| z4o3$_K+_GF4Y+OA-s`{gPd)k6t5;c7W6Y_ksSC)AAkdt1j2d;x%6n$zFinC9@;Vv6 z`Y~FqZj7R~VvXPs*)!m`bPe|he}#ry&7mEISy;M?ij}7={nb4|hsXeMi{8MRMRIiL zU3wRg5H#u$rTa-QLkf%XT7HZ+aJxJUXYdZSnMKEi$3yOHe@qKSEVEjMfD!WW08Pmo z?|bg!p_lZ0K&eBjjkl6pl z!XL@=y%IaAx2%&fuohhTac~lBEj%h$LK^S}7Pu+zX2*Nt+MfrBU`i&Yt^wykk3ill z!Z)|R^Db~0hTqpHF3;aRLT;#cb$*wgz*fv|~&(PWYbY%hS(- zGs<#EnV%dnZR|ErJ9Qev6G;IyyizPJelZ5?8%8AsA3xvjsI?2$M9fFg4#`eygXmJ$ zbakeRJIe?AKzfgrau`t(RV~^SrvYWv?-A2BZ%cAIx#2PxK>j zI)_+Ddd{|Dj;v=~KNX%jE{ohA$IEfJv|3R=7bGxPi2Vd@K8SDfp5b8VI6U z^uuV(wVroeTF3qtDEkEmI6mzeTCaB;z1%xK)QUC&vewLc&1fF(peOYsK@lDaypiW; z3{$L8(F(29w7uNE3|Fzr}H+xsWXo7LhA9OcLRZ5637d~t}P-9mgP-w5O@(h zSNyQ&_}=XsA)Pm)6*A_1k?!z+J z=M?~{9s}g1Vhn6Q=BBj_XMsH=n0iG#!A^01TyPQvDBUk5yq5ccL9dRuV~|9eU}^h;ToK%MLIJEL0+ zA(U|rL5MRs#Qw1;T`!DSf+zs*K07jT`Tcz)Ls$>FV2|1CW}7jT)CPW;2BBWXTHuhw zk@BhS*fHr5ocA&g{~V*F2dL-q{oR)1j&a)ifiH@C3Qw>Oq&b6)(6_j)IFB_wFwNSb zV=BPaToPJPe^5G{6A#*uYY%n8* zb5y<C}Jc(B&w$so!E=QY8{{PjDsXahjm%XK2RCa)@ zdugPq2-5G?R;*n%0=g0ZvIQTvRz9Opk*%kL|(+eC6M1jSHonc8U5GB_1_ zJ?L4!EwU{x#FMJAJXK0lW{f;niohc;m1&2cirPi@jE0g8p%{C zO}a-)RGk?yEP-RzT(Q5Z_VN2}`c5VJi0&&2f#o^W1bT@(+vc7srAgz&t5WAIW~?c- zOWyP$zn?VtsZv_2e;yvo6lZbOvZ+!UbZ$)>EqkhzCJPC@Ikjsf6xAEyw#s{TY$a=I z^>M7MBbD&&<59AyYagrgfiok(b zSA}nghs>W(#y(TxGslD11e_|ReHQPMNjq>qi#+Sb9EYWcMLzGODtFIzI66gV7KzS~ zX?dJBy7D{c@7{FIc>gFG8Lr2Lbmhw^%Mdd6VHVYOI77G>wQ3Pk=P1T$nvzn?o4bS&&27aYKay);UC|>5rWB(FE zQAC^w=&ZQjR?AhxcG1D9ol3Rh z$Dx%!DY;py32-6q^PW;pKU4kbAk~Up&8d$D{tz7V=g{R{CkTp0i&Pe?GHhB-098u^ zHANFgCkuJI@DrauBU&+*bJKgZ`^=?V!LM{0!2R1xgeSkwx0+5YayDk@EuBs*PA3+} zPft!K7S9*$a5}MA>uBhK=C!kH z#3Jz&s@%5Kgzkh*`L4TmGh_wy-L||JS)s^~<*E{0i5Qx^H9oO;v|fN^yfvGC=H^vWV{u-b6!Z %(tZ~>tABcFT=)fE1bNKr-0L=fYVBxt-Brn{^Ja% z=e~+xe73#tYb)-oL=H&yN3JckQhqt}=NRKf>Ff8=f;VH3iF;>n$H>X0-h{l2c^$ta zIlA&&z>~FazwY+;hZym@GaFHR;bE+3Gk*O({3q0e(#cW$F6;4+x7^^D;q6d-syft8 z+~Mu(RGuR`%1Jq*qrBUOvxwB*=9k{I-oFiu-gqk*=NQ*wPCE5O>tXpn=vctH`sA#Cyo8ss0gtO|vuMB&&bgk ze6~Q1mh{Hz!8WSpINy18Rfm;;m#UV)AvpV7@0}{|)>UPQ&I;Z@70f3pd@injSw?66 z;=SyJ;R${UbN0uh%&W!|t@=aoTb*?QZ)DT5VpX@G;tCesi}-Ci%UuOFvih=aFVNI^ zV4eT2YqR92^qA*nc~`tLEVP!k`Y3P{T=aG;-nHGYp7+Tkn^uBS`zrJB1=Z9rtl;E8 z(*62+Z%5d&&3shW&P>gN$VYZ7K|T4}bTl+DYDI9y6YUJ0iwd7)xluWSXOXn3;JJ*B zMorP7j&?6b;VtJIvCrgVfwQ%awqB(An2u)s6CTj&X?mvC7g}Ac)e+iz)?+pdNm}Mc97OJ%uUm1SVyg+ zSzFUi_uATF&g_3kIwj+qO1r#oh&K&kOOahle4BR{={-f{o|0X9IX|l!`0+(J8!`H)tS}TWY;nuyi)HYQI`))iX8bv=q4NQ>*Nrhedjub2ibF;DBg(*g53F@m4Nt zdDu?$fhLc=2rt|&BeEA*PUzSxyFLW;ZuN-XOMh4!^oTw}J1CjDBeJ>BK>D7E#mMGh z^-$pJnBj}!0eV$-9-hq`hE!8mHFW!4Xn`*Mau;)?(=tB#J#}K375`Q9QaP^D_lc>o zIw;>(B5SE<&FZiY8TY&R#OudtZ|VDQV%74w_<2rovX{p7GcZgFVe}T}xv$zUFp&MwuFDGnM7S%w9LJR$V{Ff{jHte-on{vF zj0HS4f_4y`VL!wlYF+|Ha95Rnq3q{npTJG%i2Y|oSzDGx;yqBhsEk>N3((V(cq*X_ z)NYr4baKJ76;~2BS}Ao?1rzn7^~kG4l_@aub;t|R9GrnGvVnkyxDxZwOmoNEU4!P~ z!0;%jh~1yXNsz2~6veCP=WhIhmwNYDDc%X~w^jy}na7)$EtDh}GS`|W_{Eb+gJZjw zxN2&HQ&MSPeC$Sim+yeRO3sp4!3b&ja-IM3@!cqUEYA;f11i79f8<;s>M7(Ej z%RVs27V{&f{*Wlfs6&MU@ z-;|Sd#hesv5kHr|&u=dT23~Ky`u?fJqF&Ad1Mmr+#8WAypbIb;FP~%pv#PPZ{p~T? zCHSu}fIXrYafzCzfJ0!Kc_uSydmO^pW9U5uKnu!jWp)h*I3f^YPLgrpI=IS8pkXwT zow6I|Y^JQ52aoGbR6BsWy()Hy^$HWbVz`H@LQB%ra+mcyjQO$l8rRGL!82fIJqXAq zX2UO_4#Agk#eaB;DnaPUNI0OZJ3Pxp?*~BQ!aj z|4^Im+c3wC(j#`&tN1mxQ($2$@$f%eJ7Blr`5H~wJxi|Kj5SL_8us)9J);3Yvyz~O zjqsz_znOK-`_!t{L9^C8l0=jQ#v-f0JmDI@t$(%>p`9NX<^9A4lCH*1n|_$N`POz^ zrv>r}*p1DP=UN)o)6!9h_%U9s9f`vu8<0$*Bxc}M(f+&WwWl*?Fw~Fg-2(o$G&Bpi zBQvyql^ktMHc8HE{Ms5~021j?5P;8)wYz{?g`w0r>v7PN{g|Yam_E> zuXu{~pyrmc8pm~eaUXFI#>J{J=f4r(*k!25mNPtUXnARUteCM`aHd_doyzYvC==hw{Jx zpbAB@^YeTVWAL|**Wz?4OF3d^uAhEMROm@&*=O3(9swBY=u+kE$IGr){LYRIx0FN{7ji7V{zQAXhk$y z8qZ?(2evbk8IC3U_9U&3*0=njY>(OpdGeM=ZTTL~?nqfO4{OHcOrM8^M4kLJ(&;BZ z&E%(<{4}-CfAZ5{@8S=h{4|rF20eB1)5zyG`DyT*p{XkdVW0Qpr@=3Dn*B7X5kClf z36GnsP`sh`ju9c2=T2UGd90oFph${*r+xx|k-YQxsN~ltX2P}l3Zo-+6%8hiL2Ovo z0`@RZDhexKmm}NcughNxkHS+$j6*SuK1R%#o)h<=4Zf+eT=3T6};gG3!;7 zqxS685t-UMr@1LAlrfvSg?-41*9w=cm2gkdCi?+_4W53z=~o_7#u)SP;fH<^_foIH zQ{P6=Ge*Y9LvMG++SoZpx?AjU@WI|S-f zctK`5JHlFrSv!vkkF^ql)BJ|ove2jJ45%r@!ddvd@d}^SM z6K<5f%6){Uy_bn`pSH)C`mSfgTa5Sda{QwTEZ$*iQ&F=Dk1NZ!NIm zVq9H||5xKTUf)McdWO{W(xOW&i?Dng>?WxJ2_8%^LSGaOmPw*_Bt+#0%kB%bw z`Jpuwow&dzlQhg6x;oGA`1KQT@Iz=PW0{J*ZgL!c;wkR}t;>FZDenTE3SFkokec!? zro0RMBRcJlMS#sVOGiK6ybE-8MYukMtYq}bo>xxTWY3em1TCZ;Xd7^{=YRY5d~%{Y z!5K4Kcg$Z{XJXd*sY72EviGO3k(Ci*?|gdrdVd+SXnij5<-38IZ8mC~1?SumWt?PA z99|IlBk^OY0^&}5LnkNO#9lx&0_XGKD`XZt$JqO2W2eT6B%!XBGndCaHO!4!>ih-$ z3)(}-c@E^ZQ*laJ%ce+qX!^c3qhB(VXXR?XjTr)wHUqfLo@88j;h5jmdx7srdx;dK zM`wo%+N~e1=C44$J@rGMx5|w1Au@XFN$Vq=eNH3Kd);Ku>dcJBWdCRLt|1J;dd@4! zqgQ9r%C~JlW1U6WdRUE#cmWxmmhy88GGo%Ve+K7PZcJ zFGhuvB<_*Z&a<=P2S9zuE5KOJMU7K0(L6>@&RbVIPfL0%tLnFxy-S6^vjH#O!$n<_ z3k7zo#rsNCWqh&DSuuNa3+Y41T-UBg@yE(n1`M_HxLnYY3YI9s22E3Wh;^bo}q zRkdmCs;@0xacL#0K)DXo{!be|$XH|uGlAE?+Vysy->WDkIM(e{5scG@aQ2Oe$K8p_ zc~1iFTF?CZdXqIAb}Zj`ty)FflE@uaKKj9%!u!eNemisK^V*Mb);?eL^LT^w!_Zd0 zjB249A?@x*{m{GR+qb3KClZRt#ZPe!$RV$wJLBm$aSfUEAX@OLoO0lr`!qHWb9nc2 z8c$^Sy|$dLfHzaYhFUqC&v+F7;ORu%sA73NsE`_^aD2`Lpx;ncmdM)W`2KVWp1vL$ z%7y6jVm$jlAzygott*fkuHKiPw~J%W=Ix?xba%!0*>iE>n$NWSJ0n~N;qA)cpUvBK zf1J1XGG+0z7(_)+y1JFQ5&Ed8<#)li(M;QFq_epEYV%yZ59YM&((&4 zDpD$zs;D7nf~n~FB6?NLN!F-7Xvd6z3Ri!McF*FI(Q*d5{v!HW3CV??^h;oGtxpT8 zNVzXcUy^hFPSw+`J-EUPJU`U*M6D2DjwX!tTg-UqV5z<2k{U z9=xZX8{^k+v-5pbD3#v(DxPCKU=DMCF#=tn*yAkkT%rHJ6`XonWFx!B>Cm^aN9W@o z^QKY-UXjGcb7kEx<34A$fGm2{FEImj5vcf2ah-~UmqJQVRqTsF3sVa-sP}|iAfA0v zR&mgG-P7AR{s?c78srNY19bJLSTXRE9?pt&0?qirY$Qw6(%vg$qcD+LP1xVOPl0*t zL_fku-j{{n1UhctjZ2;sJ!`)u=~U6t6@z7|!$oM9BO|AvKUM%HijN?h=?i`#%4a5` z+;$bl&cwYQHsdr*ZCal7{+W7&`Ouaqr_Eo|z6c8sk9Ddk`}bHYIbd%C4^0>7E&W?I zREZj1n7sI_vKPRNnE?af_GQ6esOnPuA97%x_o#xf_z2ts{y2|ThVpOGSe%}VwaE&>& z``_{gc$jExHAZ($iLG4-yBG0r0~O>#vCqprG=+qBz_L0 z{DgR-aYfkiadY&Y#25TNIg+M>@#loSaKdO2FS6LPI$gH&)TO~&l=h2;5!S@|iSfc|TXnLy2P5*Es z!&8!oKK>MUHev?~W1YNk5%YT$)(mC;+MTTI;r za-1*4U%WAw;=X+AWI3;u${6@e4q5>Ne+${nWB!({*zsQjlhOaALr8abCbOynOP>@* z*mrW$)x=eQc$U9~S|NBP#{DhJXEKw+d^B%;(HtBrs68JWvEOi!cVz`|xYnQTkEe9VinGVhj#bO);VX;P(JU(VfSa4%}!*zl;RO#H*P5JDf9+)El69v$OJ;?#4A{4sHP3 zeia%eXTx}!xqNuSp4u+%$0eVur>@OiuiV&(oT3G`_D(X6VZ~J}Nqlwq_lMZ9D33s2 zQ+y?TAf{ICfQ9f5uuvXE`7`8+d=)LAuV?Y;DrZ0j54Lk8@EFM-gJus8M)K(lFWGCf zB@0xvucw6>+`;n3HwW&stD2kM5wTUML6i$*@xh3f57)FGJmlBm9a?xnQY!02^G?hd z8aB?VH5`eZV1@G0NT$=W)*U2G=vn-LRml=lya!k%e-;E@?D7lXF3zJkfoITqF2^u{ z_|UkQM6sctV>We62u}ShFkhY@-b0ymvQzXS*7&Ya7#ibOu?Aqi*|bwk13c|{ki0H> z23{$-38cNJi9_HszI7mO%PO(Iow+${!r*Wg%UYqPc8qy;4ScG$zfYgday9f_{2RQF z7TW`xWi3{PF9WZ|(_*t+2(0DJOuVIOJzC0U!CqM}9uM+CIMcnpq|L$^@Pped%>B1u zvn-!0coH^?;%#We$W3J%$U^Ep9cT?yhV5H^D7(Y>aX7ofl4dhFpmY-Sz?$=+QT|uq zkBTBmUQodt9{(;rfg0Rg@Pp?ABh^->H_0x)_0pLfMA!7LBu6Ont){I^!@vJ!jDZ)} z@7B~T7n!r=3LKtUww9x0tmcnYsoyn;j=<`qiK(iGcsna)?K}SAALIeK3j69S#ei}$BMz0uN%4l$v*|8!dFglzpthAgA7gogm)RL?VT6$SG zK_1l>9;-&TRAd#cXnXI9aiPU4YfiN;)b2GJ1T#~#h!ZNUo>FVr=v82y>WqqLoXRL(XFtJPOG!dC7P7 z6}+Hl%@B<=2^FQc07Myzjf%UzmV<_iisvuFxBK=VX*(=5@-vGT#2eCp4^ z3%)5qUHn zqtv^reUR3QPMRY;jJC3ZWuMo!N$T9J`b9j&SrqUeT4raw#(tjMOA8+^1cv6QH7vCj zSpnh}$`nVV7N1Gzg0C7Y#|8>e5*8QqBCgC8_|W?@>!d1H59YouT71sY)`eCIz6uLX zm+db0l+BJTVkO^<6~Tev%=n?kEzH(Vu29r=DP)g$t-uqV ze~ice5Hsf;UFJIQP&lUJ-z%XrFK2Ba6?qfH>MmAcchp#XzSx)eY|tyH7{v}@m1+*Q zSKwi+xwl)+2Nu#^wk!9ISA2s{14W(N{B^|2`M!C&rulEM1 zl#7||(yDnIJ0q+1*MOmLj#FB~Xxo~4r#kPO7FXo1=p8P=im{D>gK*wG<*r+jjP2?7 zvHFyaxude>rQ=z4@T<;DfNnS;ni+E~rxbN-UEl>6EKP=)vL8^S^#emH=K#;eMn?0| z9I$~~eC_=!%TSqls^-EP`(7Ued^6*4+y{jQ1b2i}_LP!&L;KmhACiW|U4bysg2XK- z4!Zj}_Bwq9c*mseSsKcxx*As{<@Z5?v@>BgMFpq{O$;Y%fMXoE9b0%|9aD+{G4OjXRttB|c4VIq!zyT9slb?8AAIgfoZpBuPI=y$dcZxL{R_kM4URy4*JF)I1t^k}QnYwNYS8>JmHMNdHn0DJTvYzN{EtreEiA^lBlrh4jk9+N!; z!d@vhAHNub^$nxaZN_}Nqt>*L+{FCkiIW~7Y_XMZeE~Rd$JxTRjnTLr9Zp?TvyoNG zEbBe+iV_1fQ*2(ZPCC9@_VC_}{tg!(&T(Xe^dl&v?dO82>?t_%K48o`#`c$;Q8gP= z)i_>`!==>_`?8FB!1lMs*)LJlaaj`3I?+%2 zjj>U@<3kOxwj+AJIuCcy8T*l-L64N&a12wdUD67iO!`>HOEO&5)~=<|uLzqybBkC* z-=dWep63{!OGzajt96obKqLZg;tUq?CO8|ok6*}M3FQzCc{#oW`Q)$);k`YbxAASA z1cet;zXlrw2uKE`B#=jnU0XyJEX$kVAo7lQ6+OrIZr=#$jJ}MFd0(VE{NH@%>sZ6x z(5iu6pXq`uCZZ%LA(NcfVmP@M{Qmge-|s;X40B!ykm@l&c}vU$JD9o26Fi&+wxM9^ z74ZZ!;EsJj;)&eB%ZA;B6qckT9)KSQTao8#N@ykTX3T>gG@HX@<=|=1sn#6r>wqWx zqSs`$;#wWMudQvMF8jcK?;(Wn#%ZSnAXA%4MMC zI11xC#`39f`5~-_T(HM%cC*bGOKJnZOoLFb;!beL;Yj(^cI=q+2xX%PhkuSy(i_(E z`2KFoamP6A{n%@$#Qu7$1AJt{M(A7IR-DJJz%*-z_Mqa2Gna%$g?CUooKt7}d#*jy z31?@%iX))i6K_>iv(17Mt;7HOys$B@oxEC{?!)OV``ew+U}it{xOX@BK%Hs*MYOIh zJAM(7>7Rq*^SPlsp1e{A^-8T5uM}q|IEQs5JVdI9Lw*sNN_eH#gHEW8!+9>+@$FJz z^>*d!$S zsoHz?+H3`b*fM` zfY2p4Lkou<_Q3wp6CTC2(4{yt^T*gldhmNIyuN$U3-X`w?E^qFK{rPqVy#186dDfJ zj9L-}QOg?EbuE(_-F%u+m-S7Drt*#rx4A7+*<9)H_+xxx!&3lWa`wy+` zKgLM^9`m{!pBKv<$YsQPydIy*VdSa#BixQP{yO4Up!a_*(f_}?RcQ~fOq4YP#z`9? zYhK#7>cjNAwH0fZ*4<*QHB>T>(P-(HKC?GlZ`Sc!%s>lKkKhgwBKBLcpIV=1ZeTnf zDt1;j%hO^h*gi^q9ITR0aa^O4R|zdc)*-W)HNWAmZG=4}yM^@gK9X-8?zIb~7T7a#t4u@+`uYP*D;8%h-Di{25$fC=! z^F;NKvO9%qB6ZP}t^};$o1AOs-Cf)9?RxwrqQ^BfEqqZ2(Vy0f=vWcGkVG zB>;tGRFAo{@3Zx%skR_=r@9XF^(WOnoTWe2dI8=*)$mn@&#W`>aL#-Vja$#H#(t4q zspn2sx8hxN*0&B6~tpGsA6rC4K5!NvctXrAT3WDlp@I6 zIz76of?75DoBa+sK3W=i$4D?&plNFgejY78#(IL1NFS=2Ao@k-HF>AgcP?EDy-HCi zqN79YsK?RSK9`fLA}A}&I$>Kc%Qe=(+lpCARb=9?xp?)Co3Zj5m=^wIsAaMjv zL}Hs~2C}Ig&DEZIwD+v5I8Lj})ebagoE7<66w4HUa{a!;RSh&x{`hJJ4zc%#!Ywme zFv}{!PfUbE`FpbRwfnix<{6GGWnVQ;AT7vY6hF~lTVJilOh3Y$)q?4&GPV_XRretq zR`wGT2Wy01@PGMzXZ0?fq0Tc#uC*B$`J^!%T<3(Jjpd+ z$5}$cr4P@)Zxla(FjRkYUkpR}$Ld`*PO%>cs}86N1$Z6tmMGp0KC>=x7O%wd*9Jr; zws9u%e!&6d5HSa05@42deZYL5o@=WZ8$0O(=s|;2!-NWw-!kchpP(+jpC!3Rj0U>^?2xxT8F`#`c+wjBP>@&M^s zwE$Zj$$si*=GFb1Dg%=13>^_45LRQQE|vpL#VoufoZ`i|OjL>YmSf$bbKx1m7tVdI zJq~JBYn!6>|P zQ?)N!ypHos)xL&jAvc4n>Zlkx4;YkQ8O0c-mtrAdA348YSZJ-h*Wid?BX>>3^Ru^= zhm={7X%F=MZpQrN?ZoChOkSa8PRz4Ddp>JDH%6#ybJwOGgWFW?3u{)9W_C=u8P0&j zLfP8&Dj-F{I{UW9DwsVCT&gqlS_x}gajN#^)AM8JtlE6HuL|wAHE*zmeVV?{Y?DO= zzmR?-?+;px_mn8MvRZ9Bwf=2WR%_uX>zw)y{NqXN!L)nEGGf{urYLWo-J}XJxo#KZ zAASzJcvJvWy<*iY$8I5Wh%?*d(@`VrQfa*%->=2pO9!@Fhz@ghlRC(s>eFg%H z-s$Y-So~r$Ficvk>`*e{Fg%H;G?MZh0fFZ^3c6of5O9PQF~~H{=by+`0%E)o9IVvS9w%g>n;)KoQxpICB*&02LkZXoLpc8cH z3scpxtb)La0@e5iN;2%F)?|rzKY64VD0Aa+mWbXbt|e7ZI$=- z{&426@p-S@{Wh+xgjKv9wD2}+Yr;1<@APIbuKZ)%zaQ@}xP9h7N}tR3jmHU#_d)qf zzB!f*m6%jXOC#Ou#%X8DudSF*J?BOG{e7&Fx)(a5LiA?-T(Wk`qECDq>mgs4Rc!<; zkxIalI-|?iynozpdE>ci z{Cb_rB6z#^RQBqA?i4G7%2sFNtq3g!O*?y(J9}w&=bR6${1D#iflTv$EVr+1pYChg zTk)-$B9i)!a&Iq>?(Mfh@o*eYqj*oI{cUARy*D2(SEiy4T(_mO2O+UIGmS)<_7}}z zs56|7{UtJ|9p;q3HLSz!sd@r8z!LX0@#K@@$-KK;d&>C(}z zJ>1T=Qrdk@ocH87FK1N7c2_g-jx5KA+ub#Oa!LWprS^~epLYD@cAT0avv>S%XjOVA zJEx&@hmH~hW{ojn!AW5OHCV^60AJleF1zFS#DshuT}tOg;`D z@ln~nv-_JgGVf(=Mf=)O?=SBdfrAhCV-{y!j(acO|Fr+!>yy}jdqCQgh8g`iI*LEY z2onyRBo5ePvd9h{Emt_qh!c*SB#t=NVgE_u!8gSQJFIp;?6mq&9ipaju1b3Wv@#uF^w8c(} z3)Z_>=NRw?%R8|n=vP5RLdJrvn9|-5Q9t9?;_VqBE`eteIE+CS*(0#8D zVni^RzGhohNF+-o`GMD?{Z7Giy_Lx|NuL$y3zMx)sI90%t@X~_{{8B1-+wMX;<=#1 zw*e7lPTOAa%n!pkCoKKAu@qae#?mhX3wWpFMo=%lKN@gnf~{N4!XLu&s$F#gxBFZXmV?qOH`x<><^1)q~v=or{sdr5XN68H|A0*QQ+2f~xGue(f@6+7=jZ*|;;8$YJ^qBV zpDNDscAjy$ZhmRr*h^aDTH>sqsQKxvr~I@(Ta0y2v&NqA_0z@I-U2rMeH)T}Ot!bz zjc@*J@lI_g?D}-EYgQyim~lI#HCcM_rB_i+!&qb-T#0BUScvVdmg0qVTR-E^F%0z6 z9%sVHPZuMdnb>QUTcJNb3qK*6AvsgVr^LlsE!@(dEe7^aO}O{z;@+%?jVq@Pwq^SX&pur|>tizJVXt?6Hsk>L&Ez|KIYwjHCm#=TxPAh^j`EW78RMfrd%RRn zZ9mz|gsq=0w)SxuV-7X8(F=)RzYPtLj0a+X=5hDp&M$Gt824q!?fMC{#{L;{&Dy8@ zv_B6z`h>ZkF6KH<*t+DRxMO~7oLdZY`=|W0KMy+kgt?zC=JwH@Z-aNfD(~ZaU!soi zSuz9O1rKdAGVnm=-GgLo>_5i&ZtN*{iQAZtYLu zpr0M~K4Idgi;3oat**Hh()e}QG`w%;dH65M{B6(MsKqj8Y-aa;P&{1z#M)7vP$S2Q zb9z6=CvPd)ivPT?aaRBPz5jsIRNF-csg{3AX4T)=-qn)YyHpUS3dWuIs}mAB{YjM* z(aO1%DQyon{{dD zek<#ePlt8s+izuEqAJ!U3+lJBF0F=jNzeYRtV^qbGpc^fVb|r8pMIBfa`M-~ogW7u zCx4OCyXNq`1EiJ|I>qdB%bb9HQ@oZ~)!7?zLGp=H$Zz5owR80rp_{w1LK1{_uVYl& zw0C}v>pQz`+dI9~$#Hdpm~qtmtLPQ0icHVha_7qKX?bNnoef^L9q?X{u`k6P-fg~9 zKChJbo$th*3-OJ2SzU|2tMT_y<>Fa~UT6xZNDU=H4%%W;QRaGmvNmzc8=81qx`5xDuAz#KR%dOelw zRsxsc$M!ZI1s?Gxwuu9|R>w)=k!%V}FRZAG!BchuBd!N-tOlN3E&sryM{!jg=uzw! z9Oz1E1&4y~(Dr)llVSnFkEn}C{X)FyEAh9EOCAkAF^`EaojhN1 z9WP5XbfC-e?`gpfG@t8%AChR7;yPFard=AFX)v2 zC>joU^d#^HdO1362>-!^J0F4<)!7hdV`rZRo}k-Yi0{ZRu!VOa!;8$7xPPhKMfU-V zkcB&eBj~);>^JV{{6K0$ZA|$nxX#s>?}RxY0(0sUrC<&c2@F85KnFsmJ&J$QsISIv zxDFQLrTBI^TB1dxO(XZvlfb@Nn1iiLO`VnCJId`k8t$`RY_av2%Otr@UUJoW0cQgX zWQ!xe@S&^*K1nKpL+IGo;~LTo{Td8IKN43$o~;!P>Ea#^ZA2@wtNkwH!}1$&T_f!DxQ zo)(f%A-N?;Hg z`O)Cd#gJsoXOd(e0)KiB^o7Dd@Jvfz#-f6!fIrAAG-os;+VSmD;13ZGDx~!CUY?Z^t*{8sH6f z8j=nyvaCApm=_!ethU4=`lV=n#zHPkF|XL)zZ6dYGVEMu=^Q>@TAzz1M!6HXfIkQM zgT_om0#7m=2TYUhLk*o zNINmF&^^2Sl?J?;_rSR)bGj);pd+I1qY}GB)5+;2GKw&!KO_gN#QXBIX4? zT@Q@64lTYk;gd2;k2?dXK66YK2XP4G+T-{yPqXx6@g>DjuN4f#bBLAxD4uv4`$yar z?Rq=z8lR3k<|W)o`)k6Tlk_AK^Gcbv7T;xO!IjW=h)IyCA#Di%vSgYpF>nd#hW)-1 zf7c2ZNc+9lhK@Gobt$+G{-;)o5sR6m*zrp-<>T50TMNE%A@D?=A7WnM!+POA=t#uB zu)*Z1Lysn74E-5y1rNF&cs4s)dh{``^}YN<;&d$zA)yn8ru;)i!;W5~#&SvSL*x_5 zqpTjZXT{O6*})-U6IMR)3*E)4$Ja>Y11W~RX32HbF)#QHv#YHyWj80TOm_Qm;fnIf z&2O-v(2h%jZBUPenfmd$T0RtUPdsGJ7m9NiJ?8G zC3buZ?&9AC@}u0w{}JXtkyo#Wv;WX052gWiJ$Mdl#-GLd%0zrY$I z?%3>DSi&UiWOB+L#~rxNcC@(~ZECC`&f>E=$7yeo2TziWGI!lC2Bp*C*}EWk=f z`r!Fnjqljy%JD%e!Fk9!yjmm|@7^WOjwHjL2PgSw9Qu$tG?XyeWhWntCp*67OFD5u zRDzQiWQL&|ZO1n_5jrc{5Z)dn92P&k2rnYf;DyGjGfo|^Hgv7{fUv>H1gLq^{@V0G zD{I`0EGDXYsYVEAN8Zn@fpPG@i8MTl+8V0T@}Qhd`7W;T7J4!?Rc+(mng2NR|DO4O z&U|&|e)-(L*2W_J{yyUL&x2QpYZ04bF7I~dGOVld&%Jr+3ErSgPM6O2apF(c>l4v` zi0r}s3@h1d3_d`%ezE(;v1)+HN)+4U2iDUJ9Iva(Wxk;GwF<}+-p1(oH^rZ z=I39UhjMNI5qFt={?c8Z&>Q&}mlJKgEt)y`{>!-jEc)d6mod{f@f(P6ol0gv!)>!K zdPCX|pLVhpV zIP6GA!(n_<|8-EDxWKU912_#8={>xe5k$n(9B{m10=t47LJuNRijISnA{UI9#gn4_ zpb2rBR5}s4W!TDS(~7!7FIfFL@0Hnx=s$1~Xpqy%{azlF+a510i2M=#1wYTmU)76v z6zkrO^{H+IE0#SWxs7G2YuJH`Ds!S6dsIF!%k9$z3*r!#Bxj5Mfvtpn#ECynA;UrC zy~*5ntQf9wx)d)U+40~Emby;Hi1P0hte~dI$Bq-w1#kc!XJc(p#pUu>F<_#+Xxh@{ z*mpEIY)yG9@K6wsfu7L%IMbH&aW5*RAw4WbK6YrpzXcER3p7M{410_B6@Kw__ZvKg z${BD8tZ(#PuD~U9f{Pp-vQBGwz%5P#UT{VTNU--{2J#)Qhz*FhQz!A2696R0BvJH5 zo^tF=P8jj2YA?j?GWv4*Fav!@dks9`f0qIhL?E%C<-=13AhxwAg}fRpXY6b&A}9qp zLbL&`IkQMlA3UUslXnC>SQBg1c@TNR<#B>@z$1~dSb_2}D3g+`Y@&JClsb`bX>$7D zAx#7N2Of{(^J)AgDgbwcYa&yWSA$m$pUb0y6>tu?EZhdX!8^t?{4+e9QTFk3P;%4o zO=6>+ja8EGK?EH-00)pUinYNv6l=pDh3r_3dqhjf3n9V+W^hg@y_TmBFQj!r8NdVI zhw_KfGvFIg0DfKQ1j`FtA+pF5tMN-7IJhVt6y<`SWd_nkZ`p9@4CUfP7?71aU@bVCY(C96(HG#Gx(n zKc$PKlU|8FPP1H*Mv83$JjeioPGqw|8)zZ;7@!v@hHH4Rb!JSFSRf#)2Av-J<+Slp z)(D*-34|9%t8bhxYmJ&3f(BX#(p3>9^eyaJC}O?fJ`jU?kh7Aw*zs@|q%XV$`rtlT zWvn=DQU%RG@IdQ;Yez9?58ec$rcqvkfX=JO-~>HkXB0MPIC5Bw`Yk{8b^*t;+{Snk!A{x zNa`NFjemNijI>ff<%^WEA0%s9*qo(SN0vgKs0`?5L+N;%aAx- znmX2*;-FY;$Xa})SgEX7nQ81cUUFGCRDeZ)CzlorA3YBH4(O?-75DO-&}oAQyi@og z&!B7()x9O_Q@XmW7_!S{*JHtA&7-U9Bm+?y{&V7?&f`06@Bk|W59#Z8GO*I20eMAr zPE7cLzXvEN7hhg7d}P@9;1t{jE2g&PPK#8LuUN2RGu>8Q}C18D|mWn z1j-OBq?e2G(Kar{s_+Bi6~`lFSja<)PXvB(7+4%lhRiVYX1}};XY?yu?9Y*X^`hkS zk=r!Pj`?->{#eEwkW=*}GLk;u%@g~&A~ycy>TyNemp(9-jv3C6L78DKaP3SZ`)oizkm$wYq-}>!4F=RyhB>G zdoa5lyH34E=E-i0`iv7~JL+94-2dH~F9N5?klcyv%B`3WxeZ+Vx4_gJ(Q+fMZp8P` z1Dn2x@4Vk(CEm08e0NXvi;P6o_~YFV|5dPPC9k7}q`GGu+w3tBvo zWK^&p%20MMJwA==%%9zQ9#8I+XQ-q~_U1~wFXv_4dlSFtp`Y=&fYJE^CGvIW!K+^> zd$LmILx!>7101&FJG1u8UdA_O!Wv%3JbsF2$l}$ieu?kEOnIwnNpIYzw`Zj%t&pmo z}9_u!o#eb`%JavnSYi-I|x^1?*%^a2Ml~cU2eyROyAe37YIG@DP5nf*;C?a#VVR zTdl-%ug?5Ez5y?yks@ zZIAKNNyjvMVZ7GdV!WQIq2FTlau_d+o{jO+zmEsw$tMv04d2=bM#(-{R=eLQ(n<1Y z_Pfl+@gJF)??GEFd<&Yuwpk5X4DWtZ=3ei|$xwsoLio_r1@Z?OuTvV*w5=bG$)<10 zs^E9v=(lr%zPl9w`X+p>sP5_~6 zzbd;2-+K{r!dhmgXiI%BI$OrNwfoYo7#}?o>w;PFpE;u)F`D|>j2>AXvd-2DYpG|= z>abE6_q+HcYYv@{{(!w^3jYwid7C%ChU3%2y|N;7Q1*d*e{41FB0G%U1tsh463m}n zlYPV!=v>Snn}S)RdvZ;?#nbI9Xjx+lbGTdP{WzX)A);ScFU$_=;#pu1#<5=Y4Fohl zuDRV94xo2~XW)Ra1WXhzq$b52XVJo#hS*!oX$6Y9Jx}bT7W3=1{O_2Du!5Phr{j1$ zTr)6C3SsmX=DDxhFE9|S(5}lG1|ruO!Z&6iFOw(~e5gmz4uUi6 zhxkLyOTc9A%0huxJTLnMZbC=wKO;)(w=5Fxfzm}~%mO|Ez0nrjHgtj7?a~i+U-A)g zC2^ybGr243=S68L@5Y;$BbfQRSTbnmU=3G#?#Dbd)75X;$EuIlqCWgZ`_Tg6CH|?4aX?*=PUu?M; z7|m>{4Xiz4H{ldq9qw;UCp9fI83(R|tE>bX)*G7`+nmjmRrBC+y@}K8 zP`6jb4zXTgf>#XpcwVSRlBU;09>&OwU*noNAb1AstOv_o19b?#j4S@bQ=DCw zZ;AE$4pi|x?)`0duQj7qmM}kQ0>bi|0~$X?&qFE8_)s-tFmJdky<~eZQTr}@1~z#0 z!0>Yg4vB$7P0AQ5s7rUFhm^53E?dW|cNWNKM0~vB{u*6UPTWav5QLAxE5K1n4B!a9 zA|c^TU=ed_r9x60J0*UY{3vN#c+>JDVf6Dt3Cz$dM(fgU4d*}9ru#PZvJrD(KCDIf z(C-vj*h)Onl!l8}ZytAw7>0Fb7VpoWd`1AU>UWoBLTKDBCf zP`v|#UXdiCBrq0P1?CCY_-*~Ol?d(pz$iv#KhYq8m^{RyEOuPu(DQb*qy@7Ec4PA! z(x_%69R*K1^ zd%#Q)#aVkR?qO<4el0y>$m>()F&A*yd`$ZP*zO9xwT{Yc7WY7a1#l?#y5;$;B{nWg z*#TzFm}Bs_j@RNd5J&n+C$uCrr|NYbpy+*SIagYwV^*iV`S)UNzrJLdf4 zqwsTH3Wy)v&v~i%$WFVTQ(nsSuP&a&AkRKInDR3ohoAFc?;X)RdVjy->d0**l49-J zwRd~+@QMd5?BL^^K$z4qgsy!KvOkB8IUlONB+nlWBI+e0|{IwoJoyT))iDO!Hp}}ukiUxlJt!O)9xUIRVtaV* z$R(BcOP+7d)FWN>qcv}8zBCV`fk%HPgR!22z z50~a9U%foSz@~0tKdfS&%p^T}+*8EHzBDW;;7w*QIW73SW_ii%rOp@*-tIOEow^qz z4?V^iuVUvI>29&c!3TR><%P2k8jSgSK#1KTiqrbD1q0{C)V@}&9KRp%7R1;ovW(dg z)~f6uZ~-swtGFX98;j$#yEDX?S@_O8+-u*5y!))_L7@uvl6eWobJfr%Gf&T_R}6lW z<6xg}8+lX)lKi;zswf3i0N!Qfi5ZOfMe7;J_sYze#V~>(h|p^vH8Iv{N79Eo#5^#- z8Q`WL=C)DxD)$kZ_Fg8&{kFWWoYFnG*Hzxe)9!Uu4(#$?SI%}HpVxJ>a3bo{OP(nD zLGJdrhgFQ5o|Nj2W09c!#J%pU+K$h9d(CCysYtM$f z9DQG#(Jz^@vvLOChO7f3Z6<1)#mBg_e3#w}c(t@ldB)_cRlf3e^xpci@LX}mm>f&p zt52WM=dChhtP)0Vy-|Hebe~(t^IkV2=2~8 z%7WQo|KMGb{}Y_jNmACMQyDES4y|K)X>kz`Dtl7vjQ659dQRLUx0+{X`QU;2kXL}Q zoX;7jUh;(*IXQ1#k0veYvCO28KZ}&wi?u)V%Yge&frIip`jz~J zwI}T;&d1A#XvzhX`0knVCNlhe@E+ve{rF3z9#y|OOy1~~QUgo%vkp@cLfMkg9`h0o zYyLOlT3r#sdok|6lw4&;Ud8!$YCdV_XkEj+9)ZZ)QC7Zk2B@%O%x5VrBiBjh=lR$j zctLyB*Jf8(>GS+nqOy!@%k2NO;e(ul4>J?^<*QwfG1V(nrABb9+o{SBC&%E98xa?} z6V#Uj2Yd^-FdU$?*=1)uyxw`8L*gBWUNZ@r!TY#&>aiy#GJNH6RDihwhB0-^4Ze{)1@2=i5Swz%}=2Y#!#4 z?&o8uBH}mcx-y{W=C$?wQCw#>e-wqFLn>Yi+{DRhT0IK>DE=~=KkEKCe_XygAoZRP zTQP^4JJkFAUEtax{LvJRUL=g;Ni?Jv4PTwbDOa24>U}sFo@wqW+!^DZW7IOFS}F)q z1q*u-9r{`P{yJz8eTI5)*gXHX%XjNGD@Es_YTk>YF~Qw<1}jY!#n40HTvQu-7~HR} z(g)0Wmfo>^yc_7UU&b|6{i8=$Cu4@h*%Xb|j)}uz8T}If-|uQ+o;5Y%6wOoIiqnzQ z*n1JZX0;}_SNIaOG6#*THVt{}3W)sxL3c%jAXE!EkIo?gWYb-Goj4s~Ke+!vdMSPr@> z72c2t_}Y06zQVa}G+cduA0yI6_2tO!0V+TQjaMhhbq{?;aMP;1mpQZgY2U?`)bo6* zN}S{zb8MkHhNGXyTG&_M_OwV6_KS0IZ(~=^$3N!F8GS5>#JzL7*m^$BPzs)$`as4a zxzTa{6xXR|MqPR8DSc5+rqnG=8}N(V2l6*~@=2Nfqe53`D>c=$>pCA}KA(#(f+&)K zShIIrSAUANf-llnSt}Agq0USsFVxbW5@Vk*udPYA6TJxgUKKCOX268@)Vnh!kn2Ui z8cDK@JVg8~^5n=SgrCqZ$JJeGL%uDTCvJh2OJ8teQ@H4}U4ijMcnPldaPbW3o!u9$ zQWH`*CXQwcPk7G$iAvgB6ZzB*k7cR}`uA8PnL2L+FHHed+$LwB#!j7lYH{YPn7=uz zSMX)QRxGVc@qfr&fxX8RoK%q*4gvR@M;YK~I|Hs5pP@zZxB1xnLm35F%LAsj6+`jt zw%0*)3oK^eX(tS>xikB0i1Ce@nb}v36ZHEws6>0+?syAj`VmE~#@IeJzZF1dKXuK&h?m23bSw1S`Ib45eiqQhzUb|a7Duw5`Wa5kqvt;fAA)v3 zT#Ozs6dh|`i_iBw2{&UN(9ah$D%A5<9IQ|O1tzxC^I5KH)?b!+J=<&ZF?bw!w?*xV z-HP>6H69H~5?4B{J+i73Dt${(wfEqpYxJrj=`4@K<=tw+;~t0Qb4tl3J(~9s%=XA` z1P6v9-xZ$(a=7&@q*a9H;iNqX!T@+b_D_B8ei6SxQtVjkmb&qW;D5xcfJQH`=i+U8 zT>cp7jrXS3a;@0S^+W}#n0+aTL*8qnGn;GG@)+-<<_ocfH5-hbFoo6g;O|FP6^LdR{bVS%~PiSYcokTFmn^ z|6SJA`c!&bPIyY2+Rj7^miGmZ1y-UxE@?LocLY0)6>*d5&^hra0HZOi*(y&8^Y(|)e5_;x7^?1oYS^?Q~WTr zz8mvl=HLc8biayT^J5*FIi4yse6Xjs(E4%7PNCPDx;D%BuSQ4YTph5rFN|>vE3RVO z=xs=2*sv&%K9nk~CnQbiS^R)i$(q5>04#uvJ>!DFi(P&J+{Jn1 zi}nm!kJ%Uo%=QT@?(lQWrj9qjshGfJNTS= zSqpP{0rU*KQgRbW3*W#K^CPbgSRUg`Uakq|xZSym%xlg*Wmv z{F8pIMJ60Ge(AN_2cNC2V<(?fj0~^u_hn>s(3WreX&|Y1s$wuH>%diJC#jEKg2s&; zOAEwsVMW|eZNnO#rGRBTe7&}mST#DDqGIgi_TClaLc2$_L2s*dihgaa=N=p*!_4x& z)>P3?zy|5($aio`nI1%^sb>B>Xcm1H-Ipu|`84}=Fdy_9bOp&b;kNWAc(8O{Lqsc= zPK3O~Hh2`0TE0`hv#;OGUF<2F9a+TMycsKk1HqZ`=Zsrwt-V>Vw1s_UeI-1Z3D3i475{^h z>)mKqD&1Uqz1IqNLw6qIu|LGjdCQ2o4m?zGMSByL)!NY|s8hbWi&g0FH5Q*Qb{f79 z^a{=)u|s6hXb#r<;bE+~*Z9vfug(?zm8Z7-#1U!H2-Zp_uu6% z7Q)>a-+Tf|{w}1B^5e2yS_f|f4`m(x8c-F^adtztxNSDQd6u^niz`ZU%=hoX;kYiq;d}M zT(lz2t!NI|k}baWeu`zN%sf?dVU2yS4`POy8#eCCk*7^npn6KlypR2CN5%$LV>x&8 zE#Je_khm)l#(OUgg8u@FgYJHg-A=U@Xq{*`dp`Qd!tKSohou|{x+j0f;rx`z9M zzaryW&7mEISy;M?ij`X{{nb4|hiFdVmi5;~@+#TLhgf1?P76gWvs#A0pXD6_nvyr(_uR+H^K#*Uo)`HnPP^x2`7DQ{ z@VpRpU5`xY*`60HBx^VDmfpKL=7Xu9=`|uo`f%PD;mqN@F_N*VyTHi=7c5h8t)3&8 zt0oUs+;cmik#+*yyR~|gKcvNZE2N}2uX}@Ak`L6&5cne2EHomU+Ve=6#+dRzNTzC! ziHFy|6lLZrN@gjD3{Vc9?R~~bD`rd&taB12pU}Eq#2m*+Zb=m0~yXi!oT=FhVN$`1y86t*s#ah(F1jC0Q(Nv88O8 z3mmv3o1f=pUn12VsZ4!Nvyo-TEbBe+j1mJhQ|v~sPI|Ii_VC_}{*nWXYoM*|h)g#| z;C;z)q@VO7C`0Mzf~o8&IPyMV%sR&QS9t0eF?zr_UXH`1)w24zAkl$77T$LB{Geb~ z3)`_d!4)4Dt6$t9ZPmoC+%X_xFBKMuJy^BgcwAb{{uV8>8`GkXP8)~TiNx9WO3&W$ zp_Wza;yquThdbz9{YcQDM@n6H3{$M3(F&YQ`dG$F8m?+7xMke6eR(*wSDq{=W0zKylQ;h|`~ zdksAv2uKE`B#>8!U0XyJEX$kVAn+ohCR#<$@x9wOLOO3oD`d?3fQNXirRdkOhP&Z; z1$uqf1+qB%heP(>G53P+9N+c(fQI~LV3>0pfK-nG@_HeOuqBzB)-s$0yjU>xig9b81`_nJbNMja=M2esJB5j{`{;OThjQ!k<@4vaOj~&2R%XYB3j~)SIZjK_hNp? zXI2J3f?vHV{pI?B(d>5YHZqtVSc@~@{q5@R4lnP$`CGvDi`b*5#dj@!E#3*QwwzF_ z^tS*fWD@!sT-+uj}n2Zw9V^c_cL@8)j45t8^;aMi7HqU49DEOsY;arfJ}wsPh#vC}VOy#+});vN!yr+i+CZM9ZBsSK`XG^6PO}A)lT3KLIT`-Pw2wjic2UR^m#nFI))wR;|vS z`Jb5UX@w{nr%pTb4TxSZ(in)5*#aD&21Eo=;B_^wT@Scl3#g-wJ&Ai)1D03gD$l}i zFD(gC_UmFidzvA7aSx(=I~x$X7|?kfpWrB31n*A27Tk0T zD{yo@+AR-Ja;r}_L@(_@ly7GPE*In9m4Mf^z_`l+v!{W5`~#wo;;L};Q9uqHy;53% z!(b+DuLn%7L{H05y|mTS4N=~~C93BeR1e)$6PvjC#TR_-IGp#Pl$ zTe!tez!up;{9!qWUXHO(JJnM^R1oDG5QTz)47MWN6CUs={sB?27Kwd5poca9ypdJN z{wsw~z+u^y6KranJRD6tJa|B2owMf#@5_1TNzb zxfb8iFrUVi3rj+j9Xah(4>Sc+oiRjzLRS}#qHThatn_Jt>4ktLIu-iWdbAWwfhQgs zuvqeIeMy*t?WdjY!7Ia*Z)XEKU?|cE>;!7aawHCT%0KXwyX*p9Mr0Ct71cn|qL6Ku zmw@TTVmHy#>8AV(0UN{AmJ^wVKnAT-`VxLac<810d=fAQrfB}+tCs?%*spL5B=+Ti z$}&0>FufSho_;({+evte=6*4tgDwh9!#nXC@(r1UJmMPIi0!l;->_DJD!Kxk0~jA% zLIG2D@ATtoT2I1Lxa8A-+|_{FPT(Ax(zUoE>j_RP9?O|mu5HIXeMcV!_D_N*EMq+Z zQ?UQ^%c!)UWaFdjb21x@6Yqp$K8ma0DHYklSbk$Q0deW6U>LB4{=w_z@RX-dKc1!q zB`Y6Z2yaBw#J+@gVl7FRLYD_mu}9_G1DAn0oR;U1Z(!6 z@PH}4QLaJz(g1)lTmW5aC;k%Ez7VYs4%16Tm-;QpsI;SG>#qf-0Tbz`*!n;UixHS2 z%9H&}Z;puLRu1eikkr=6b?!?0~?Yaa;%Mgk!yUVbL@CSWS)qG@51 z>MoiU76RS@_yD@Wa(K$Pr(N#jbuvt4?<2dBNKiIjP-GN&E#M?M4czA%dJ}e(I0YO5 zi6);FF|6fa3Z9>Sn5G>C#^Q@cN92V3c0d+O2~L3I2c}3MvQkGP2V0UAF10FMFsf#lQE0$<`N%h5hQ?b9!# z(vGr^pEweJ(yM_r&_2J>oPa6*DYPmiz2J<`4==XPYQQlr#FGcprTosUbI~VO@#*$U z;rD1|6i`8X!dn6zug3T7fSUZL@JjF$zyH+&XY&292;c?iS<+yE%i>;sS1CRhTO&DL7-Ihk_EL}6hm#5Bgh!D%TK5H? ze;ubNl{4ydCCT|8?d9*P1?SAk+tn{Jq?Lhqb}Z z9V{>R^g`EMS#SngcS?3Q8UKbYCq-1xTctUh26-3s zw`-^kQWItoP4Uy__xRLpy+bMEP)6sc>U8QeJ(Y;-D<70T#PwaDJ~hut4x~nd@7=Hm z*Aw!PsD&(>*-z zI!e2F=tVtT??+*c+uJ(N3UA?@7Ur0pYz!fT(71BtkT&g6&(U@~Sq+}!)sJkBwuXr( zc#hXTvN_s{BtrbL&e1j)k?)Unj<#Tk9(j(3^`{>-&Da7U4(K@^)_Z=`bF}76RNQkM zdO{E8Pdn;4T1Og=Bx8_G=ZUhLEVI{QX7H_ zk{j{Psc+&JH63J`ya^2n>HaXR6MWby+gGCX&G<*n9co2v#=URjn(9K(!-J^J^VjHS z_~e6Vc_(TaZp7yg(Zhemn0#i1h(0=T(0Q)MjHn~_Bxb?9sh>neqO5PR=zdvQ3NF;`oBwphh&{rTga;Wxoqo-NH&^6BH-`EQDsAm5F*I4r?>BClJZ|ss^Yw>vwpPL8ggK{d>6~oh4*BoAacKGS)C*ST%U-C&U4mZz` z43B>-q07#G{y5;MSuPI0c6R&W-?F<)rvEZ?(o;tdr}mu^@0Z@ydHo#!tQ9SNbYRH# zv#$F&`dQyC6iTg}Wh_DA=d3>F&2~9DuSZ%BYZLCGxqlV&rv|Jv=f!NF;q2%2Id3)f zOeDMNEA`wC%GvIQwxDXMJzgAKM@NI$zpr`gT#m!cUc=&CXZGBWhb!ismzm@7%&FIM z9f4bXhQj!H{mk3_cFYR@ew#7l|wx8`m z_h{_-d8_i5xKb)&?k1ZQer+- z9shHD=Um>O1G@#4UJo_*VpO6=Sv`DS%Zv-bK{g}ew79ftJxz{dEdsOKP5f#+l65;) z0VM96`Kqj@j%3;Ep143h46Sd+e?ITUN|Zgdf4nVWKrezFFehH8UAPxlfzOTjeP_3Y z+C7XNzPYzs!*(YZzc5T|54!in(F`CxcAq_41m3C%e=s=z*u)+`4)|K9JP5AVaP#v$ zJbisXc#=nqmV_MVtpW#uYmV_T;H`KO7EtY9TpX_B&o2wtSDlWsC{Oq}VY;}NQnYVa z>N(4at-!V3Cp(YU(dFy*mi)6}*^Zk$`QyRQUIOME_t%?i*v{&whPAx0`$70|(7htu zi@=pWKVE3on#X=x>^x|?pJl0kyRnQ+)BD4@m5F}tV}f{k!Fmi_oYS_eoZVv&{n;&R zDw>DyFN34(=kJ`SzlpyrGLMgkM#lU`2ceDr`F>XtOXq8DuYN-kaop-%oC1VL= 1 -AND CHARINDEX('F',userTypeDefaultPermissions,0) < 1 -; - -UPDATE umbracoUserType SET userTypeDefaultPermissions = userTypeDefaultPermissions + 'H' WHERE userTypeAlias = 'writer' -AND CHARINDEX('F',userTypeDefaultPermissions,0) < 1 -; - -INSERT INTO umbracoUser2NodePermission (userID, nodeId, permission) -SELECT userID, nodeId, 'F' FROM umbracoUser2NodePermission WHERE permission='A' -; - -INSERT INTO umbracoUser2NodePermission (userID, nodeId, permission) -SELECT DISTINCT userID, nodeId, 'H' FROM umbracoUser2NodePermission WHERE userId IN -(SELECT umbracoUser.id FROM umbracoUserType INNER JOIN umbracoUser ON umbracoUserType.id = umbracoUser.userType WHERE (umbracoUserType.userTypeAlias = 'writer')) -; - -alter TABLE [cmsContentType] -add [masterContentType] int NULL CONSTRAINT -[DF_cmsContentType_masterContentType] DEFAULT (0) -; -CREATE TABLE [cmsTagRelationship]( - [nodeId] [int] NOT NULL, - [tagId] [int] NOT NULL) -; - -CREATE TABLE [cmsTags]( - [id] [int] IDENTITY(1,1) NOT NULL, - [tag] [nvarchar](200) NULL, - [parentId] [int] NULL, - [group] [nvarchar](100) NULL) -; -alter TABLE [umbracoUser] -add [defaultToLiveEditing] bit NOT NULL CONSTRAINT -[DF_umbracoUser_defaultToLiveEditing] DEFAULT (0) -; - -CREATE TABLE [cmsPreviewXml]( - [nodeId] [int] NOT NULL, - [versionId] [uniqueidentifier] NOT NULL, - [timestamp] [datetime] NOT NULL, - [xml] [ntext] NOT NULL) -; - - -ALTER TABLE [umbracoNode] ALTER COLUMN id IDENTITY(1042,1) -; -ALTER TABLE [cmsContentType] ALTER COLUMN pk IDENTITY(535,1) -; -ALTER TABLE [umbracoUser] ALTER COLUMN id IDENTITY(1,1) -; -ALTER TABLE [umbracoUserType] ALTER COLUMN id IDENTITY(5,1) -; -ALTER TABLE [cmsMacroPropertyType] ALTER COLUMN id IDENTITY(26,1) -; -ALTER TABLE [cmsTab] ALTER COLUMN id IDENTITY(6,1) -; -ALTER TABLE [cmsPropertyType] ALTER COLUMN id IDENTITY(28,1) -; -ALTER TABLE [umbracoLanguage] ALTER COLUMN id IDENTITY(2,1) -; -ALTER TABLE [cmsDataType] ALTER COLUMN pk IDENTITY(39,1) -; -ALTER TABLE [cmsDataTypePreValues] ALTER COLUMN id IDENTITY(5,1) \ No newline at end of file diff --git a/src/Umbraco.Tests/Migrations/SqlScripts/SqlResources.Designer.cs b/src/Umbraco.Tests/Migrations/SqlScripts/SqlResources.Designer.cs deleted file mode 100644 index 7a7cee0ce3..0000000000 --- a/src/Umbraco.Tests/Migrations/SqlScripts/SqlResources.Designer.cs +++ /dev/null @@ -1,143 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Umbraco.Tests.Migrations.SqlScripts { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class SqlResources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal SqlResources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Umbraco.Tests.Migrations.SqlScripts.SqlResources", typeof(SqlResources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to CREATE TABLE [umbracoUserType] ( - /// [id] int NOT NULL IDENTITY (5,1) - ///, [userTypeAlias] nvarchar(50) NULL - ///, [userTypeName] nvarchar(255) NOT NULL - ///, [userTypeDefaultPermissions] nvarchar(50) NULL - ///); - ///GO - ///CREATE TABLE [umbracoUser2NodePermission] ( - /// [userId] int NOT NULL - ///, [nodeId] int NOT NULL - ///, [permission] nchar(1) NOT NULL - ///); - ///GO - ///CREATE TABLE [umbracoUser2NodeNotify] ( - /// [userId] int NOT NULL - ///, [nodeId] int NOT NULL - ///, [action] nchar(1) NOT NULL - ///); - ///GO - ///CREATE TABLE [umbracoUser] ( - /// [id] in [rest of string was truncated]";. - /// - internal static string SqlCe_SchemaAndData_4110 { - get { - return ResourceManager.GetString("SqlCe_SchemaAndData_4110", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to CREATE TABLE [umbracoRelation] - ///( - ///[id] [int] NOT NULL IDENTITY(1, 1), - ///[parentId] [int] NOT NULL, - ///[childId] [int] NOT NULL, - ///[relType] [int] NOT NULL, - ///[datetime] [datetime] NOT NULL CONSTRAINT [DF_umbracoRelation_datetime] DEFAULT (getdate()), - ///[comment] [nvarchar] (1000) NOT NULL - ///) - /// - ///; - ///ALTER TABLE [umbracoRelation] ADD CONSTRAINT [PK_umbracoRelation] PRIMARY KEY ([id]) - ///; - ///CREATE TABLE [cmsDocument] - ///( - ///[nodeId] [int] NOT NULL, - ///[published] [bit] NOT NULL, - ///[documentUser] [int] NOT [rest of string was truncated]";. - /// - internal static string SqlCeTotal_480 { - get { - return ResourceManager.GetString("SqlCeTotal_480", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to /******************************************************************************************* - /// - /// - /// - /// - /// - /// - /// - /// Umbraco database installation script for SQL Server - /// - ///IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT - /// - /// Database version: 4.8.0.0 - /// - /// Please increment this version number if ANY change is made to this script, - /// so compatibility with scripts for other database systems can be verified easily. - /// The first 3 digits depict the Umbraco versi [rest of string was truncated]";. - /// - internal static string SqlServerTotal_480 { - get { - return ResourceManager.GetString("SqlServerTotal_480", resourceCulture); - } - } - } -} diff --git a/src/Umbraco.Tests/Migrations/SqlScripts/SqlResources.resx b/src/Umbraco.Tests/Migrations/SqlScripts/SqlResources.resx deleted file mode 100644 index 20ba6d0e8e..0000000000 --- a/src/Umbraco.Tests/Migrations/SqlScripts/SqlResources.resx +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - sqlcetotal-480.sql;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 - - - sqlce-schemaanddata-4110.sql;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16 - - - sqlservertotal-480.sql;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 - - diff --git a/src/Umbraco.Tests/Migrations/SqlScripts/SqlServerTotal-480.sql b/src/Umbraco.Tests/Migrations/SqlScripts/SqlServerTotal-480.sql deleted file mode 100644 index e69d87f759..0000000000 --- a/src/Umbraco.Tests/Migrations/SqlScripts/SqlServerTotal-480.sql +++ /dev/null @@ -1,1671 +0,0 @@ -/******************************************************************************************* - - - - - - - - Umbraco database installation script for SQL Server - -IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT - - Database version: 4.8.0.0 - - Please increment this version number if ANY change is made to this script, - so compatibility with scripts for other database systems can be verified easily. - The first 3 digits depict the Umbraco version, the last digit is the database version. - (e.g. version 4.0.0.3 means "Umbraco version 4.0.0, database version 3") - - Check-in policy: only commit this script if - * you ran the Umbraco installer completely; - * you ran it on the targetted database system; - * you ran the Runway and Module installations; - * you were able to browse the Boost site; - * you were able to open the Umbraco administration panel; - * you have documented the code change in this script; - * you have incremented the version number in this script. - -IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT - - - - - - - -********************************************************************************************/ - -CREATE TABLE [umbracoRelation] -( -[id] [int] NOT NULL IDENTITY(1, 1), -[parentId] [int] NOT NULL, -[childId] [int] NOT NULL, -[relType] [int] NOT NULL, -[datetime] [datetime] NOT NULL CONSTRAINT [DF_umbracoRelation_datetime] DEFAULT (getdate()), -[comment] [nvarchar] (1000) COLLATE Danish_Norwegian_CI_AS NOT NULL -) - -; -ALTER TABLE [umbracoRelation] ADD CONSTRAINT [PK_umbracoRelation] PRIMARY KEY CLUSTERED ([id]) -; -CREATE TABLE [cmsDocument] -( -[nodeId] [int] NOT NULL, -[published] [bit] NOT NULL, -[documentUser] [int] NOT NULL, -[versionId] [uniqueidentifier] NOT NULL, -[text] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[releaseDate] [datetime] NULL, -[expireDate] [datetime] NULL, -[updateDate] [datetime] NOT NULL CONSTRAINT [DF_cmsDocument_updateDate] DEFAULT (getdate()), -[templateId] [int] NULL, -[alias] [nvarchar] (255) COLLATE Danish_Norwegian_CI_AS NULL , -[newest] [bit] NOT NULL CONSTRAINT [DF_cmsDocument_newest] DEFAULT (0) -) - -; -ALTER TABLE [cmsDocument] ADD CONSTRAINT [PK_cmsDocument] PRIMARY KEY CLUSTERED ([versionId]) -; -CREATE TABLE [umbracoLog] -( -[id] [int] NOT NULL IDENTITY(1, 1), -[userId] [int] NOT NULL, -[NodeId] [int] NOT NULL, -[Datestamp] [datetime] NOT NULL CONSTRAINT [DF_umbracoLog_Datestamp] DEFAULT (getdate()), -[logHeader] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[logComment] [nvarchar] (1000) COLLATE Danish_Norwegian_CI_AS NULL -) - -; -ALTER TABLE [umbracoLog] ADD CONSTRAINT [PK_umbracoLog] PRIMARY KEY CLUSTERED ([id]) -; - -/* TABLES ARE NEVER USED, REMOVED FOR 4.1 - -CREATE TABLE [umbracoUserGroup] -( -[id] [smallint] NOT NULL IDENTITY(1, 1), -[userGroupName] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL -) -; -ALTER TABLE [umbracoUserGroup] ADD CONSTRAINT [PK_userGroup] PRIMARY KEY CLUSTERED ([id]) -; -CREATE TABLE [umbracoUser2userGroup] -( -[user] [int] NOT NULL, -[userGroup] [smallint] NOT NULL -) -; -ALTER TABLE [umbracoUser2userGroup] ADD CONSTRAINT [PK_user2userGroup] PRIMARY KEY CLUSTERED ([user], [userGroup]) -; - -*/ - -CREATE TABLE [umbracoApp] -( -[sortOrder] [tinyint] NOT NULL CONSTRAINT [DF_app_sortOrder] DEFAULT (0), -[appAlias] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[appIcon] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[appName] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[appInitWithTreeAlias] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL -) - -; -ALTER TABLE [umbracoApp] ADD CONSTRAINT [PK_umbracoApp] PRIMARY KEY CLUSTERED ([appAlias]) -; -CREATE TABLE [cmsPropertyData] -( -[id] [int] NOT NULL IDENTITY(1, 1), -[contentNodeId] [int] NOT NULL, -[versionId] [uniqueidentifier] NULL, -[propertytypeid] [int] NOT NULL, -[dataInt] [int] NULL, -[dataDate] [datetime] NULL, -[dataNvarchar] [nvarchar] (500) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, -[dataNtext] [ntext] COLLATE SQL_Latin1_General_CP1_CI_AS NULL -) - -; -ALTER TABLE [cmsPropertyData] ADD CONSTRAINT [PK_cmsPropertyData] PRIMARY KEY CLUSTERED ([id]) -; -CREATE NONCLUSTERED INDEX [IX_cmsPropertyData] ON [cmsPropertyData] ([id]) -; -CREATE NONCLUSTERED INDEX [IX_cmsPropertyData_1] ON [cmsPropertyData] ([contentNodeId]) -; -CREATE NONCLUSTERED INDEX [IX_cmsPropertyData_2] ON [cmsPropertyData] ([versionId]) -; -CREATE NONCLUSTERED INDEX [IX_cmsPropertyData_3] ON [cmsPropertyData] ([propertytypeid]) -; -CREATE TABLE [cmsContent] -( -[pk] [int] NOT NULL IDENTITY(1, 1), -[nodeId] [int] NOT NULL, -[contentType] [int] NOT NULL -) - -; -ALTER TABLE [cmsContent] ADD CONSTRAINT [PK_cmsContent] PRIMARY KEY CLUSTERED ([pk]) -; -CREATE TABLE [cmsContentType] -( -[pk] [int] NOT NULL IDENTITY(1, 1), -[nodeId] [int] NOT NULL, -[alias] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, -[icon] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL -) - -; -ALTER TABLE [cmsContentType] ADD CONSTRAINT [PK_cmsContentType] PRIMARY KEY CLUSTERED ([pk]) -; -CREATE TABLE [cmsMacroPropertyType] -( -[id] [smallint] NOT NULL IDENTITY(1, 1), -[macroPropertyTypeAlias] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, -[macroPropertyTypeRenderAssembly] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, -[macroPropertyTypeRenderType] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, -[macroPropertyTypeBaseType] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL -) - -; -ALTER TABLE [cmsMacroPropertyType] ADD CONSTRAINT [PK_macroPropertyType] PRIMARY KEY CLUSTERED ([id]) -; - -/* TABLE IS NEVER USED, REMOVED FOR 4.1 - -CREATE TABLE [umbracoStylesheetProperty] -( -[id] [smallint] NOT NULL IDENTITY(1, 1), -[stylesheetPropertyEditor] [bit] NOT NULL CONSTRAINT [DF_stylesheetProperty_stylesheetPropertyEditor] DEFAULT (0), -[stylesheet] [tinyint] NOT NULL, -[stylesheetPropertyAlias] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, -[stylesheetPropertyName] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, -[stylesheetPropertyValue] [nvarchar] (400) COLLATE SQL_Latin1_General_CP1_CI_AS NULL -) -; - -ALTER TABLE [umbracoStylesheetProperty] ADD CONSTRAINT [PK_stylesheetProperty] PRIMARY KEY CLUSTERED ([id]) -; - -*/ - -CREATE TABLE [cmsTab] -( -[id] [int] NOT NULL IDENTITY(1, 1), -[contenttypeNodeId] [int] NOT NULL, -[text] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[sortorder] [int] NOT NULL -) - -; -ALTER TABLE [cmsTab] ADD CONSTRAINT [PK_cmsTab] PRIMARY KEY CLUSTERED ([id]) -; -CREATE TABLE [cmsTemplate] -( -[pk] [int] NOT NULL IDENTITY(1, 1), -[nodeId] [int] NOT NULL, -[master] [int] NULL, -[alias] [nvarchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, -[design] [ntext] COLLATE Danish_Norwegian_CI_AS NOT NULL -) - -; -ALTER TABLE [cmsTemplate] ADD CONSTRAINT [PK_templates] PRIMARY KEY CLUSTERED ([pk]) -; -CREATE TABLE [umbracoUser2app] -( -[user] [int] NOT NULL, -[app] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL -) - -; -ALTER TABLE [umbracoUser2app] ADD CONSTRAINT [PK_user2app] PRIMARY KEY CLUSTERED ([user], [app]) -; -CREATE TABLE [umbracoUserType] -( -[id] [smallint] NOT NULL IDENTITY(1, 1), -[userTypeAlias] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, -[userTypeName] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[userTypeDefaultPermissions] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL -) - -; -ALTER TABLE [umbracoUserType] ADD CONSTRAINT [PK_userType] PRIMARY KEY CLUSTERED ([id]) -; -CREATE TABLE [umbracoUser] -( -[id] [int] NOT NULL IDENTITY(1, 1), -[userDisabled] [bit] NOT NULL CONSTRAINT [DF_umbracoUser_userDisabled] DEFAULT (0), -[userNoConsole] [bit] NOT NULL CONSTRAINT [DF_umbracoUser_userNoConsole] DEFAULT (0), -[userType] [smallint] NOT NULL, -[startStructureID] [int] NOT NULL, -[startMediaID] [int] NULL, -[userName] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[userLogin] [nvarchar] (125) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[userPassword] [nvarchar] (125) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[userEmail] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[userDefaultPermissions] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, -[userLanguage] [nvarchar] (10) COLLATE SQL_Latin1_General_CP1_CI_AS NULL -) - -; -ALTER TABLE [umbracoUser] ADD CONSTRAINT [PK_user] PRIMARY KEY CLUSTERED ([id]) -; -CREATE TABLE [cmsDocumentType] -( -[contentTypeNodeId] [int] NOT NULL, -[templateNodeId] [int] NOT NULL, -[IsDefault] [bit] NOT NULL CONSTRAINT [DF_cmsDocumentType_IsDefault] DEFAULT (0) -) - -; -ALTER TABLE [cmsDocumentType] ADD CONSTRAINT [PK_cmsDocumentType] PRIMARY KEY CLUSTERED ([contentTypeNodeId], [templateNodeId]) -; -CREATE TABLE [cmsMemberType] -( -[pk] [int] NOT NULL IDENTITY(1, 1), -[NodeId] [int] NOT NULL, -[propertytypeId] [int] NOT NULL, -[memberCanEdit] [bit] NOT NULL CONSTRAINT [DF_cmsMemberType_memberCanEdit] DEFAULT (0), -[viewOnProfile] [bit] NOT NULL CONSTRAINT [DF_cmsMemberType_viewOnProfile] DEFAULT (0) -) - -; -ALTER TABLE [cmsMemberType] ADD CONSTRAINT [PK_cmsMemberType] PRIMARY KEY CLUSTERED ([pk]) -; -CREATE TABLE [cmsMember] -( -[nodeId] [int] NOT NULL, -[Email] [nvarchar] (1000) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL CONSTRAINT [DF_cmsMember_Email] DEFAULT (''), -[LoginName] [nvarchar] (1000) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL CONSTRAINT [DF_cmsMember_LoginName] DEFAULT (''), -[Password] [nvarchar] (1000) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL CONSTRAINT [DF_cmsMember_Password] DEFAULT ('') -) - -; -CREATE TABLE [umbracoNode] -( -[id] [int] NOT NULL IDENTITY(1, 1), -[trashed] [bit] NOT NULL CONSTRAINT [DF_umbracoNode_trashed] DEFAULT (0), -[parentID] [int] NOT NULL, -[nodeUser] [int] NULL, -[level] [smallint] NOT NULL, -[path] [nvarchar] (150) COLLATE Danish_Norwegian_CI_AS NOT NULL, -[sortOrder] [int] NOT NULL, -[uniqueID] [uniqueidentifier] NULL, -[text] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, -[nodeObjectType] [uniqueidentifier] NULL, -[createDate] [datetime] NOT NULL CONSTRAINT [DF_umbracoNode_createDate] DEFAULT (getdate()) -) - -; -ALTER TABLE [umbracoNode] ADD CONSTRAINT [PK_structure] PRIMARY KEY CLUSTERED ([id]) -; -CREATE NONCLUSTERED INDEX [IX_umbracoNodeParentId] ON [umbracoNode] ([parentID]) -; -CREATE NONCLUSTERED INDEX [IX_umbracoNodeObjectType] ON [umbracoNode] ([nodeObjectType]) -; -CREATE TABLE [cmsPropertyType] -( -[id] [int] NOT NULL IDENTITY(1, 1), -[dataTypeId] [int] NOT NULL, -[contentTypeId] [int] NOT NULL, -[tabId] [int] NULL, -[Alias] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[Name] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, -[helpText] [nvarchar] (1000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, -[sortOrder] [int] NOT NULL CONSTRAINT [DF__cmsProper__sortO__1EA48E88] DEFAULT (0), -[mandatory] [bit] NOT NULL CONSTRAINT [DF__cmsProper__manda__2180FB33] DEFAULT (0), -[validationRegExp] [nvarchar] (255) COLLATE Danish_Norwegian_CI_AS NULL, -[Description] [nvarchar] (2000) COLLATE Danish_Norwegian_CI_AS NULL -) - -; -ALTER TABLE [cmsPropertyType] ADD CONSTRAINT [PK_cmsPropertyType] PRIMARY KEY CLUSTERED ([id]) -; - -CREATE TABLE [cmsMacroProperty] -( -[id] [int] NOT NULL IDENTITY(1, 1), -[macroPropertyHidden] [bit] NOT NULL CONSTRAINT [DF_macroProperty_macroPropertyHidden] DEFAULT (0), -[macroPropertyType] [smallint] NOT NULL, -[macro] [int] NOT NULL, -[macroPropertySortOrder] [tinyint] NOT NULL CONSTRAINT [DF_macroProperty_macroPropertySortOrder] DEFAULT (0), -[macroPropertyAlias] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[macroPropertyName] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL -) - -; -ALTER TABLE [cmsMacroProperty] ADD CONSTRAINT [PK_macroProperty] PRIMARY KEY CLUSTERED ([id]) -; -CREATE TABLE [cmsMacro] -( -[id] [int] NOT NULL IDENTITY(1, 1), -[macroUseInEditor] [bit] NOT NULL CONSTRAINT [DF_macro_macroUseInEditor] DEFAULT (0), -[macroRefreshRate] [int] NOT NULL CONSTRAINT [DF_macro_macroRefreshRate] DEFAULT (0), -[macroAlias] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[macroName] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, -[macroScriptType] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, -[macroScriptAssembly] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, -[macroXSLT] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, -[macroCacheByPage] [bit] NOT NULL CONSTRAINT [DF_cmsMacro_macroCacheByPage] DEFAULT (1), -[macroCachePersonalized] [bit] NOT NULL CONSTRAINT [DF_cmsMacro_macroCachePersonalized] DEFAULT (0), -[macroDontRender] [bit] NOT NULL CONSTRAINT [DF_cmsMacro_macroDontRender] DEFAULT (0) -) - -; -ALTER TABLE [cmsMacro] ADD CONSTRAINT [PK_macro] PRIMARY KEY CLUSTERED ([id]) -; -CREATE TABLE [cmsContentVersion] -( -[id] [int] NOT NULL IDENTITY(1, 1) PRIMARY KEY, -[ContentId] [int] NOT NULL, -[VersionId] [uniqueidentifier] NOT NULL, -[VersionDate] [datetime] NOT NULL CONSTRAINT [DF_cmsContentVersion_VersionDate] DEFAULT (getdate()) -) - -; -CREATE TABLE [umbracoAppTree] -( -[treeSilent] [bit] NOT NULL CONSTRAINT [DF_umbracoAppTree_treeSilent] DEFAULT (0), -[treeInitialize] [bit] NOT NULL CONSTRAINT [DF_umbracoAppTree_treeInitialize] DEFAULT (1), -[treeSortOrder] [tinyint] NOT NULL, -[appAlias] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[treeAlias] [nvarchar] (150) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[treeTitle] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[treeIconClosed] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[treeIconOpen] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[treeHandlerAssembly] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[treeHandlerType] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[action] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL -) - -; -ALTER TABLE [umbracoAppTree] ADD CONSTRAINT [PK_umbracoAppTree] PRIMARY KEY CLUSTERED ([appAlias], [treeAlias]) -; - -CREATE TABLE [cmsContentTypeAllowedContentType] -( -[Id] [int] NOT NULL, -[AllowedId] [int] NOT NULL -) - -; -ALTER TABLE [cmsContentTypeAllowedContentType] ADD CONSTRAINT [PK_cmsContentTypeAllowedContentType] PRIMARY KEY CLUSTERED ([Id], [AllowedId]) -; -CREATE TABLE [cmsContentXml] -( -[nodeId] [int] NOT NULL, -[xml] [ntext] COLLATE Danish_Norwegian_CI_AS NOT NULL -) - -; -ALTER TABLE [cmsContentXml] ADD CONSTRAINT [PK_cmsContentXml] PRIMARY KEY CLUSTERED ([nodeId]) -; -CREATE TABLE [cmsDataType] -( -[pk] [int] NOT NULL IDENTITY(1, 1), -[nodeId] [int] NOT NULL, -[controlId] [uniqueidentifier] NOT NULL, -[dbType] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL -) - -; -ALTER TABLE [cmsDataType] ADD CONSTRAINT [PK_cmsDataType] PRIMARY KEY CLUSTERED ([pk]) -; -CREATE TABLE [cmsDataTypePreValues] -( -[id] [int] NOT NULL IDENTITY(1, 1), -[datatypeNodeId] [int] NOT NULL, -[value] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, -[sortorder] [int] NOT NULL, -[alias] [nvarchar] (50) COLLATE Danish_Norwegian_CI_AS NULL -) - -; -ALTER TABLE [cmsDataTypePreValues] ADD CONSTRAINT [PK_cmsDataTypePreValues] PRIMARY KEY CLUSTERED ([id]) -; -CREATE TABLE [cmsDictionary] -( -[pk] [int] NOT NULL IDENTITY(1, 1), -[id] [uniqueidentifier] NOT NULL, -[parent] [uniqueidentifier] NOT NULL, -[key] [nvarchar] (1000) COLLATE Danish_Norwegian_CI_AS NOT NULL -) - -; -ALTER TABLE [cmsDictionary] ADD CONSTRAINT [PK_cmsDictionary] PRIMARY KEY CLUSTERED ([pk]) -; -CREATE TABLE [cmsLanguageText] -( -[pk] [int] NOT NULL IDENTITY(1, 1), -[languageId] [int] NOT NULL, -[UniqueId] [uniqueidentifier] NOT NULL, -[value] [nvarchar] (1000) COLLATE Danish_Norwegian_CI_AS NOT NULL -) - -; -ALTER TABLE [cmsLanguageText] ADD CONSTRAINT [PK_cmsLanguageText] PRIMARY KEY CLUSTERED ([pk]) -; -CREATE TABLE [cmsMember2MemberGroup] -( -[Member] [int] NOT NULL, -[MemberGroup] [int] NOT NULL -) - -; -ALTER TABLE [cmsMember2MemberGroup] ADD CONSTRAINT [PK_cmsMember2MemberGroup] PRIMARY KEY CLUSTERED ([Member], [MemberGroup]) -; -CREATE TABLE [cmsStylesheet] -( -[nodeId] [int] NOT NULL, -[filename] [nvarchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[content] [ntext] COLLATE SQL_Latin1_General_CP1_CI_AS NULL -) - -; -CREATE TABLE [cmsStylesheetProperty] -( -[nodeId] [int] NOT NULL, -[stylesheetPropertyEditor] [bit] NULL, -[stylesheetPropertyAlias] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, -[stylesheetPropertyValue] [nvarchar] (400) COLLATE SQL_Latin1_General_CP1_CI_AS NULL -) - -; -CREATE TABLE [umbracoDomains] -( -[id] [int] NOT NULL IDENTITY(1, 1), -[domainDefaultLanguage] [int] NULL, -[domainRootStructureID] [int] NULL, -[domainName] [nvarchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL -) - -; -ALTER TABLE [umbracoDomains] ADD CONSTRAINT [PK_domains] PRIMARY KEY CLUSTERED ([id]) -; -CREATE TABLE [umbracoLanguage] -( -[id] [smallint] NOT NULL IDENTITY(1, 1), -[languageISOCode] [nvarchar] (10) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, -[languageCultureName] [nvarchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL -) - -; -ALTER TABLE [umbracoLanguage] ADD CONSTRAINT [PK_language] PRIMARY KEY CLUSTERED ([id]) -; -CREATE TABLE [umbracoRelationType] -( -[id] [int] NOT NULL IDENTITY(1, 1), -[dual] [bit] NOT NULL, -[parentObjectType] [uniqueidentifier] NOT NULL, -[childObjectType] [uniqueidentifier] NOT NULL, -[name] [nvarchar] (255) COLLATE Danish_Norwegian_CI_AS NOT NULL, -[alias] [nvarchar] (100) COLLATE Danish_Norwegian_CI_AS NULL -) - -; -ALTER TABLE [umbracoRelationType] ADD CONSTRAINT [PK_umbracoRelationType] PRIMARY KEY CLUSTERED ([id]) -; - -/* TABLE IS NEVER USED, REMOVED FOR 4.1 - -CREATE TABLE [umbracoStylesheet] -( -[nodeId] [int] NOT NULL, -[filename] [nvarchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, -[content] [ntext] COLLATE SQL_Latin1_General_CP1_CI_AS NULL -) -; - -ALTER TABLE [umbracoStylesheet] ADD CONSTRAINT [PK_umbracoStylesheet] PRIMARY KEY CLUSTERED ([nodeId]) -; - -*/ - -CREATE TABLE [umbracoUser2NodeNotify] -( -[userId] [int] NOT NULL, -[nodeId] [int] NOT NULL, -[action] [char] (1) COLLATE Danish_Norwegian_CI_AS NOT NULL -) - -; -ALTER TABLE [umbracoUser2NodeNotify] ADD CONSTRAINT [PK_umbracoUser2NodeNotify] PRIMARY KEY CLUSTERED ([userId], [nodeId], [action]) -; -CREATE TABLE [umbracoUser2NodePermission] -( -[userId] [int] NOT NULL, -[nodeId] [int] NOT NULL, -[permission] [char] (1) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL -) - -; -ALTER TABLE [umbracoUser2NodePermission] ADD CONSTRAINT [PK_umbracoUser2NodePermission] PRIMARY KEY CLUSTERED ([userId], [nodeId], [permission]) -; -ALTER TABLE [umbracoAppTree] ADD -CONSTRAINT [FK_umbracoAppTree_umbracoApp] FOREIGN KEY ([appAlias]) REFERENCES [umbracoApp] ([appAlias]) -; -ALTER TABLE [cmsPropertyData] ADD -CONSTRAINT [FK_cmsPropertyData_umbracoNode] FOREIGN KEY ([contentNodeId]) REFERENCES [umbracoNode] ([id]) -; - -/* TABLES ARE NEVER USED, REMOVED FOR 4.1 - -ALTER TABLE [umbracoUser2userGroup] ADD -CONSTRAINT [FK_user2userGroup_user] FOREIGN KEY ([user]) REFERENCES [umbracoUser] ([id]), -CONSTRAINT [FK_user2userGroup_userGroup] FOREIGN KEY ([userGroup]) REFERENCES [umbracoUserGroup] ([id]) -; - -*/ - -ALTER TABLE [cmsDocument] ADD -CONSTRAINT [FK_cmsDocument_umbracoNode] FOREIGN KEY ([nodeId]) REFERENCES [umbracoNode] ([id]) -; -ALTER TABLE [cmsMacroProperty] ADD -CONSTRAINT [FK_umbracoMacroProperty_umbracoMacroPropertyType] FOREIGN KEY ([macroPropertyType]) REFERENCES [cmsMacroPropertyType] ([id]) -; -ALTER TABLE [umbracoUser] ADD -CONSTRAINT [FK_user_userType] FOREIGN KEY ([userType]) REFERENCES [umbracoUserType] ([id]) -; -ALTER TABLE [umbracoNode] ADD -CONSTRAINT [FK_umbracoNode_umbracoNode] FOREIGN KEY ([parentID]) REFERENCES [umbracoNode] ([id]) -; -ALTER TABLE [cmsTemplate] ADD -CONSTRAINT [FK_cmsTemplate_umbracoNode] FOREIGN KEY ([nodeId]) REFERENCES [umbracoNode] ([id]) -; -ALTER TABLE [cmsContentType] ADD -CONSTRAINT [FK_cmsContentType_umbracoNode] FOREIGN KEY ([nodeId]) REFERENCES [umbracoNode] ([id]) -; -ALTER TABLE [cmsPropertyType] ADD -CONSTRAINT [FK_cmsPropertyType_cmsTab] FOREIGN KEY ([tabId]) REFERENCES [cmsTab] ([id]) -; -ALTER TABLE [cmsContent] ADD -CONSTRAINT [FK_cmsContent_umbracoNode] FOREIGN KEY ([nodeId]) REFERENCES [umbracoNode] ([id]) -; -ALTER TABLE [umbracoUser2app] ADD -CONSTRAINT [FK_umbracoUser2app_umbracoApp] FOREIGN KEY ([app]) REFERENCES [umbracoApp] ([appAlias]), -CONSTRAINT [FK_umbracoUser2app_umbracoUser] FOREIGN KEY ([user]) REFERENCES [umbracoUser] ([id]) -; - -ALTER TABLE [cmsTemplate] DROP CONSTRAINT [FK_cmsTemplate_umbracoNode] -; -ALTER TABLE [cmsPropertyType] DROP CONSTRAINT [FK_cmsPropertyType_cmsTab] -; -ALTER TABLE [cmsContent] DROP CONSTRAINT [FK_cmsContent_umbracoNode] -; -ALTER TABLE [cmsMacroProperty] DROP CONSTRAINT [FK_umbracoMacroProperty_umbracoMacroPropertyType] -; -ALTER TABLE [umbracoAppTree] DROP CONSTRAINT [FK_umbracoAppTree_umbracoApp] -; -ALTER TABLE [umbracoUser2app] DROP CONSTRAINT [FK_umbracoUser2app_umbracoApp] -; -ALTER TABLE [umbracoUser2app] DROP CONSTRAINT [FK_umbracoUser2app_umbracoUser] -; -ALTER TABLE [cmsPropertyData] DROP CONSTRAINT [FK_cmsPropertyData_umbracoNode] -; - -/* TABLE IS NEVER USED, REMOVED FOR 4.1 - -ALTER TABLE [umbracoUser2userGroup] DROP CONSTRAINT [FK_user2userGroup_user] -; -ALTER TABLE [umbracoUser2userGroup] DROP CONSTRAINT [FK_user2userGroup_userGroup] -; - -*/ - -ALTER TABLE [umbracoUser] DROP CONSTRAINT [FK_user_userType] -; -ALTER TABLE [cmsContentType] DROP CONSTRAINT [FK_cmsContentType_umbracoNode] -; -ALTER TABLE [cmsDocument] DROP CONSTRAINT [FK_cmsDocument_umbracoNode] -; -ALTER TABLE [umbracoNode] DROP CONSTRAINT [FK_umbracoNode_umbracoNode] -; -SET IDENTITY_INSERT [umbracoNode] ON -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-92, 0, -1, 0, 11, N'-1,-92', 37, 'f0bc4bfb-b499-40d6-ba86-058885a5178c', N'Label', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20040930 14:01:49.920') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-90, 0, -1, 0, 11, N'-1,-90', 35, '84c6b441-31df-4ffe-b67e-67d5bc3ae65a', N'Upload', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20040930 14:01:49.920') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-89, 0, -1, 0, 11, N'-1,-89', 34, 'c6bac0dd-4ab9-45b1-8e30-e4b619ee5da3', N'Textarea', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20040930 14:01:49.920') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-88, 0, -1, 0, 11, N'-1,-88', 33, '0cc0eba1-9960-42c9-bf9b-60e150b429ae', N'Textstring', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20040930 14:01:49.920') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-87, 0, -1, 0, 11, N'-1,-87', 32, 'ca90c950-0aff-4e72-b976-a30b1ac57dad', N'Richtext editor', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20040930 14:01:49.920') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-51, 0, -1, 0, 11, N'-1,-51', 4, '2e6d3631-066e-44b8-aec4-96f09099b2b5', N'Numeric', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20040930 14:01:49.920') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-49, 0, -1, 0, 11, N'-1,-49', 2, '92897bc6-a5f3-4ffe-ae27-f2e7e33dda49', N'True/false', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20040930 14:01:49.920') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-43, 0, -1, 0, 1, N'-1,-43', 2, 'fbaf13a8-4036-41f2-93a3-974f678c312a', N'Checkbox list', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20041015 14:11:04.367') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-42, 0, -1, 0, 1, N'-1,-42', 2, '0b6a45e7-44ba-430d-9da5-4e46060b9e03', N'Dropdown', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20041015 14:10:59.000') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-41, 0, -1, 0, 1, N'-1,-41', 2, '5046194e-4237-453c-a547-15db3a07c4e1', N'Date Picker', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20041015 14:10:54.303') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-40, 0, -1, 0, 1, N'-1,-40', 2, 'bb5f57c9-ce2b-4bb9-b697-4caca783a805', N'Radiobox', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20041015 14:10:49.253') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-39, 0, -1, 0, 1, N'-1,-39', 2, 'f38f0ac7-1d27-439c-9f3f-089cd8825a53', N'Dropdown multiple', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20041015 14:10:44.480') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-38, 0, -1, 0, 1, N'-1,-38', 2, 'fd9f1447-6c61-4a7c-9595-5aa39147d318', N'Folder Browser', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20041015 14:10:37.020') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-37, 0, -1, 0, 1, N'-1,-37', 2, '0225af17-b302-49cb-9176-b9f35cab9c17', N'Approved Color', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20041015 14:10:30.580') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-36, 0, -1, 0, 1, N'-1,-36', 2, 'e4d66c0f-b935-4200-81f0-025f7256b89a', N'Date Picker with time', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20041015 14:10:23.007') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-1, 0, -1, 0, 0, N'-1', 0, '916724a5-173d-4619-b97e-b9de133dd6f5', N'SYSTEM DATA: umbraco master root', 'ea7d8624-4cfe-4578-a871-24aa946bf34d', '20040930 14:01:49.920') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (1031, 0, -1, 1, 1, N'-1,1031', 2, 'f38bd2d7-65d0-48e6-95dc-87ce06ec2d3d', N'Folder', '4ea4382b-2f5a-4c2b-9587-ae9b3cf3602e', '20041201 00:13:40.743') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (1032, 0, -1, 1, 1, N'-1,1032', 2, 'cc07b313-0843-4aa8-bbda-871c8da728c8', N'Image', '4ea4382b-2f5a-4c2b-9587-ae9b3cf3602e', '20041201 00:13:43.737') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (1033, 0, -1, 1, 1, N'-1,1033', 2, '4c52d8ab-54e6-40cd-999c-7a5f24903e4d', N'File', '4ea4382b-2f5a-4c2b-9587-ae9b3cf3602e', '20041201 00:13:46.210') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (1034, 0, -1, 0, 1, N'-1,1034', 2, 'a6857c73-d6e9-480c-b6e6-f15f6ad11125', N'Content Picker', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20060103 13:07:29.203') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (1035, 0, -1, 0, 1, N'-1,1035', 2, '93929b9a-93a2-4e2a-b239-d99334440a59', N'Media Picker', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20060103 13:07:36.143') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (1036, 0, -1, 0, 1, N'-1,1036', 2, '2b24165f-9782-4aa3-b459-1de4a4d21f60', N'Member Picker', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20060103 13:07:40.260') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (1038, 0, -1, 0, 1, N'-1,1038', 2, '1251c96c-185c-4e9b-93f4-b48205573cbd', N'Simple Editor', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20060103 13:07:55.250') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (1039, 0, -1, 0, 1, N'-1,1039', 2, '06f349a9-c949-4b6a-8660-59c10451af42', N'Ultimate Picker', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20060103 13:07:55.250') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (1040, 0, -1, 0, 1, N'-1,1040', 2, '21e798da-e06e-4eda-a511-ed257f78d4fa', N'Related Links', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20060103 13:07:55.250') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (1041, 0, -1, 0, 1, N'-1,1041', 2, 'b6b73142-b9c1-4bf8-a16d-e1c23320b549', N'Tags', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20060103 13:07:55.250') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (1042, 0, -1, 0, 1, N'-1,1042', 2, '0a452bd5-83f9-4bc3-8403-1286e13fb77e', N'Macro Container', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20060103 13:07:55.250') -INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (1043, 0, -1, 0, 1, N'-1,1043', 2, '1df9f033-e6d4-451f-b8d2-e0cbc50a836f', N'Image Cropper', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20060103 13:07:55.250') - -SET IDENTITY_INSERT [umbracoNode] OFF -; -SET IDENTITY_INSERT [cmsContentType] ON -INSERT INTO [cmsContentType] ([pk], [nodeId], [alias], [icon]) VALUES (532, 1031, N'Folder', N'folder.gif') -INSERT INTO [cmsContentType] ([pk], [nodeId], [alias], [icon]) VALUES (533, 1032, N'Image', N'mediaPhoto.gif') -INSERT INTO [cmsContentType] ([pk], [nodeId], [alias], [icon]) VALUES (534, 1033, N'File', N'mediaMulti.gif') -SET IDENTITY_INSERT [cmsContentType] OFF -; -SET IDENTITY_INSERT [umbracoUser] ON -INSERT INTO [umbracoUser] ([id], [userDisabled], [userNoConsole], [userType], [startStructureID], [startMediaID], [userName], [userLogin], [userPassword], [userEmail], [userDefaultPermissions], [userLanguage]) VALUES (0, 0, 0, 1, -1, -1, N'Administrator', N'admin', N'default', N'', NULL, N'en') -SET IDENTITY_INSERT [umbracoUser] OFF -; -SET IDENTITY_INSERT [umbracoUserType] ON -INSERT INTO [umbracoUserType] ([id], [userTypeAlias], [userTypeName], [userTypeDefaultPermissions]) VALUES (1, N'admin', N'Administrators', N'CADMOSKTPIURZ:') -INSERT INTO [umbracoUserType] ([id], [userTypeAlias], [userTypeName], [userTypeDefaultPermissions]) VALUES (2, N'writer', N'Writer', N'CAH:') -INSERT INTO [umbracoUserType] ([id], [userTypeAlias], [userTypeName], [userTypeDefaultPermissions]) VALUES (3, N'editor', N'Editors', N'CADMOSKTPUZ:') -SET IDENTITY_INSERT [umbracoUserType] OFF -; -INSERT INTO [umbracoUser2app] ([user], [app]) VALUES (0, N'content') -INSERT INTO [umbracoUser2app] ([user], [app]) VALUES (0, N'developer') -INSERT INTO [umbracoUser2app] ([user], [app]) VALUES (0, N'media') -INSERT INTO [umbracoUser2app] ([user], [app]) VALUES (0, N'member') -INSERT INTO [umbracoUser2app] ([user], [app]) VALUES (0, N'settings') -INSERT INTO [umbracoUser2app] ([user], [app]) VALUES (0, N'users') - -INSERT INTO [umbracoApp] ([appAlias], [sortOrder], [appIcon], [appName], [appInitWithTreeAlias]) VALUES (N'content', 0, N'.traycontent', N'Indhold', N'content') -INSERT INTO [umbracoApp] ([appAlias], [sortOrder], [appIcon], [appName], [appInitWithTreeAlias]) VALUES (N'developer', 7, N'.traydeveloper', N'Developer', NULL) -INSERT INTO [umbracoApp] ([appAlias], [sortOrder], [appIcon], [appName], [appInitWithTreeAlias]) VALUES (N'media', 1, N'.traymedia', N'Mediearkiv', NULL) -INSERT INTO [umbracoApp] ([appAlias], [sortOrder], [appIcon], [appName], [appInitWithTreeAlias]) VALUES (N'member', 8, N'.traymember', N'Medlemmer', NULL) -INSERT INTO [umbracoApp] ([appAlias], [sortOrder], [appIcon], [appName], [appInitWithTreeAlias]) VALUES (N'settings', 6, N'.traysettings', N'Indstillinger', NULL) -INSERT INTO [umbracoApp] ([appAlias], [sortOrder], [appIcon], [appName], [appInitWithTreeAlias]) VALUES (N'users', 5, N'.trayusers', N'Brugere', NULL) - - -INSERT INTO [umbracoAppTree] ([appAlias], [treeAlias], [treeSilent], [treeInitialize], [treeSortOrder], [treeTitle], [treeIconClosed], [treeIconOpen], [treeHandlerAssembly], [treeHandlerType]) VALUES (N'content', N'content', 1, 1, 0, N'Indhold', N'.sprTreeFolder', N'.sprTreeFolder_o', N'umbraco', N'loadContent') -INSERT INTO [umbracoAppTree] ([appAlias], [treeAlias], [treeSilent], [treeInitialize], [treeSortOrder], [treeTitle], [treeIconClosed], [treeIconOpen], [treeHandlerAssembly], [treeHandlerType]) VALUES (N'developer', N'cacheBrowser', 0, 1, 0, N'CacheBrowser', N'.sprTreeFolder', N'.sprTreeFolder_o', N'umbraco', N'loadCache') -INSERT INTO [umbracoAppTree] ([appAlias], [treeAlias], [treeSilent], [treeInitialize], [treeSortOrder], [treeTitle], [treeIconClosed], [treeIconOpen], [treeHandlerAssembly], [treeHandlerType]) VALUES (N'developer', N'CacheItem', 0, 0, 0, N'Cachebrowser', N'.sprTreeFolder', N'.sprTreeFolder_o', N'umbraco', N'loadCacheItem') -INSERT INTO [umbracoAppTree] ([appAlias], [treeAlias], [treeSilent], [treeInitialize], [treeSortOrder], [treeTitle], [treeIconClosed], [treeIconOpen], [treeHandlerAssembly], [treeHandlerType]) VALUES (N'developer', N'datatype', 0, 1, 1, N'Datatyper', N'.sprTreeFolder', N'.sprTreeFolder_o', N'umbraco', N'loadDataTypes') -INSERT INTO [umbracoAppTree] ([appAlias], [treeAlias], [treeSilent], [treeInitialize], [treeSortOrder], [treeTitle], [treeIconClosed], [treeIconOpen], [treeHandlerAssembly], [treeHandlerType]) VALUES (N'developer', N'macros', 0, 1, 2, N'Macros', N'.sprTreeFolder', N'.sprTreeFolder_o', N'umbraco', N'loadMacros') -INSERT INTO [umbracoAppTree] ([appAlias], [treeAlias], [treeSilent], [treeInitialize], [treeSortOrder], [treeTitle], [treeIconClosed], [treeIconOpen], [treeHandlerAssembly], [treeHandlerType]) VALUES (N'developer', N'xslt', 0, 1, 5, N'XSLT Files', N'.sprTreeFolder', N'.sprTreeFolder_o', N'umbraco', N'loadXslt') - -INSERT INTO [umbracoAppTree] ([appAlias], [treeAlias], [treeSilent], [treeInitialize], [treeSortOrder], [treeTitle], [treeIconClosed], [treeIconOpen], [treeHandlerAssembly], [treeHandlerType]) VALUES (N'media', N'media', 0, 1, 0, N'Medier', N'.sprTreeFolder', N'.sprTreeFolder_o', N'umbraco', N'loadMedia') -INSERT INTO [umbracoAppTree] ([appAlias], [treeAlias], [treeSilent], [treeInitialize], [treeSortOrder], [treeTitle], [treeIconClosed], [treeIconOpen], [treeHandlerAssembly], [treeHandlerType]) VALUES (N'member', N'member', 0, 1, 0, N'Medlemmer', N'.sprTreeFolder', N'.sprTreeFolder_o', N'umbraco', N'loadMembers') -INSERT INTO [umbracoAppTree] ([appAlias], [treeAlias], [treeSilent], [treeInitialize], [treeSortOrder], [treeTitle], [treeIconClosed], [treeIconOpen], [treeHandlerAssembly], [treeHandlerType]) VALUES (N'member', N'memberGroups', 0, 1, 1, N'MemberGroups', N'.sprTreeFolder', N'.sprTreeFolder_o', N'umbraco', N'loadMemberGroups') -INSERT INTO [umbracoAppTree] ([appAlias], [treeAlias], [treeSilent], [treeInitialize], [treeSortOrder], [treeTitle], [treeIconClosed], [treeIconOpen], [treeHandlerAssembly], [treeHandlerType]) VALUES (N'member', N'memberTypes', 0, 1, 2, N'Medlemstyper', N'.sprTreeFolder', N'.sprTreeFolder_o', N'umbraco', N'loadMemberTypes') -INSERT INTO [umbracoAppTree] ([appAlias], [treeAlias], [treeSilent], [treeInitialize], [treeSortOrder], [treeTitle], [treeIconClosed], [treeIconOpen], [treeHandlerAssembly], [treeHandlerType], [action]) VALUES (N'settings', N'dictionary', 0, 1, 3, N'Dictionary', N'.sprTreeFolder', N'.sprTreeFolder_o', N'umbraco', N'loadDictionary', N'openDictionary()') -INSERT INTO [umbracoAppTree] ([appAlias], [treeAlias], [treeSilent], [treeInitialize], [treeSortOrder], [treeTitle], [treeIconClosed], [treeIconOpen], [treeHandlerAssembly], [treeHandlerType]) VALUES (N'settings', N'languages', 0, 1, 4, N'Languages', N'.sprTreeFolder', N'.sprTreeFolder_o', N'umbraco', N'loadLanguages') -INSERT INTO [umbracoAppTree] ([appAlias], [treeAlias], [treeSilent], [treeInitialize], [treeSortOrder], [treeTitle], [treeIconClosed], [treeIconOpen], [treeHandlerAssembly], [treeHandlerType]) VALUES (N'settings', N'mediaTypes', 0, 1, 5, N'Medietyper', N'.sprTreeFolder', N'.sprTreeFolder_o', N'umbraco', N'loadMediaTypes') -INSERT INTO [umbracoAppTree] ([appAlias], [treeAlias], [treeSilent], [treeInitialize], [treeSortOrder], [treeTitle], [treeIconClosed], [treeIconOpen], [treeHandlerAssembly], [treeHandlerType]) VALUES (N'settings', N'documentTypes', 0, 1, 6, N'Dokumenttyper', N'.sprTreeFolder', N'.sprTreeFolder_o', N'umbraco', N'loadNodeTypes') -INSERT INTO [umbracoAppTree] ([appAlias], [treeAlias], [treeSilent], [treeInitialize], [treeSortOrder], [treeTitle], [treeIconClosed], [treeIconOpen], [treeHandlerAssembly], [treeHandlerType]) VALUES (N'settings', N'stylesheetProperty', 0, 0, 0, N'Stylesheet Property', N'', N'', N'umbraco', N'loadStylesheetProperty') -INSERT INTO [umbracoAppTree] ([appAlias], [treeAlias], [treeSilent], [treeInitialize], [treeSortOrder], [treeTitle], [treeIconClosed], [treeIconOpen], [treeHandlerAssembly], [treeHandlerType]) VALUES (N'settings', N'stylesheets', 0, 1, 0, N'Stylesheets', N'.sprTreeFolder', N'.sprTreeFolder_o', N'umbraco', N'loadStylesheets') -INSERT INTO [umbracoAppTree] ([appAlias], [treeAlias], [treeSilent], [treeInitialize], [treeSortOrder], [treeTitle], [treeIconClosed], [treeIconOpen], [treeHandlerAssembly], [treeHandlerType]) VALUES (N'settings', N'templates', 0, 1, 1, N'Templates', N'.sprTreeFolder', N'.sprTreeFolder_o', N'umbraco', N'loadTemplates') - -INSERT INTO [umbracoAppTree] ([appAlias], [treeAlias], [treeSilent], [treeInitialize], [treeSortOrder], [treeTitle], [treeIconClosed], [treeIconOpen], [treeHandlerAssembly], [treeHandlerType]) VALUES (N'users', N'users', 0, 1, 0, N'Brugere', N'.sprTreeFolder', N'.sprTreeFolder_o', N'umbraco', N'loadUsers') - -SET IDENTITY_INSERT [cmsMacroPropertyType] ON -INSERT INTO [cmsMacroPropertyType] ([id], [macroPropertyTypeAlias], [macroPropertyTypeRenderAssembly], [macroPropertyTypeRenderType], [macroPropertyTypeBaseType]) VALUES (3, N'mediaCurrent', N'umbraco.macroRenderings', N'media', N'Int32') -INSERT INTO [cmsMacroPropertyType] ([id], [macroPropertyTypeAlias], [macroPropertyTypeRenderAssembly], [macroPropertyTypeRenderType], [macroPropertyTypeBaseType]) VALUES (4, N'contentSubs', N'umbraco.macroRenderings', N'content', N'Int32') -INSERT INTO [cmsMacroPropertyType] ([id], [macroPropertyTypeAlias], [macroPropertyTypeRenderAssembly], [macroPropertyTypeRenderType], [macroPropertyTypeBaseType]) VALUES (5, N'contentRandom', N'umbraco.macroRenderings', N'content', N'Int32') -INSERT INTO [cmsMacroPropertyType] ([id], [macroPropertyTypeAlias], [macroPropertyTypeRenderAssembly], [macroPropertyTypeRenderType], [macroPropertyTypeBaseType]) VALUES (6, N'contentPicker', N'umbraco.macroRenderings', N'content', N'Int32') -INSERT INTO [cmsMacroPropertyType] ([id], [macroPropertyTypeAlias], [macroPropertyTypeRenderAssembly], [macroPropertyTypeRenderType], [macroPropertyTypeBaseType]) VALUES (13, N'number', N'umbraco.macroRenderings', N'numeric', N'Int32') -INSERT INTO [cmsMacroPropertyType] ([id], [macroPropertyTypeAlias], [macroPropertyTypeRenderAssembly], [macroPropertyTypeRenderType], [macroPropertyTypeBaseType]) VALUES (14, N'bool', N'umbraco.macroRenderings', N'yesNo', N'Boolean') -INSERT INTO [cmsMacroPropertyType] ([id], [macroPropertyTypeAlias], [macroPropertyTypeRenderAssembly], [macroPropertyTypeRenderType], [macroPropertyTypeBaseType]) VALUES (16, N'text', N'umbraco.macroRenderings', N'text', N'String') -INSERT INTO [cmsMacroPropertyType] ([id], [macroPropertyTypeAlias], [macroPropertyTypeRenderAssembly], [macroPropertyTypeRenderType], [macroPropertyTypeBaseType]) VALUES (17, N'contentTree', N'umbraco.macroRenderings', N'content', N'Int32') -INSERT INTO [cmsMacroPropertyType] ([id], [macroPropertyTypeAlias], [macroPropertyTypeRenderAssembly], [macroPropertyTypeRenderType], [macroPropertyTypeBaseType]) VALUES (18, N'contentType', N'umbraco.macroRenderings', N'contentTypeSingle', N'Int32') -INSERT INTO [cmsMacroPropertyType] ([id], [macroPropertyTypeAlias], [macroPropertyTypeRenderAssembly], [macroPropertyTypeRenderType], [macroPropertyTypeBaseType]) VALUES (19, N'contentTypeMultiple', N'umbraco.macroRenderings', N'contentTypeMultiple', N'Int32') -INSERT INTO [cmsMacroPropertyType] ([id], [macroPropertyTypeAlias], [macroPropertyTypeRenderAssembly], [macroPropertyTypeRenderType], [macroPropertyTypeBaseType]) VALUES (20, N'contentAll', N'umbraco.macroRenderings', N'content', N'Int32') -INSERT INTO [cmsMacroPropertyType] ([id], [macroPropertyTypeAlias], [macroPropertyTypeRenderAssembly], [macroPropertyTypeRenderType], [macroPropertyTypeBaseType]) VALUES (21, N'tabPicker', N'umbraco.macroRenderings', N'tabPicker', N'String') -INSERT INTO [cmsMacroPropertyType] ([id], [macroPropertyTypeAlias], [macroPropertyTypeRenderAssembly], [macroPropertyTypeRenderType], [macroPropertyTypeBaseType]) VALUES (22, N'tabPickerMultiple', N'umbraco.macroRenderings', N'tabPickerMultiple', N'String') -INSERT INTO [cmsMacroPropertyType] ([id], [macroPropertyTypeAlias], [macroPropertyTypeRenderAssembly], [macroPropertyTypeRenderType], [macroPropertyTypeBaseType]) VALUES (23, N'propertyTypePicker', N'umbraco.macroRenderings', N'propertyTypePicker', N'String') -INSERT INTO [cmsMacroPropertyType] ([id], [macroPropertyTypeAlias], [macroPropertyTypeRenderAssembly], [macroPropertyTypeRenderType], [macroPropertyTypeBaseType]) VALUES (24, N'propertyTypePickerMultiple', N'umbraco.macroRenderings', N'propertyTypePickerMultiple', N'String') -INSERT INTO [cmsMacroPropertyType] ([id], [macroPropertyTypeAlias], [macroPropertyTypeRenderAssembly], [macroPropertyTypeRenderType], [macroPropertyTypeBaseType]) VALUES (25, N'textMultiLine', N'umbraco.macroRenderings', N'textMultiple', N'String') -SET IDENTITY_INSERT [cmsMacroPropertyType] OFF -; -SET IDENTITY_INSERT [cmsTab] ON -INSERT INTO [cmsTab] ([id], [contenttypeNodeId], [text], [sortorder]) VALUES (3, 1032, N'Image', 1) -INSERT INTO [cmsTab] ([id], [contenttypeNodeId], [text], [sortorder]) VALUES (4, 1033, N'File', 1) -INSERT INTO [cmsTab] ([id], [contenttypeNodeId], [text], [sortorder]) VALUES (5, 1031, N'Contents', 1) -SET IDENTITY_INSERT [cmsTab] OFF -; -SET IDENTITY_INSERT [cmsPropertyType] ON -INSERT INTO [cmsPropertyType] ([id], [dataTypeId], [contentTypeId], [tabId], [Alias], [Name], [helpText], [sortOrder], [mandatory], [validationRegExp], [Description]) VALUES (6, -90, 1032, 3, N'umbracoFile', N'Upload image', NULL, 0, 0, NULL, NULL) -INSERT INTO [cmsPropertyType] ([id], [dataTypeId], [contentTypeId], [tabId], [Alias], [Name], [helpText], [sortOrder], [mandatory], [validationRegExp], [Description]) VALUES (7, -92, 1032, 3, N'umbracoWidth', N'Width', NULL, 0, 0, NULL, NULL) -INSERT INTO [cmsPropertyType] ([id], [dataTypeId], [contentTypeId], [tabId], [Alias], [Name], [helpText], [sortOrder], [mandatory], [validationRegExp], [Description]) VALUES (8, -92, 1032, 3, N'umbracoHeight', N'Height', NULL, 0, 0, NULL, NULL) -INSERT INTO [cmsPropertyType] ([id], [dataTypeId], [contentTypeId], [tabId], [Alias], [Name], [helpText], [sortOrder], [mandatory], [validationRegExp], [Description]) VALUES (9, -92, 1032, 3, N'umbracoBytes', N'Size', NULL, 0, 0, NULL, NULL) -INSERT INTO [cmsPropertyType] ([id], [dataTypeId], [contentTypeId], [tabId], [Alias], [Name], [helpText], [sortOrder], [mandatory], [validationRegExp], [Description]) VALUES (10, -92, 1032, 3, N'umbracoExtension', N'Type', NULL, 0, 0, NULL, NULL) -INSERT INTO [cmsPropertyType] ([id], [dataTypeId], [contentTypeId], [tabId], [Alias], [Name], [helpText], [sortOrder], [mandatory], [validationRegExp], [Description]) VALUES (24, -90, 1033, 4, N'umbracoFile', N'Upload file', NULL, 0, 0, NULL, NULL) -INSERT INTO [cmsPropertyType] ([id], [dataTypeId], [contentTypeId], [tabId], [Alias], [Name], [helpText], [sortOrder], [mandatory], [validationRegExp], [Description]) VALUES (25, -92, 1033, 4, N'umbracoExtension', N'Type', NULL, 0, 0, NULL, NULL) -INSERT INTO [cmsPropertyType] ([id], [dataTypeId], [contentTypeId], [tabId], [Alias], [Name], [helpText], [sortOrder], [mandatory], [validationRegExp], [Description]) VALUES (26, -92, 1033, 4, N'umbracoBytes', N'Size', NULL, 0, 0, NULL, NULL) -INSERT INTO [cmsPropertyType] ([id], [dataTypeId], [contentTypeId], [tabId], [Alias], [Name], [helpText], [sortOrder], [mandatory], [validationRegExp], [Description]) VALUES (27, -38, 1031, 5, N'contents', N'Contents:', NULL, 0, 0, NULL, NULL) -SET IDENTITY_INSERT [cmsPropertyType] OFF -; -SET IDENTITY_INSERT [umbracoLanguage] ON -INSERT INTO [umbracoLanguage] ([id], [languageISOCode], [languageCultureName]) VALUES (1, N'en-US', N'en-US') -SET IDENTITY_INSERT [umbracoLanguage] OFF -; -INSERT INTO [cmsContentTypeAllowedContentType] ([Id], [AllowedId]) VALUES (1031, 1031) -INSERT INTO [cmsContentTypeAllowedContentType] ([Id], [AllowedId]) VALUES (1031, 1032) -INSERT INTO [cmsContentTypeAllowedContentType] ([Id], [AllowedId]) VALUES (1031, 1033) -SET IDENTITY_INSERT [cmsDataType] ON -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (4, -49, '38b352c1-e9f8-4fd8-9324-9a2eab06d97a', 'Integer') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (6, -51, '1413afcb-d19a-4173-8e9a-68288d2a73b8', 'Integer') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (8, -87, '5E9B75AE-FACE-41c8-B47E-5F4B0FD82F83', 'Ntext') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (9, -88, 'ec15c1e5-9d90-422a-aa52-4f7622c63bea', 'Nvarchar') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (10, -89, '67db8357-ef57-493e-91ac-936d305e0f2a', 'Ntext') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (11, -90, '5032a6e6-69e3-491d-bb28-cd31cd11086c', 'Nvarchar') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (12, -91, 'a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6', 'Nvarchar') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (13, -92, '6c738306-4c17-4d88-b9bd-6546f3771597', 'Nvarchar') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (14, -36, 'b6fb1622-afa5-4bbf-a3cc-d9672a442222', 'Date') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (15, -37, 'f8d60f68-ec59-4974-b43b-c46eb5677985', 'Nvarchar') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (16, -38, 'cccd4ae9-f399-4ed2-8038-2e88d19e810c', 'Nvarchar') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (17, -39, '928639ed-9c73-4028-920c-1e55dbb68783', 'Nvarchar') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (18, -40, 'a52c7c1c-c330-476e-8605-d63d3b84b6a6', 'Nvarchar') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (19, -41, '23e93522-3200-44e2-9f29-e61a6fcbb79a', 'Date') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (20, -42, 'a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6', 'Integer') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (21, -43, 'b4471851-82b6-4c75-afa4-39fa9c6a75e9', 'Nvarchar') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (22, -44, 'a3776494-0574-4d93-b7de-efdfdec6f2d1', 'Ntext') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (23, -128, 'a52c7c1c-c330-476e-8605-d63d3b84b6a6', 'Nvarchar') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (24, -129, '928639ed-9c73-4028-920c-1e55dbb68783', 'Nvarchar') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (25, -130, 'a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6', 'Nvarchar') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (26, -131, 'a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6', 'Nvarchar') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (27, -132, 'a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6', 'Nvarchar') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (28, -133, '6c738306-4c17-4d88-b9bd-6546f3771597', 'Ntext') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (29, -134, '928639ed-9c73-4028-920c-1e55dbb68783', 'Nvarchar') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (30, -50, 'aaf99bb2-dbbe-444d-a296-185076bf0484', 'Date') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (31, 1034, '158aa029-24ed-4948-939e-c3da209e5fba', 'Integer') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (32, 1035, 'ead69342-f06d-4253-83ac-28000225583b', 'Integer') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (33, 1036, '39f533e4-0551-4505-a64b-e0425c5ce775', 'Integer') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (35, 1038, '60b7dabf-99cd-41eb-b8e9-4d2e669bbde9', 'Ntext') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (36, 1039, 'cdbf0b5d-5cb2-445f-bc12-fcaaec07cf2c', 'Ntext') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (37, 1040, '71b8ad1a-8dc2-425c-b6b8-faa158075e63', 'Ntext') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (38, 1041, '4023e540-92f5-11dd-ad8b-0800200c9a66', 'Ntext') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (39, 1042, '474FCFF8-9D2D-11DE-ABC6-AD7A56D89593', 'Ntext') -INSERT INTO [cmsDataType] ([pk], [nodeId], [controlId], [dbType]) VALUES (40, 1043, '7A2D436C-34C2-410F-898F-4A23B3D79F54', 'Ntext') - -SET IDENTITY_INSERT [cmsDataType] OFF -; -ALTER TABLE [cmsTemplate] ADD CONSTRAINT [FK_cmsTemplate_umbracoNode] FOREIGN KEY ([nodeId]) REFERENCES [umbracoNode] ([id]) -ALTER TABLE [cmsPropertyType] ADD CONSTRAINT [FK_cmsPropertyType_cmsTab] FOREIGN KEY ([tabId]) REFERENCES [cmsTab] ([id]) -ALTER TABLE [cmsContent] ADD CONSTRAINT [FK_cmsContent_umbracoNode] FOREIGN KEY ([nodeId]) REFERENCES [umbracoNode] ([id]) -ALTER TABLE [cmsMacroProperty] ADD CONSTRAINT [FK_umbracoMacroProperty_umbracoMacroPropertyType] FOREIGN KEY ([macroPropertyType]) REFERENCES [cmsMacroPropertyType] ([id]) -ALTER TABLE [umbracoAppTree] ADD CONSTRAINT [FK_umbracoAppTree_umbracoApp] FOREIGN KEY ([appAlias]) REFERENCES [umbracoApp] ([appAlias]) -ALTER TABLE [umbracoUser2app] ADD CONSTRAINT [FK_umbracoUser2app_umbracoApp] FOREIGN KEY ([app]) REFERENCES [umbracoApp] ([appAlias]) -ALTER TABLE [umbracoUser2app] ADD CONSTRAINT [FK_umbracoUser2app_umbracoUser] FOREIGN KEY ([user]) REFERENCES [umbracoUser] ([id]) -ALTER TABLE [cmsPropertyData] ADD CONSTRAINT [FK_cmsPropertyData_umbracoNode] FOREIGN KEY ([contentNodeId]) REFERENCES [umbracoNode] ([id]) - -/* TABLE IS NEVER USED, REMOVED FOR 4.1 - -ALTER TABLE [umbracoUser2userGroup] ADD CONSTRAINT [FK_user2userGroup_user] FOREIGN KEY ([user]) REFERENCES [umbracoUser] ([id]) -ALTER TABLE [umbracoUser2userGroup] ADD CONSTRAINT [FK_user2userGroup_userGroup] FOREIGN KEY ([userGroup]) REFERENCES [umbracoUserGroup] ([id]) - -*/ - -ALTER TABLE [umbracoUser] ADD CONSTRAINT [FK_user_userType] FOREIGN KEY ([userType]) REFERENCES [umbracoUserType] ([id]) -ALTER TABLE [cmsContentType] ADD CONSTRAINT [FK_cmsContentType_umbracoNode] FOREIGN KEY ([nodeId]) REFERENCES [umbracoNode] ([id]) -ALTER TABLE [cmsDocument] ADD CONSTRAINT [FK_cmsDocument_umbracoNode] FOREIGN KEY ([nodeId]) REFERENCES [umbracoNode] ([id]) -ALTER TABLE [umbracoNode] ADD CONSTRAINT [FK_umbracoNode_umbracoNode] FOREIGN KEY ([parentID]) REFERENCES [umbracoNode] ([id]) -; -set identity_insert umbracoNode on -insert into umbracoNode -(id, trashed, parentID, nodeUser, level, path, sortOrder, uniqueID, text, nodeObjectType) -values -(-20, 0, -1, 0, 0, '-1,-20', 0, '0F582A79-1E41-4CF0-BFA0-76340651891A', 'Recycle Bin', '01BB7FF2-24DC-4C0C-95A2-C24EF72BBAC8') -set identity_insert umbracoNode off -; -ALTER TABLE cmsDataTypePreValues ALTER COLUMN value NVARCHAR(2500) NULL -; -CREATE TABLE [cmsTask] -( -[closed] [bit] NOT NULL CONSTRAINT [DF__cmsTask__closed__04E4BC85] DEFAULT ((0)), -[id] [int] NOT NULL IDENTITY(1, 1), -[taskTypeId] [tinyint] NOT NULL, -[nodeId] [int] NOT NULL, -[parentUserId] [int] NOT NULL, -[userId] [int] NOT NULL, -[DateTime] [datetime] NOT NULL CONSTRAINT [DF__cmsTask__DateTim__05D8E0BE] DEFAULT (getdate()), -[Comment] [nvarchar] (500) NULL -) -; -ALTER TABLE [cmsTask] ADD CONSTRAINT [PK_cmsTask] PRIMARY KEY CLUSTERED ([id]) -; -CREATE TABLE [cmsTaskType] -( -[id] [tinyint] NOT NULL IDENTITY(1, 1), -[alias] [nvarchar] (255) NOT NULL -) -; -ALTER TABLE [cmsTaskType] ADD CONSTRAINT [PK_cmsTaskType] PRIMARY KEY CLUSTERED ([id]) -; -ALTER TABLE [cmsTask] ADD -CONSTRAINT [FK_cmsTask_cmsTaskType] FOREIGN KEY ([taskTypeId]) REFERENCES [cmsTaskType] ([id]) -; -insert into cmsTaskType (alias) values ('toTranslate') -; -/* Add send to translate actions to admins and editors */ -update umbracoUserType set userTypeDefaultPermissions = userTypeDefaultPermissions + '5' where userTypeAlias in ('editor','admin') -; -/* Add translator usertype */ -if not exists(select id from umbracoUserType where userTypeAlias = 'translator') -insert into umbracoUserType (userTypeAlias, userTypeName, userTypeDefaultPermissions) values ('translator', 'Translator', 'A') -; -insert into umbracoRelationType (dual, parentObjectType, childObjectType, name, alias) values (1, 'c66ba18e-eaf3-4cff-8a22-41b16d66a972', 'c66ba18e-eaf3-4cff-8a22-41b16d66a972', 'Relate Document On Copy','relateDocumentOnCopy') -; -ALTER TABLE cmsMacro ADD macroPython nvarchar(255) -; - -INSERT INTO [umbracoAppTree]([treeSilent], [treeInitialize], [treeSortOrder], [appAlias], [treeAlias], [treeTitle], [treeIconClosed], [treeIconOpen], [treeHandlerAssembly], [treeHandlerType]) VALUES(0, 1, 4, 'developer', 'python', 'Python Files', 'folder.gif', 'folder_o.gif', 'umbraco', 'loadPython') -; -INSERT INTO [umbracoAppTree]([treeSilent], [treeInitialize], [treeSortOrder], [appAlias], [treeAlias], [treeTitle], [treeIconClosed], [treeIconOpen], [treeHandlerAssembly], [treeHandlerType]) VALUES(0, 1, 2, 'settings', 'scripts', 'Scripts', 'folder.gif', 'folder_o.gif', 'umbraco', 'loadScripts') -; -alter TABLE [cmsContentType] -add [thumbnail] nvarchar(255) NOT NULL CONSTRAINT -[DF_cmsContentType_thumbnail] DEFAULT ('folder.png') -; -alter TABLE [cmsContentType] -add [description] nvarchar(1500) NULL -; -ALTER TABLE umbracoLog ALTER COLUMN logComment NVARCHAR(4000) NULL -; -SET IDENTITY_INSERT [cmsDataTypePreValues] ON -insert into cmsDataTypePreValues (id, dataTypeNodeId, [value], sortorder, alias) -values (3,-87,',code,undo,redo,cut,copy,mcepasteword,stylepicker,bold,italic,bullist,numlist,outdent,indent,mcelink,unlink,mceinsertanchor,mceimage,umbracomacro,mceinserttable,mcecharmap,' + char(124) + '1' + char(124) + '1,2,3,' + char(124) + '0' + char(124) + '500,400' + char(124) + '1049,' + char(124) + '', 0, '') - -insert into cmsDataTypePreValues (id, dataTypeNodeId, [value], sortorder, alias) -values (4,1041,'default', 0, 'group') - -SET IDENTITY_INSERT [cmsDataTypePreValues] OFF -; -/* 3.1 SQL changes */ - -INSERT INTO [umbracoAppTree] ([appAlias], [treeAlias], [treeSilent], [treeInitialize], [treeSortOrder], [treeTitle], [treeIconClosed], [treeIconOpen], [treeHandlerAssembly], [treeHandlerType]) VALUES (N'developer', N'packagerPackages', 0, 0, 1, N'Packager Packages', N'folder.gif', N'folder_o.gif', N'umbraco', N'loadPackages'); - - -/* Add ActionBrowse as a default permission to all user types that have ActionUpdate */ -UPDATE umbracoUserType SET userTypeDefaultPermissions = userTypeDefaultPermissions + 'F' WHERE CHARINDEX('A',userTypeDefaultPermissions,0) >= 1 -AND CHARINDEX('F',userTypeDefaultPermissions,0) < 1 -; -/* Add ActionToPublish to all users types that have the alias 'writer' */ -UPDATE umbracoUserType SET userTypeDefaultPermissions = userTypeDefaultPermissions + 'H' WHERE userTypeAlias = 'writer' -AND CHARINDEX('F',userTypeDefaultPermissions,0) < 1 -; -/* Add ActionBrowse to all user permissions for nodes that have the ActionUpdate permission */ -IF NOT EXISTS (SELECT permission FROM umbracoUser2NodePermission WHERE permission='F') -INSERT INTO umbracoUser2NodePermission (userID, nodeId, permission) -SELECT userID, nodeId, 'F' FROM umbracoUser2NodePermission WHERE permission='A' -; -/* Add ActionToPublish permissions to all nodes for users that are of type 'writer' */ -IF NOT EXISTS (SELECT permission FROM umbracoUser2NodePermission WHERE permission='H') -INSERT INTO umbracoUser2NodePermission (userID, nodeId, permission) -SELECT DISTINCT userID, nodeId, 'H' FROM umbracoUser2NodePermission WHERE userId IN -(SELECT umbracoUser.id FROM umbracoUserType INNER JOIN umbracoUser ON umbracoUserType.id = umbracoUser.userType WHERE (umbracoUserType.userTypeAlias = 'writer')) -; -/* Add the contentRecycleBin tree type */ -IF NOT EXISTS (SELECT treeAlias FROM umbracoAppTree WHERE treeAlias='contentRecycleBin') -INSERT INTO umbracoAppTree (treeSilent, treeInitialize, treeSortOrder, appAlias, treeAlias, treeTitle, treeIconClosed, treeIconOpen, treeHandlerAssembly, treeHandlerType) -VALUES (0, 0, 0, 'content', 'contentRecycleBin', 'RecycleBin', 'folder.gif', 'folder_o.gif', 'umbraco', 'cms.presentation.Trees.ContentRecycleBin') -; -/* Add the UserType tree type */ -IF NOT EXISTS (SELECT treeAlias FROM umbracoAppTree WHERE treeAlias='userTypes') -INSERT INTO umbracoAppTree (treeSilent, treeInitialize, treeSortOrder, appAlias, treeAlias, treeTitle, treeIconClosed, treeIconOpen, treeHandlerAssembly, treeHandlerType) -VALUES (0, 1, 1, 'users', 'userTypes', 'User Types', 'folder.gif', 'folder_o.gif', 'umbraco', 'cms.presentation.Trees.UserTypes') -; -/* Add the User Permission tree type */ -IF NOT EXISTS (SELECT treeAlias FROM umbracoAppTree WHERE treeAlias='userPermissions') -INSERT INTO umbracoAppTree (treeSilent, treeInitialize, treeSortOrder, appAlias, treeAlias, treeTitle, treeIconClosed, treeIconOpen, treeHandlerAssembly, treeHandlerType) -VALUES (0, 1, 2, 'users', 'userPermissions', 'User Permissions', 'folder.gif', 'folder_o.gif', 'umbraco', 'cms.presentation.Trees.UserPermissions'); - - -/* TRANSLATION RELATED SQL */ -INSERT INTO [umbracoApp] ([appAlias], [sortOrder], [appIcon], [appName], [appInitWithTreeAlias]) VALUES (N'translation', 5, N'.traytranslation', N'Translation', NULL) -INSERT INTO umbracoAppTree (treeSilent, treeInitialize, treeSortOrder, appAlias, treeAlias, treeTitle, treeIconClosed, treeIconOpen, treeHandlerAssembly, treeHandlerType) -VALUES (0, 1, 1, 'translation','openTasks', 'Tasks assigned to you', '.sprTreeFolder', '.sprTreeFolder_o', 'umbraco', 'loadOpenTasks'); -INSERT INTO umbracoAppTree (treeSilent, treeInitialize, treeSortOrder, appAlias, treeAlias, treeTitle, treeIconClosed, treeIconOpen, treeHandlerAssembly, treeHandlerType) -VALUES (0, 1, 2, 'translation','yourTasks', 'Tasks created by you', '.sprTreeFolder', '.sprTreeFolder_o', 'umbraco', 'loadYourTasks'); - - -alter TABLE [cmsContentType] -add [masterContentType] int NULL CONSTRAINT -[DF_cmsContentType_masterContentType] DEFAULT (0) -; - -CREATE TABLE [cmsTagRelationship]( - [nodeId] [int] NOT NULL, - [tagId] [int] NOT NULL, - CONSTRAINT [PK_cmsTagRelationship] PRIMARY KEY CLUSTERED -( - [nodeId] ASC, - [tagId] ASC -) -) ON [PRIMARY] -; - -CREATE TABLE [cmsTags]( - [id] [int] IDENTITY(1,1) NOT NULL, - [tag] [varchar](200) NULL, - [parentId] [int] NULL, - [group] [varchar](100) NULL, - CONSTRAINT [PK_cmsTags] PRIMARY KEY CLUSTERED -( - [id] ASC -) -) ON [PRIMARY] -; - -ALTER TABLE [cmsTagRelationship] WITH CHECK ADD CONSTRAINT [umbracoNode_cmsTagRelationship] FOREIGN KEY([nodeId]) -REFERENCES [umbracoNode] ([id]) -ON DELETE CASCADE -; - -ALTER TABLE [cmsTagRelationship] CHECK CONSTRAINT [umbracoNode_cmsTagRelationship] -; - -ALTER TABLE [cmsTagRelationship] WITH CHECK ADD CONSTRAINT [cmsTags_cmsTagRelationship] FOREIGN KEY([tagId]) -REFERENCES [cmsTags] ([id]) -ON DELETE CASCADE -; - -ALTER TABLE [cmsTagRelationship] CHECK CONSTRAINT [cmsTags_cmsTagRelationship] -; -alter TABLE [umbracoUser] -add [defaultToLiveEditing] bit NOT NULL CONSTRAINT -[DF_umbracoUser_defaultToLiveEditing] DEFAULT (0) -; - -/* INSERT NEW MEDIA RECYCLE BIN NODE */ -SET IDENTITY_INSERT [umbracoNode] ON -INSERT INTO umbracoNode (id, trashed, parentID, nodeUser, level, path, sortOrder, uniqueID, text, nodeObjectType) -VALUES (-21, 0, -1, 0, 0, '-1,-21', 0, 'BF7C7CBC-952F-4518-97A2-69E9C7B33842', 'Recycle Bin', 'CF3D8E34-1C1C-41e9-AE56-878B57B32113') -SET IDENTITY_INSERT [umbracoNode] OFF -; -/* Add the mediaRecycleBin tree type */ -IF NOT EXISTS (SELECT treeAlias FROM umbracoAppTree WHERE treeAlias='mediaRecycleBin') -INSERT INTO umbracoAppTree (treeSilent, treeInitialize, treeSortOrder, appAlias, treeAlias, treeTitle, treeIconClosed, treeIconOpen, treeHandlerAssembly, treeHandlerType) -VALUES (0, 0, 0, 'media', 'mediaRecycleBin', 'RecycleBin', 'folder.gif', 'folder_o.gif', 'umbraco', 'cms.presentation.Trees.MediaRecycleBin') -; - -/* PREVIEW */ -CREATE TABLE [cmsPreviewXml]( - [nodeId] [int] NOT NULL, - [versionId] [uniqueidentifier] NOT NULL, - [timestamp] [datetime] NOT NULL, - [xml] [ntext] NOT NULL, - CONSTRAINT [PK_cmsContentPreviewXml] PRIMARY KEY CLUSTERED -( - [nodeId] ASC, - [versionId] ASC -) WITH ( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF) -) -; - - - - -/*********************************************************************************************************************** - -ADD NEW PRIMARY KEYS, FOREIGN KEYS AND INDEXES FOR VERSION 4.1 - -IMPORTANT!!!!! -YOU MUST MAKE SURE THAT THE SCRIPT BELOW THIS MATCHES THE KeysIndexesAndConstraints.sql FILE FOR THE MANUAL UPGRADE - -*/ - -/************************** CLEANUP ***********************************************/ - -/* DELETE NON-EXISTING DOCUMENTS */ -delete from cmsDocument where nodeId not in (select id from umbracoNode) -; - -/* CLEAN UNUSED CONTENT ROWS */ -delete from cmsContent where nodeId not in (select id from umbracoNode) -; - -/* CLEAN UNUSED VERSIONS */ -delete from cmsContentVersion where contentid not in (select nodeId from cmsContent) -; - -/* CLEAN UNUSED XML */ -delete from cmsContentXml where nodeid not in (select nodeId from cmsContent) -; - -/* CLEAN UNUSED DOCUMENT TYPES */ -delete from cmsDocumentType where contentTypeNodeId not in (select nodeId from cmsContentType) -; -delete from cmsDocumentType where templateNodeId not in (select nodeid from cmsTemplate) -; - -/* UPDATE EMPTY TEMPLATE REFERENCES IN DOCUMENTS */ -update cmsDocument set templateId = NULL where templateId not in (select nodeId from cmsTemplate) -; - -/* DELETE ALL NOTIFICATIONS THAT NO LONGER HAVE NODES */ -delete from umbracoUser2NodeNotify where nodeId not in (select id from umbracoNode) -; - -/* DELETE ALL NOTIFICATIONS THAT NO LONGER HAVE USERS */ -delete from umbracoUser2NodeNotify where userId not in (select id from umbracoUser) -; - -/* DELETE UMBRACO NODE DATA THAT IS FLAGGED AS A DOCUMENT OBJECT TYPE THAT DOESN'T EXIST IN THE CONTENT TABLE ANY LONGER */ -delete from umbracoNode where id not in -(select nodeId from cmsContent) and nodeObjectType = 'c66ba18e-eaf3-4cff-8a22-41b16d66a972' -; - -/* DELETE PERMISSIONS THAT RELATED TO NON-EXISTING USERS */ -delete from umbracoUser2NodePermission where userId not in (select id from umbracoUser) -; - -/* DELETE PERMISSIONS THAT RELATED TO NON-EXISTING NODES */ -delete from umbracoUser2NodePermission where nodeId not in (select id from umbracoNode) -; - -/* SET MASTER TEMPLATE TO NULL WHEN THERE ISN'T ONE SPECIFIED */ -update cmsTemplate set [master] = NULL where [master] = 0 - -/* -We need to remove any data type that doesn't exist in umbracoNode as these shouldn't actually exist -I think they must be left over from how Umbraco used to show the types of data types registered instead -of using reflection. Here are the data types in the cmsDataType table that are not in umbracoNode: - -12 -91 A74EA9C9-8E18-4D2A-8CF6-73C6206C5DA6 Nvarchar -22 -44 A3776494-0574-4D93-B7DE-EFDFDEC6F2D1 Ntext -23 -128 A52C7C1C-C330-476E-8605-D63D3B84B6A6 Nvarchar -24 -129 928639ED-9C73-4028-920C-1E55DBB68783 Nvarchar -25 -130 A74EA9C9-8E18-4D2A-8CF6-73C6206C5DA6 Nvarchar -26 -131 A74EA9C9-8E18-4D2A-8CF6-73C6206C5DA6 Nvarchar -27 -132 A74EA9C9-8E18-4D2A-8CF6-73C6206C5DA6 Nvarchar -28 -133 6C738306-4C17-4D88-B9BD-6546F3771597 Ntext -29 -134 928639ED-9C73-4028-920C-1E55DBB68783 Nvarchar -30 -50 AAF99BB2-DBBE-444D-A296-185076BF0484 Date -39 1042 5E9B75AE-FACE-41C8-B47E-5F4B0FD82F83 Ntext -40 1043 5E9B75AE-FACE-41C8-B47E-5F4B0FD82F83 Ntext -41 1044 A74EA9C9-8E18-4D2A-8CF6-73C6206C5DA6 Ntext -42 1045 A74EA9C9-8E18-4D2A-8CF6-73C6206C5DA6 Ntext -47 1194 D15E1281-E456-4B24-AA86-1DDA3E4299D5 Ntext - -*/ -DELETE FROM cmsDataType WHERE nodeId NOT IN (SELECT id FROM umbracoNode) -; - -/* Need to remove any data type prevalues that aren't related to a data type */ -DELETE FROM cmsDataTypePreValues WHERE dataTypeNodeID NOT IN (SELECT nodeId FROM cmsDataType) -; - -/* Remove any domains that should not exist as they weren't deleted before when documents were deleted */ -DELETE FROM umbracoDomains WHERE domainRootStructureId NOT IN (SELECT id FROM umbracoNode) -; - --- It would be good to add constraints from cmsLanguageText to umbracoLanguage but unfortunately, a 'zero' id --- is entered into cmsLanguageText when a new entry is made, since there's not language with id of zero this won't work. --- However, we need to remove translations that aren't related to a language (these would be left over from deleting a language) -DELETE FROM cmsLanguageText -WHERE languageId <> 0 AND languageId NOT IN (SELECT id FROM umbracoLanguage) -; - -/* need to remove any content restrictions that don't exist in cmsContent */ - -DELETE FROM cmsContentTypeAllowedContentType WHERE id NOT IN (SELECT nodeId FROM cmsContentType) -; -DELETE FROM cmsContentTypeAllowedContentType WHERE Allowedid NOT IN (SELECT nodeId FROM cmsContentType) -; - -/* Though this should not have to be run because it's a new install, you need to clean the previews if you've been testing before the RC */ -DELETE FROM cmsPreviewXml WHERE VersionID NOT IN (SELECT VersionId FROM cmsContentVersion) -; - -/* Though this should not have to run because it's a new install, you need to remove this constraint if you've been testing with the RC */ -/*IF EXISTS (SELECT name FROM sysindexes WHERE name = 'IX_cmsMemberType')*/ -/*ALTER TABLE [cmsMemberType] DROP CONSTRAINT [IX_cmsMemberType]*/ - -/************************** CLEANUP END ********************************************/ - - -/* Create missing indexes and primary keys */ -CREATE NONCLUSTERED INDEX [IX_Icon] ON CMSContenttype(nodeId, Icon) -; - -ALTER TABLE cmsContentType ADD CONSTRAINT - IX_cmsContentType UNIQUE NONCLUSTERED - ( - nodeId - ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) -; - -ALTER TABLE cmsContent ADD CONSTRAINT - IX_cmsContent UNIQUE NONCLUSTERED - ( - nodeId - ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) -; - -ALTER TABLE cmsContentVersion ADD CONSTRAINT - FK_cmsContentVersion_cmsContent FOREIGN KEY - ( - ContentId - ) REFERENCES cmsContent - ( - nodeId - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsMember ADD CONSTRAINT - PK_cmsMember PRIMARY KEY CLUSTERED - ( - nodeId - ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) -; - -ALTER TABLE cmsMember ADD CONSTRAINT - FK_cmsMember_cmsContent FOREIGN KEY - ( - nodeId - ) REFERENCES cmsContent - ( - nodeId - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsMember ADD CONSTRAINT - FK_cmsMember_umbracoNode FOREIGN KEY - ( - nodeId - ) REFERENCES umbracoNode - ( - id - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsStylesheet ADD CONSTRAINT - PK_cmsStylesheet PRIMARY KEY CLUSTERED - ( - nodeId - ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) -; - -ALTER TABLE cmsStylesheetProperty ADD CONSTRAINT - PK_cmsStylesheetProperty PRIMARY KEY CLUSTERED - ( - nodeId - ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) -; - -ALTER TABLE cmsStylesheetProperty ADD CONSTRAINT - FK_cmsStylesheetProperty_umbracoNode FOREIGN KEY - ( - nodeId - ) REFERENCES umbracoNode - ( - id - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsStylesheet ADD CONSTRAINT - FK_cmsStylesheet_umbracoNode FOREIGN KEY - ( - nodeId - ) REFERENCES umbracoNode - ( - id - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsContentXml ADD CONSTRAINT - FK_cmsContentXml_cmsContent FOREIGN KEY - ( - nodeId - ) REFERENCES cmsContent - ( - nodeId - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsDataType ADD CONSTRAINT - IX_cmsDataType UNIQUE NONCLUSTERED - ( - nodeId - ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) -; - - - -ALTER TABLE cmsDataType ADD CONSTRAINT - FK_cmsDataType_umbracoNode FOREIGN KEY - ( - nodeId - ) REFERENCES umbracoNode - ( - id - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - - - -ALTER TABLE cmsDataTypePreValues ADD CONSTRAINT - FK_cmsDataTypePreValues_cmsDataType FOREIGN KEY - ( - datatypeNodeId - ) REFERENCES cmsDataType - ( - nodeId - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsDocument ADD CONSTRAINT - FK_cmsDocument_cmsContent FOREIGN KEY - ( - nodeId - ) REFERENCES cmsContent - ( - nodeId - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsDocumentType ADD CONSTRAINT - FK_cmsDocumentType_cmsContentType FOREIGN KEY - ( - contentTypeNodeId - ) REFERENCES cmsContentType - ( - nodeId - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsDocumentType ADD CONSTRAINT - FK_cmsDocumentType_umbracoNode FOREIGN KEY - ( - contentTypeNodeId - ) REFERENCES umbracoNode - ( - id - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsMacroProperty ADD CONSTRAINT - FK_cmsMacroProperty_cmsMacro FOREIGN KEY - ( - macro - ) REFERENCES cmsMacro - ( - id - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsMemberType ADD CONSTRAINT - FK_cmsMemberType_cmsContentType FOREIGN KEY - ( - NodeId - ) REFERENCES cmsContentType - ( - nodeId - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsMemberType ADD CONSTRAINT - FK_cmsMemberType_umbracoNode FOREIGN KEY - ( - NodeId - ) REFERENCES umbracoNode - ( - id - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsMember2MemberGroup ADD CONSTRAINT - FK_cmsMember2MemberGroup_cmsMember FOREIGN KEY - ( - Member - ) REFERENCES cmsMember - ( - nodeId - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsDocument ADD CONSTRAINT - IX_cmsDocument UNIQUE NONCLUSTERED - ( - nodeId, - versionId - ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) -; - -ALTER TABLE cmsPropertyData ADD CONSTRAINT - FK_cmsPropertyData_cmsPropertyType FOREIGN KEY - ( - propertytypeid - ) REFERENCES cmsPropertyType - ( - id - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsPropertyType ADD CONSTRAINT - FK_cmsPropertyType_cmsContentType FOREIGN KEY - ( - contentTypeId - ) REFERENCES cmsContentType - ( - nodeId - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsPropertyType ADD CONSTRAINT - FK_cmsPropertyType_cmsDataType FOREIGN KEY - ( - dataTypeId - ) REFERENCES cmsDataType - ( - nodeId - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsTab ADD CONSTRAINT - FK_cmsTab_cmsContentType FOREIGN KEY - ( - contenttypeNodeId - ) REFERENCES cmsContentType - ( - nodeId - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsTemplate ADD CONSTRAINT - IX_cmsTemplate UNIQUE NONCLUSTERED - ( - nodeId - ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) -; - -ALTER TABLE cmsDocument ADD CONSTRAINT - FK_cmsDocument_cmsTemplate FOREIGN KEY - ( - templateId - ) REFERENCES cmsTemplate - ( - nodeId - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - - -ALTER TABLE umbracoDomains ADD CONSTRAINT - FK_umbracoDomains_umbracoNode FOREIGN KEY - ( - domainRootStructureID - ) REFERENCES umbracoNode - ( - id - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsDictionary ADD CONSTRAINT - IX_cmsDictionary UNIQUE NONCLUSTERED - ( - id - ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) -; - -ALTER TABLE cmsLanguageText ADD CONSTRAINT - FK_cmsLanguageText_cmsDictionary FOREIGN KEY - ( - UniqueId - ) REFERENCES cmsDictionary - ( - id - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - - - -ALTER TABLE umbracoUser2NodeNotify ADD CONSTRAINT - FK_umbracoUser2NodeNotify_umbracoUser FOREIGN KEY - ( - userId - ) REFERENCES umbracoUser - ( - id - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE umbracoUser2NodeNotify ADD CONSTRAINT - FK_umbracoUser2NodeNotify_umbracoNode FOREIGN KEY - ( - nodeId - ) REFERENCES umbracoNode - ( - id - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE umbracoUser2NodePermission ADD CONSTRAINT - FK_umbracoUser2NodePermission_umbracoUser FOREIGN KEY - ( - userId - ) REFERENCES umbracoUser - ( - id - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE umbracoUser2NodePermission ADD CONSTRAINT - FK_umbracoUser2NodePermission_umbracoNode FOREIGN KEY - ( - nodeId - ) REFERENCES umbracoNode - ( - id - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsTask ADD CONSTRAINT - FK_cmsTask_umbracoUser FOREIGN KEY - ( - parentUserId - ) REFERENCES umbracoUser - ( - id - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsTask ADD CONSTRAINT - FK_cmsTask_umbracoUser1 FOREIGN KEY - ( - userId - ) REFERENCES umbracoUser - ( - id - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsTask ADD CONSTRAINT - FK_cmsTask_umbracoNode FOREIGN KEY - ( - nodeId - ) REFERENCES umbracoNode - ( - id - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -CREATE NONCLUSTERED INDEX IX_umbracoLog ON umbracoLog - ( - NodeId - ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) -; - -ALTER TABLE umbracoRelation ADD CONSTRAINT - FK_umbracoRelation_umbracoRelationType FOREIGN KEY - ( - relType - ) REFERENCES umbracoRelationType - ( - id - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE umbracoRelation ADD CONSTRAINT - FK_umbracoRelation_umbracoNode FOREIGN KEY - ( - parentId - ) REFERENCES umbracoNode - ( - id - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE umbracoRelation ADD CONSTRAINT - FK_umbracoRelation_umbracoNode1 FOREIGN KEY - ( - childId - ) REFERENCES umbracoNode - ( - id - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - - - -ALTER TABLE cmsContentTypeAllowedContentType ADD CONSTRAINT - FK_cmsContentTypeAllowedContentType_cmsContentType FOREIGN KEY - ( - Id - ) REFERENCES cmsContentType - ( - nodeId - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsContentTypeAllowedContentType ADD CONSTRAINT - FK_cmsContentTypeAllowedContentType_cmsContentType1 FOREIGN KEY - ( - AllowedId - ) REFERENCES cmsContentType - ( - nodeId - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE umbracoLanguage ADD CONSTRAINT - IX_umbracoLanguage UNIQUE NONCLUSTERED - ( - languageISOCode - ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) -; - -ALTER TABLE umbracoUser ADD CONSTRAINT - IX_umbracoUser UNIQUE NONCLUSTERED - ( - userLogin - ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) -; - -ALTER TABLE cmsTaskType ADD CONSTRAINT - IX_cmsTaskType UNIQUE NONCLUSTERED - ( - alias - ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) -; - -ALTER TABLE cmsDocumentType ADD CONSTRAINT - FK_cmsDocumentType_cmsTemplate FOREIGN KEY - ( - templateNodeId - ) REFERENCES cmsTemplate - ( - nodeId - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsTemplate ADD CONSTRAINT - FK_cmsTemplate_cmsTemplate FOREIGN KEY - ( - master - ) REFERENCES cmsTemplate - ( - nodeId - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsContentVersion ADD CONSTRAINT - IX_cmsContentVersion UNIQUE NONCLUSTERED - ( - VersionId - ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) -; - -ALTER TABLE cmsPreviewXml ADD CONSTRAINT - FK_cmsPreviewXml_cmsContentVersion FOREIGN KEY - ( - versionId - ) REFERENCES cmsContentVersion - ( - VersionId - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - -ALTER TABLE cmsPreviewXml ADD CONSTRAINT - FK_cmsPreviewXml_cmsContent FOREIGN KEY - ( - nodeId - ) REFERENCES cmsContent - ( - nodeId - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - - -ALTER TABLE cmsMember2MemberGroup ADD CONSTRAINT - FK_cmsMember2MemberGroup_umbracoNode FOREIGN KEY - ( - MemberGroup - ) REFERENCES umbracoNode - ( - id - ) ON UPDATE NO ACTION - ON DELETE NO ACTION -; - - -/*********************************************************************************************************************** - -END OF NEW CONSTRAINTS - -***********************************************************************************************************************/ diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 74eed99143..0320161398 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -129,16 +129,11 @@ - - - - - @@ -160,12 +155,10 @@ - - @@ -186,14 +179,13 @@ - - + @@ -204,9 +196,6 @@ - - - @@ -218,15 +207,6 @@ - - - True - True - SqlResources.resx - - - - @@ -336,11 +316,6 @@ - - ResXFileCodeGenerator - SqlResources.Designer.cs - Designer - ResXFileCodeGenerator ImportResources.Designer.cs @@ -353,10 +328,6 @@ - - - - Designer diff --git a/src/Umbraco.Web/Macros/PartialViewMacroPage.cs b/src/Umbraco.Web/Macros/PartialViewMacroPage.cs deleted file mode 100644 index 7297fec6d3..0000000000 --- a/src/Umbraco.Web/Macros/PartialViewMacroPage.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Umbraco.Web.Models; -using Umbraco.Web.Mvc; - -namespace Umbraco.Web.Macros -{ - /// - /// The base view class that PartialViewMacro views need to inherit from - /// - public abstract class PartialViewMacroPage : UmbracoViewPage - { } -} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index ad7dd86730..8e988e3980 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -204,6 +204,7 @@ + From 474f267e693e25df0a69b09812e6af70503098f6 Mon Sep 17 00:00:00 2001 From: Elitsa Marinovska Date: Tue, 8 Dec 2020 12:16:55 +0100 Subject: [PATCH 09/27] Removing references of deleted files --- src/Umbraco.Tests/Umbraco.Tests.csproj | 5 ----- src/Umbraco.Web/Umbraco.Web.csproj | 2 -- 2 files changed, 7 deletions(-) diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 0320161398..807c64f315 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -185,11 +185,6 @@ - - - - - diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 8e988e3980..e59eed272c 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -204,8 +204,6 @@ - - From 1727a5d6f1ccd354ba4e56f143e33a8bab051e1b Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 8 Dec 2020 12:32:19 +0100 Subject: [PATCH 10/27] Added specific PhysicalFileProvider for the app_plugins folder, that also checks whether extensions are allowed. --- .../Models/UmbracoPluginSettings.cs | 21 ++++++++ src/Umbraco.Core/Constants-Configuration.cs | 1 + .../BackOfficeApplicationBuilderExtensions.cs | 21 +++++++- .../UmbracoPluginPhysicalFileProvider.cs | 53 +++++++++++++++++++ .../Builder/UmbracoBuilderExtensions.cs | 3 +- src/Umbraco.Web.UI.NetCore/Startup.cs | 9 ++-- 6 files changed, 102 insertions(+), 6 deletions(-) create mode 100644 src/Umbraco.Core/Configuration/Models/UmbracoPluginSettings.cs create mode 100644 src/Umbraco.Web.BackOffice/Plugins/UmbracoPluginPhysicalFileProvider.cs diff --git a/src/Umbraco.Core/Configuration/Models/UmbracoPluginSettings.cs b/src/Umbraco.Core/Configuration/Models/UmbracoPluginSettings.cs new file mode 100644 index 0000000000..3532db4e9e --- /dev/null +++ b/src/Umbraco.Core/Configuration/Models/UmbracoPluginSettings.cs @@ -0,0 +1,21 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + +using System.Collections.Generic; + +namespace Umbraco.Core.Configuration.Models +{ + /// + /// Typed configuration options for the plugins. + /// + public class UmbracoPluginSettings + { + /// + /// Gets or sets the allowed file extensions (including the period ".") that should be accessible from the browser. + /// + public ISet BrowsableFileExtensions { get; set; } = new HashSet(new[] + { + ".html", ".css", ".js", ".jpg", ".jpeg", ".gif", ".png", ".svg" + }); + } +} diff --git a/src/Umbraco.Core/Constants-Configuration.cs b/src/Umbraco.Core/Constants-Configuration.cs index 2c9fe3caee..a60f29c39d 100644 --- a/src/Umbraco.Core/Constants-Configuration.cs +++ b/src/Umbraco.Core/Constants-Configuration.cs @@ -39,6 +39,7 @@ public const string ConfigMemberPassword = ConfigPrefix + "Security:MemberPassword"; public const string ConfigModelsBuilder = ConfigPrefix + "ModelsBuilder"; public const string ConfigNuCache = ConfigPrefix + "NuCache"; + public const string ConfigPlugins = ConfigPrefix + "Plugins"; public const string ConfigRequestHandler = ConfigPrefix + "RequestHandler"; public const string ConfigRuntime = ConfigPrefix + "Runtime"; public const string ConfigRuntimeMinification = ConfigPrefix + "RuntimeMinification"; diff --git a/src/Umbraco.Web.BackOffice/Extensions/BackOfficeApplicationBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/Extensions/BackOfficeApplicationBuilderExtensions.cs index 6ff42a5737..84383b1d40 100644 --- a/src/Umbraco.Web.BackOffice/Extensions/BackOfficeApplicationBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/Extensions/BackOfficeApplicationBuilderExtensions.cs @@ -1,8 +1,13 @@ using System; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using SixLabors.ImageSharp.Web.DependencyInjection; +using Umbraco.Core; +using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Hosting; using Umbraco.Web.BackOffice.Middleware; +using Umbraco.Web.BackOffice.Plugins; using Umbraco.Web.BackOffice.Routing; using Umbraco.Web.Common.Security; @@ -21,6 +26,7 @@ namespace Umbraco.Extensions app.UseRequestLocalization(); app.UseUmbracoRequestLogging(); app.UseUmbracoBackOffice(); + app.UseUmbracoPlugins(); app.UseUmbracoPreview(); app.UseUmbracoInstaller(); @@ -57,6 +63,20 @@ namespace Umbraco.Extensions return app; } + public static IApplicationBuilder UseUmbracoPlugins(this IApplicationBuilder app) + { + app.UseStaticFiles(new StaticFileOptions + { + FileProvider = new UmbracoPluginPhysicalFileProvider( + app.ApplicationServices.GetRequiredService().MapPathContentRoot(Constants.SystemDirectories.AppPlugins), + app.ApplicationServices.GetRequiredService>()), + RequestPath = Constants.SystemDirectories.AppPlugins + }); + + return app; + } + + public static IApplicationBuilder UseUmbracoPreview(this IApplicationBuilder app) { app.UseEndpoints(endpoints => @@ -67,7 +87,6 @@ namespace Umbraco.Extensions return app; } - private static IApplicationBuilder UseBackOfficeUserManagerAuditing(this IApplicationBuilder app) { var auditer = app.ApplicationServices.GetRequiredService(); diff --git a/src/Umbraco.Web.BackOffice/Plugins/UmbracoPluginPhysicalFileProvider.cs b/src/Umbraco.Web.BackOffice/Plugins/UmbracoPluginPhysicalFileProvider.cs new file mode 100644 index 0000000000..42300e3b71 --- /dev/null +++ b/src/Umbraco.Web.BackOffice/Plugins/UmbracoPluginPhysicalFileProvider.cs @@ -0,0 +1,53 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + +using System.IO; +using Microsoft.Extensions.FileProviders; +using Microsoft.Extensions.FileProviders.Physical; +using Microsoft.Extensions.Options; +using Umbraco.Core; +using Umbraco.Core.Configuration.Models; + +namespace Umbraco.Web.BackOffice.Plugins +{ + /// + /// Looks up files using the on-disk file system and check file extensions are on a allow list + /// + /// + /// When the environment variable "DOTNET_USE_POLLING_FILE_WATCHER" is set to "1" or "true", calls to + /// will use . + /// + public class UmbracoPluginPhysicalFileProvider : PhysicalFileProvider, IFileProvider + { + private readonly IOptions _options; + + /// + /// Initializes a new instance of the class, at the given root directory. + /// + /// The root directory. This should be an absolute path. + /// The configuration options. + /// Specifies which files or directories are excluded. + public UmbracoPluginPhysicalFileProvider(string root, IOptions options, ExclusionFilters filters = ExclusionFilters.Sensitive) + : base(root, filters) => _options = options; + + /// + /// Locate a file at the given path by directly mapping path segments to physical directories. + /// + /// + /// The path needs to pass the and the to be found. + /// + /// A path under the root directory + /// The file information. Caller must check property. + public new IFileInfo GetFileInfo(string subpath) + { + var extension = Path.GetExtension(subpath); + var subPathInclAppPluginsFolder = Path.Combine(Constants.SystemDirectories.AppPlugins, subpath); + if (!_options.Value.BrowsableFileExtensions.Contains(extension)) + { + return new NotFoundFileInfo(subPathInclAppPluginsFolder); + } + + return base.GetFileInfo(subPathInclAppPluginsFolder); + } + } +} diff --git a/src/Umbraco.Web.Common/Builder/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Common/Builder/UmbracoBuilderExtensions.cs index e72089b8fe..17c91d433a 100644 --- a/src/Umbraco.Web.Common/Builder/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Common/Builder/UmbracoBuilderExtensions.cs @@ -18,13 +18,11 @@ using Microsoft.Extensions.Options; using Serilog; using Smidge; using Smidge.Nuglify; -using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.Models.Validation; -using Umbraco.Core.DependencyInjection; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; @@ -195,6 +193,7 @@ namespace Umbraco.Core.DependencyInjection builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigTypeFinder)); builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigUserPassword)); builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigWebRouting)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigPlugins)); return builder; } diff --git a/src/Umbraco.Web.UI.NetCore/Startup.cs b/src/Umbraco.Web.UI.NetCore/Startup.cs index d496aadfd3..2598b09d8d 100644 --- a/src/Umbraco.Web.UI.NetCore/Startup.cs +++ b/src/Umbraco.Web.UI.NetCore/Startup.cs @@ -4,8 +4,8 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using Umbraco.Extensions; using Umbraco.Core.DependencyInjection; +using Umbraco.Extensions; namespace Umbraco.Web.UI.NetCore { @@ -28,11 +28,14 @@ namespace Umbraco.Web.UI.NetCore _config = config ?? throw new ArgumentNullException(nameof(config)); } - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 + /// /// Configures the services /// + /// + /// This method gets called by the runtime. Use this method to add services to the container. + /// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 + /// public void ConfigureServices(IServiceCollection services) { #pragma warning disable IDE0022 // Use expression body for methods From f580e38383a25ab651bf94b93e628e6a81067f5e Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 8 Dec 2020 13:18:23 +0100 Subject: [PATCH 11/27] Added fonts to default BrowsableFileExtensions --- .../Configuration/Models/UmbracoPluginSettings.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Configuration/Models/UmbracoPluginSettings.cs b/src/Umbraco.Core/Configuration/Models/UmbracoPluginSettings.cs index 3532db4e9e..1bac495408 100644 --- a/src/Umbraco.Core/Configuration/Models/UmbracoPluginSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/UmbracoPluginSettings.cs @@ -15,7 +15,11 @@ namespace Umbraco.Core.Configuration.Models /// public ISet BrowsableFileExtensions { get; set; } = new HashSet(new[] { - ".html", ".css", ".js", ".jpg", ".jpeg", ".gif", ".png", ".svg" + ".html", // markup + ".css", // styles + ".js", // scripts + ".jpg", ".jpeg", ".gif", ".png", ".svg", // images + ".eot", ".ttf", ".woff" // fonts }); } } From 6bd8285a803a0a7825e1bbbfd3cf232092202e23 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 8 Dec 2020 14:30:51 +0100 Subject: [PATCH 12/27] Added Configuration files and license to default BrowsableFileExtensions --- .../Configuration/Models/UmbracoPluginSettings.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Configuration/Models/UmbracoPluginSettings.cs b/src/Umbraco.Core/Configuration/Models/UmbracoPluginSettings.cs index 1bac495408..907b29490d 100644 --- a/src/Umbraco.Core/Configuration/Models/UmbracoPluginSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/UmbracoPluginSettings.cs @@ -19,7 +19,9 @@ namespace Umbraco.Core.Configuration.Models ".css", // styles ".js", // scripts ".jpg", ".jpeg", ".gif", ".png", ".svg", // images - ".eot", ".ttf", ".woff" // fonts + ".eot", ".ttf", ".woff", // fonts + ".xml", ".json", ".config", // configurations + ".lic" // license }); } } From 0f36db188e6daa4719260a87c6ec6d8d36086775 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Wed, 9 Dec 2020 09:03:49 +0100 Subject: [PATCH 13/27] Ensure folder app_plugins exists --- .../BackOfficeApplicationBuilderExtensions.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.BackOffice/Extensions/BackOfficeApplicationBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/Extensions/BackOfficeApplicationBuilderExtensions.cs index 84383b1d40..dd7c1b12fc 100644 --- a/src/Umbraco.Web.BackOffice/Extensions/BackOfficeApplicationBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/Extensions/BackOfficeApplicationBuilderExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; @@ -65,11 +66,21 @@ namespace Umbraco.Extensions public static IApplicationBuilder UseUmbracoPlugins(this IApplicationBuilder app) { + var hostingEnvironment = app.ApplicationServices.GetRequiredService(); + var umbracoPluginSettings = app.ApplicationServices.GetRequiredService>(); + + var pluginFolder = hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.AppPlugins); + + // Ensure the plugin folder exists + Directory.CreateDirectory(pluginFolder); + + var fileProvider = new UmbracoPluginPhysicalFileProvider( + pluginFolder, + umbracoPluginSettings); + app.UseStaticFiles(new StaticFileOptions { - FileProvider = new UmbracoPluginPhysicalFileProvider( - app.ApplicationServices.GetRequiredService().MapPathContentRoot(Constants.SystemDirectories.AppPlugins), - app.ApplicationServices.GetRequiredService>()), + FileProvider = fileProvider, RequestPath = Constants.SystemDirectories.AppPlugins }); From 7776e203a65ab02e27a124e85a6a03830c0818ae Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 10 Dec 2020 08:55:47 +0100 Subject: [PATCH 14/27] Fix issue with auth on media upload --- .../Controllers/MediaController.cs | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs b/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs index 49a20f1150..f03130b537 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs @@ -6,6 +6,7 @@ using System.Net; using System.Net.Mime; using System.Text; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; @@ -22,7 +23,6 @@ using Umbraco.Core.Media; using Umbraco.Core.Models; using Umbraco.Core.Models.ContentEditing; using Umbraco.Core.Models.Entities; -using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.Validation; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Querying; @@ -32,17 +32,15 @@ using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Extensions; +using Umbraco.Web.BackOffice.ActionResults; +using Umbraco.Web.BackOffice.Authorization; using Umbraco.Web.BackOffice.Filters; using Umbraco.Web.BackOffice.ModelBinders; -using Umbraco.Web.BackOffice.ActionResults; using Umbraco.Web.Common.Attributes; +using Umbraco.Web.Common.Authorization; using Umbraco.Web.Common.Exceptions; using Umbraco.Web.ContentApps; using Umbraco.Web.Models.ContentEditing; -using Constants = Umbraco.Core.Constants; -using Microsoft.AspNetCore.Authorization; -using Umbraco.Web.Common.Authorization; -using Umbraco.Web.BackOffice.Authorization; namespace Umbraco.Web.BackOffice.Controllers { @@ -702,7 +700,7 @@ namespace Umbraco.Web.BackOffice.Controllers return NotFound("The passed id doesn't exist"); } var tempFiles = new PostedFiles(); - + //in case we pass a path with a folder in it, we will create it and upload media to it. if (!string.IsNullOrEmpty(path)) @@ -882,7 +880,7 @@ namespace Umbraco.Web.BackOffice.Controllers if (validatePermissions) { var requirement = new MediaPermissionsResourceRequirement(); - var authorizationResult = await _authorizationService.AuthorizeAsync(User, _mediaService.GetById(intParentId), requirement); + var authorizationResult = await _authorizationService.AuthorizeAsync(User, new MediaPermissionsResource(_mediaService.GetById(intParentId)), requirement); if (!authorizationResult.Succeeded) { throw new HttpResponseException( @@ -893,7 +891,7 @@ namespace Umbraco.Web.BackOffice.Controllers NotificationStyle.Warning))); } } - + return intParentId; } @@ -909,7 +907,7 @@ namespace Umbraco.Web.BackOffice.Controllers throw new HttpResponseException(HttpStatusCode.NotFound); } - + var toMove = _mediaService.GetById(model.Id); if (toMove == null) { @@ -957,7 +955,7 @@ namespace Umbraco.Web.BackOffice.Controllers return toMove; } - + public PagedResult GetPagedReferences(int id, string entityType, int pageNumber = 1, int pageSize = 100) { From 3f9b2845409f4402400b0103e6e4a6d9d58ba403 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 10 Dec 2020 08:56:41 +0100 Subject: [PATCH 15/27] Fix issue with missing properties --- src/Umbraco.Core/Models/ContentEditing/ContentItemBasic.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentItemBasic.cs b/src/Umbraco.Core/Models/ContentEditing/ContentItemBasic.cs index 6689e133fc..5f5bc3cebd 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentItemBasic.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentItemBasic.cs @@ -91,6 +91,7 @@ namespace Umbraco.Web.Models.ContentEditing private IEnumerable _properties; + [DataMember(Name = "properties")] public virtual IEnumerable Properties { get => _properties; From 51f20119a240a21f768dab4e4ecd569b1496806b Mon Sep 17 00:00:00 2001 From: Paul Johnson Date: Fri, 27 Nov 2020 19:15:49 +0000 Subject: [PATCH 16/27] Enable running integrations tests on Linux --- .gitattributes | 1 + .../Persistence/LocalDb.cs | 2 +- .../Testing/ITestDatabase.cs | 10 ++ .../Testing/IntegrationTestComposer.cs | 2 + .../Testing/LocalDbTestDatabase.cs | 20 +-- .../Testing/SqlDeveloperTestDatabase.cs | 163 ++++++++++++++++++ .../Testing/TestDatabaseFactory.cs | 44 +++++ .../Testing/UmbracoIntegrationTest.cs | 9 +- .../Services/Importing/ImportResources.resx | 4 +- .../Umbraco.Tests.Integration.csproj | 4 + 10 files changed, 232 insertions(+), 27 deletions(-) create mode 100644 src/Umbraco.Tests.Integration/Testing/ITestDatabase.cs create mode 100644 src/Umbraco.Tests.Integration/Testing/SqlDeveloperTestDatabase.cs create mode 100644 src/Umbraco.Tests.Integration/Testing/TestDatabaseFactory.cs diff --git a/.gitattributes b/.gitattributes index c8987ade67..3241b6511c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -43,6 +43,7 @@ *.hs text=auto *.json text=auto *.xml text=auto +*.resx text=auto *.csproj text=auto merge=union *.vbproj text=auto merge=union diff --git a/src/Umbraco.Infrastructure/Persistence/LocalDb.cs b/src/Umbraco.Infrastructure/Persistence/LocalDb.cs index 4ec233e17f..89fce803b2 100644 --- a/src/Umbraco.Infrastructure/Persistence/LocalDb.cs +++ b/src/Umbraco.Infrastructure/Persistence/LocalDb.cs @@ -937,7 +937,7 @@ namespace Umbraco.Core.Persistence /// This is a C# implementation of T-SQL QUOTEDNAME. /// is optional, it can be '[' (default), ']', '\'' or '"'. /// - private static string QuotedName(string name, char quote = '[') + internal static string QuotedName(string name, char quote = '[') { switch (quote) { diff --git a/src/Umbraco.Tests.Integration/Testing/ITestDatabase.cs b/src/Umbraco.Tests.Integration/Testing/ITestDatabase.cs new file mode 100644 index 0000000000..250e062ee4 --- /dev/null +++ b/src/Umbraco.Tests.Integration/Testing/ITestDatabase.cs @@ -0,0 +1,10 @@ +namespace Umbraco.Tests.Integration.Testing +{ + public interface ITestDatabase + { + string ConnectionString { get; } + int AttachEmpty(); + int AttachSchema(); + void Detach(int id); + } +} diff --git a/src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs b/src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs index dacfd950e0..39d74f8869 100644 --- a/src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs +++ b/src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs @@ -49,8 +49,10 @@ namespace Umbraco.Tests.Integration.Testing // we don't want persisted nucache files in tests builder.Services.AddTransient(factory => new PublishedSnapshotServiceOptions { IgnoreLocalDb = true }); + #if IS_WINDOWS // ensure all lucene indexes are using RAM directory (no file system) builder.Services.AddUnique(); + #endif // replace this service so that it can lookup the correct file locations builder.Services.AddUnique(GetLocalizedTextService); diff --git a/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs b/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs index 39f9ca5592..bb83914b63 100644 --- a/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs +++ b/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs @@ -20,7 +20,7 @@ namespace Umbraco.Tests.Integration.Testing /// /// Manages a pool of LocalDb databases for integration testing /// - public class LocalDbTestDatabase + public class LocalDbTestDatabase : ITestDatabase { public const string InstanceName = "UmbracoTests"; public const string DatabaseName = "UmbracoTests"; @@ -139,7 +139,7 @@ namespace Umbraco.Tests.Integration.Testing } - private static void AddParameter(IDbCommand cmd, UmbracoDatabase.ParameterInfo parameterInfo) + internal static void AddParameter(IDbCommand cmd, UmbracoDatabase.ParameterInfo parameterInfo) { var p = cmd.CreateParameter(); p.ParameterName = parameterInfo.Name; @@ -149,22 +149,6 @@ namespace Umbraco.Tests.Integration.Testing cmd.Parameters.Add(p); } - public void Clear() - { - var filename = Path.Combine(_filesPath, DatabaseName).ToUpper(); - - foreach (var database in _instance.GetDatabases()) - { - if (database.StartsWith(filename)) - _instance.DropDatabase(database); - } - - foreach (var file in Directory.EnumerateFiles(_filesPath)) - { - if (file.EndsWith(".mdf") == false && file.EndsWith(".ldf") == false) continue; - File.Delete(file); - } - } private static void ResetLocalDb(IDbCommand cmd) { diff --git a/src/Umbraco.Tests.Integration/Testing/SqlDeveloperTestDatabase.cs b/src/Umbraco.Tests.Integration/Testing/SqlDeveloperTestDatabase.cs new file mode 100644 index 0000000000..f5ae1661b8 --- /dev/null +++ b/src/Umbraco.Tests.Integration/Testing/SqlDeveloperTestDatabase.cs @@ -0,0 +1,163 @@ +using System; +using System.Data; +using System.Data.SqlClient; +using System.Linq; +using System.Text.RegularExpressions; +using Microsoft.Extensions.Logging; +using Umbraco.Core; +using Umbraco.Core.Configuration; +using Umbraco.Core.Migrations.Install; +using Umbraco.Core.Persistence; + +// ReSharper disable ConvertToUsingDeclaration + +namespace Umbraco.Tests.Integration.Testing +{ + /// + /// It's not meant to be pretty, rushed port of LocalDb.cs + LocalDbTestDatabase.cs + /// + public class SqlDeveloperTestDatabase : ITestDatabase + { + private readonly string _masterConnectionString; + private readonly string _databaseName; + private readonly ILoggerFactory _loggerFactory; + private readonly ILogger _log; + private readonly IUmbracoDatabaseFactory _databaseFactory; + private UmbracoDatabase.CommandInfo[] _cachedDatabaseInitCommands; + + public SqlDeveloperTestDatabase(ILoggerFactory loggerFactory, IUmbracoDatabaseFactory databaseFactory, string masterConnectionString) + { + _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); + _databaseFactory = databaseFactory ?? throw new ArgumentNullException(nameof(databaseFactory)); + _masterConnectionString = masterConnectionString; + _databaseName = $"Umbraco_Integration_{Guid.NewGuid()}".Replace("-", string.Empty); + _log = loggerFactory.CreateLogger(); + } + + public string ConnectionString { get; private set; } + + public int AttachEmpty() + { + CreateDatabase(); + return -1; + } + + public int AttachSchema() + { + CreateDatabase(); + + _log.LogInformation($"Attaching schema {_databaseName}"); + + using (var connection = new SqlConnection(ConnectionString)) + { + connection.Open(); + using (var command = connection.CreateCommand()) + { + RebuildSchema(command); + } + } + + return -1; + } + + public void Detach(int id) + { + _log.LogInformation($"Dropping database {_databaseName}"); + using (var connection = new SqlConnection(_masterConnectionString)) + { + connection.Open(); + using (var command = connection.CreateCommand()) + { + SetCommand(command, $@" + ALTER DATABASE{LocalDb.QuotedName(_databaseName)} + SET SINGLE_USER + WITH ROLLBACK IMMEDIATE + "); + command.ExecuteNonQuery(); + + SetCommand(command, $@"DROP DATABASE {LocalDb.QuotedName(_databaseName)}"); + command.ExecuteNonQuery(); + } + } + } + + private void CreateDatabase() + { + _log.LogInformation($"Creating database {_databaseName}"); + using (var connection = new SqlConnection(_masterConnectionString)) + { + connection.Open(); + using (var command = connection.CreateCommand()) + { + SetCommand(command, $@"CREATE DATABASE {LocalDb.QuotedName(_databaseName)}"); + var unused = command.ExecuteNonQuery(); + } + } + + ConnectionString = ConstructConnectionString(_masterConnectionString, _databaseName); + } + + private static string ConstructConnectionString(string masterConnectionString, string databaseName) + { + var prefix = Regex.Replace(masterConnectionString, "Database=.+?;", string.Empty); + var connectionString = $"{prefix};Database={databaseName};"; + return connectionString.Replace(";;", ";"); + } + + private static void SetCommand(SqlCommand command, string sql, params object[] args) + { + command.CommandType = CommandType.Text; + command.CommandText = sql; + command.Parameters.Clear(); + + for (var i = 0; i < args.Length; i++) + { + command.Parameters.AddWithValue("@" + i, args[i]); + } + } + + private void RebuildSchema(IDbCommand command) + { + if (_cachedDatabaseInitCommands != null) + { + foreach (var dbCommand in _cachedDatabaseInitCommands) + { + + if (dbCommand.Text.StartsWith("SELECT ")) + { + continue; + } + + command.CommandText = dbCommand.Text; + command.Parameters.Clear(); + + foreach (var parameterInfo in dbCommand.Parameters) + { + LocalDbTestDatabase.AddParameter(command, parameterInfo); + } + + command.ExecuteNonQuery(); + } + } + else + { + _databaseFactory.Configure(ConnectionString, Constants.DatabaseProviders.SqlServer); + + using (var database = (UmbracoDatabase)_databaseFactory.CreateDatabase()) + { + database.LogCommands = true; + + using (var transaction = database.GetTransaction()) + { + var schemaCreator = new DatabaseSchemaCreator(database, _loggerFactory.CreateLogger(), _loggerFactory, new UmbracoVersion()); + schemaCreator.InitializeDatabaseSchema(); + + transaction.Complete(); + + _cachedDatabaseInitCommands = database.Commands.ToArray(); + } + } + } + } + } +} diff --git a/src/Umbraco.Tests.Integration/Testing/TestDatabaseFactory.cs b/src/Umbraco.Tests.Integration/Testing/TestDatabaseFactory.cs new file mode 100644 index 0000000000..0f403818b7 --- /dev/null +++ b/src/Umbraco.Tests.Integration/Testing/TestDatabaseFactory.cs @@ -0,0 +1,44 @@ +using System; +using System.Runtime.InteropServices; +using Microsoft.Extensions.Logging; +using Umbraco.Core.Persistence; + +namespace Umbraco.Tests.Integration.Testing +{ + public class TestDatabaseFactory + { + public static ITestDatabase Create(string filesPath, ILoggerFactory loggerFactory, IUmbracoDatabaseFactory dbFactory) + { + return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + ? CreateLocalDb(filesPath, loggerFactory, dbFactory) + : CreateSqlDeveloper(loggerFactory, dbFactory); + } + + private static ITestDatabase CreateLocalDb(string filesPath, ILoggerFactory loggerFactory, IUmbracoDatabaseFactory dbFactory) + { + var localDb = new LocalDb(); + + if (!localDb.IsAvailable) + { + throw new InvalidOperationException("LocalDB is not available."); + } + + return new LocalDbTestDatabase(loggerFactory, localDb, filesPath, dbFactory); + } + + private static ITestDatabase CreateSqlDeveloper(ILoggerFactory loggerFactory, IUmbracoDatabaseFactory dbFactory) + { + // $ export SA_PASSWORD=Foobar123! + // $ export UmbracoIntegrationTestConnectionString="Server=localhost,1433;User Id=sa;Password=$SA_PASSWORD;" + // $ docker run -e 'ACCEPT_EULA=Y' -e "SA_PASSWORD=$SA_PASSWORD" -e 'MSSQL_PID=Developer' -p 1433:1433 -d mcr.microsoft.com/mssql/server:2017-latest-ubuntu + var connectionString = Environment.GetEnvironmentVariable("UmbracoIntegrationTestConnectionString"); + + if (string.IsNullOrEmpty(connectionString)) + { + throw new InvalidOperationException("ENV: UmbracoIntegrationTestConnectionString is not set"); + } + + return new SqlDeveloperTestDatabase(loggerFactory, dbFactory, connectionString); + } + } +} diff --git a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs index a8875de286..9627fdf42a 100644 --- a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs +++ b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs @@ -242,7 +242,7 @@ namespace Umbraco.Tests.Integration.Testing #region LocalDb private static readonly object _dbLocker = new object(); - private static LocalDbTestDatabase _dbInstance; + private static ITestDatabase _dbInstance; protected void UseTestLocalDb(IServiceProvider serviceProvider) { @@ -267,17 +267,14 @@ namespace Umbraco.Tests.Integration.Testing /// /// There must only be ONE instance shared between all tests in a session /// - private static LocalDbTestDatabase GetOrCreateDatabase(string filesPath, ILoggerFactory loggerFactory, IUmbracoDatabaseFactory dbFactory) + private static ITestDatabase GetOrCreateDatabase(string filesPath, ILoggerFactory loggerFactory, IUmbracoDatabaseFactory dbFactory) { lock (_dbLocker) { if (_dbInstance != null) return _dbInstance; - var localDb = new LocalDb(); - if (localDb.IsAvailable == false) - throw new InvalidOperationException("LocalDB is not available."); - _dbInstance = new LocalDbTestDatabase(loggerFactory, localDb, filesPath, dbFactory); + _dbInstance = TestDatabaseFactory.Create(filesPath, loggerFactory, dbFactory); return _dbInstance; } } diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/ImportResources.resx b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/ImportResources.resx index 5823fa1245..fdf7880297 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/ImportResources.resx +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/Importing/ImportResources.resx @@ -119,6 +119,6 @@ - dictionary-package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + Dictionary-Package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - \ No newline at end of file + diff --git a/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj b/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj index c5b42f9848..b996205712 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj +++ b/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj @@ -7,6 +7,10 @@ 8 + + IS_WINDOWS + + From 897fe804b0c0e1bca21a1c180cd9bf7b0900666b Mon Sep 17 00:00:00 2001 From: Paul Johnson Date: Mon, 30 Nov 2020 12:14:53 +0000 Subject: [PATCH 17/27] Multiple test databases, similar setup to LocalDbTestDatabase.DatabasePool --- .../GlobalSetupTeardown.cs | 1 + .../Testing/LocalDbTestDatabase.cs | 4 +- .../Testing/SqlDeveloperTestDatabase.cs | 209 ++++++++++++++---- .../Testing/UmbracoIntegrationTest.cs | 2 +- 4 files changed, 171 insertions(+), 45 deletions(-) diff --git a/src/Umbraco.Tests.Integration/GlobalSetupTeardown.cs b/src/Umbraco.Tests.Integration/GlobalSetupTeardown.cs index fe1d604dd9..0fdac242d9 100644 --- a/src/Umbraco.Tests.Integration/GlobalSetupTeardown.cs +++ b/src/Umbraco.Tests.Integration/GlobalSetupTeardown.cs @@ -24,6 +24,7 @@ public class TestsSetup public void TearDown() { LocalDbTestDatabase.KillLocalDb(); + SqlDeveloperTestDatabase.Instance?.Finish(); Console.WriteLine("TOTAL TESTS DURATION: {0}", _stopwatch.Elapsed); } } diff --git a/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs b/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs index bb83914b63..0a081f48e9 100644 --- a/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs +++ b/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs @@ -150,7 +150,7 @@ namespace Umbraco.Tests.Integration.Testing } - private static void ResetLocalDb(IDbCommand cmd) + internal static void ResetLocalDb(IDbCommand cmd) { // https://stackoverflow.com/questions/536350 @@ -211,7 +211,7 @@ namespace Umbraco.Tests.Integration.Testing } } - private static void Retry(int maxIterations, Action action) + internal static void Retry(int maxIterations, Action action) { for (var i = 0; i < maxIterations; i++) { diff --git a/src/Umbraco.Tests.Integration/Testing/SqlDeveloperTestDatabase.cs b/src/Umbraco.Tests.Integration/Testing/SqlDeveloperTestDatabase.cs index f5ae1661b8..560bcbe00a 100644 --- a/src/Umbraco.Tests.Integration/Testing/SqlDeveloperTestDatabase.cs +++ b/src/Umbraco.Tests.Integration/Testing/SqlDeveloperTestDatabase.cs @@ -1,8 +1,11 @@ using System; +using System.Collections.Concurrent; +using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Linq; using System.Text.RegularExpressions; +using System.Threading; using Microsoft.Extensions.Logging; using Umbraco.Core; using Umbraco.Core.Configuration; @@ -18,83 +21,90 @@ namespace Umbraco.Tests.Integration.Testing /// public class SqlDeveloperTestDatabase : ITestDatabase { + + // This is gross but it's how the other one works and I don't want to refactor everything. + public string ConnectionString { get; private set; } + private readonly string _masterConnectionString; - private readonly string _databaseName; private readonly ILoggerFactory _loggerFactory; private readonly ILogger _log; private readonly IUmbracoDatabaseFactory _databaseFactory; + private readonly IDictionary _testDatabases; private UmbracoDatabase.CommandInfo[] _cachedDatabaseInitCommands; + + private BlockingCollection _prepareQueue; + private BlockingCollection _readySchemaQueue; + private BlockingCollection _readyEmptyQueue; + + private const string _databasePrefix = "UmbracoTest"; + private const int _threadCount = 2; + + public static SqlDeveloperTestDatabase Instance; public SqlDeveloperTestDatabase(ILoggerFactory loggerFactory, IUmbracoDatabaseFactory databaseFactory, string masterConnectionString) { _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); _databaseFactory = databaseFactory ?? throw new ArgumentNullException(nameof(databaseFactory)); _masterConnectionString = masterConnectionString; - _databaseName = $"Umbraco_Integration_{Guid.NewGuid()}".Replace("-", string.Empty); _log = loggerFactory.CreateLogger(); - } - public string ConnectionString { get; private set; } + _testDatabases = new[] + { + new TestDbMeta(1, false, masterConnectionString), + new TestDbMeta(2, false, masterConnectionString), + + new TestDbMeta(3, true, masterConnectionString), + new TestDbMeta(4, true, masterConnectionString), + }.ToDictionary(x => x.Id); + + Instance = this; // For GlobalSetupTeardown.cs + } public int AttachEmpty() { - CreateDatabase(); - return -1; + if (_prepareQueue == null) + { + Initialize(); + } + + var meta = _readyEmptyQueue.Take(); + + ConnectionString = meta.ConnectionString; + + return meta.Id; } public int AttachSchema() { - CreateDatabase(); - - _log.LogInformation($"Attaching schema {_databaseName}"); - - using (var connection = new SqlConnection(ConnectionString)) + if (_prepareQueue == null) { - connection.Open(); - using (var command = connection.CreateCommand()) - { - RebuildSchema(command); - } + Initialize(); } - return -1; + var meta = _readySchemaQueue.Take(); + + ConnectionString = meta.ConnectionString; + + return meta.Id; } public void Detach(int id) { - _log.LogInformation($"Dropping database {_databaseName}"); - using (var connection = new SqlConnection(_masterConnectionString)) - { - connection.Open(); - using (var command = connection.CreateCommand()) - { - SetCommand(command, $@" - ALTER DATABASE{LocalDb.QuotedName(_databaseName)} - SET SINGLE_USER - WITH ROLLBACK IMMEDIATE - "); - command.ExecuteNonQuery(); - - SetCommand(command, $@"DROP DATABASE {LocalDb.QuotedName(_databaseName)}"); - command.ExecuteNonQuery(); - } - } + _prepareQueue.TryAdd(_testDatabases[id]); } - private void CreateDatabase() + private void CreateDatabase(TestDbMeta meta) { - _log.LogInformation($"Creating database {_databaseName}"); + _log.LogInformation($"Creating database {meta.Name}"); using (var connection = new SqlConnection(_masterConnectionString)) { connection.Open(); using (var command = connection.CreateCommand()) { - SetCommand(command, $@"CREATE DATABASE {LocalDb.QuotedName(_databaseName)}"); - var unused = command.ExecuteNonQuery(); + SetCommand(command, $@"CREATE DATABASE {LocalDb.QuotedName(meta.Name)}"); + command.ExecuteNonQuery(); } } - - ConnectionString = ConstructConnectionString(_masterConnectionString, _databaseName); } private static string ConstructConnectionString(string masterConnectionString, string databaseName) @@ -116,7 +126,7 @@ namespace Umbraco.Tests.Integration.Testing } } - private void RebuildSchema(IDbCommand command) + private void RebuildSchema(IDbCommand command, TestDbMeta meta) { if (_cachedDatabaseInitCommands != null) { @@ -141,7 +151,7 @@ namespace Umbraco.Tests.Integration.Testing } else { - _databaseFactory.Configure(ConnectionString, Constants.DatabaseProviders.SqlServer); + _databaseFactory.Configure(meta.ConnectionString, Constants.DatabaseProviders.SqlServer); using (var database = (UmbracoDatabase)_databaseFactory.CreateDatabase()) { @@ -159,5 +169,120 @@ namespace Umbraco.Tests.Integration.Testing } } } + + private void Initialize() + { + _prepareQueue = new BlockingCollection(); + _readySchemaQueue = new BlockingCollection(); + _readyEmptyQueue = new BlockingCollection(); + + foreach (var meta in _testDatabases.Values) + { + CreateDatabase(meta); + _prepareQueue.Add(meta); + } + + for (var i = 0; i < _threadCount; i++) + { + var thread = new Thread(PrepareThread); + thread.Start(); + } + } + + private void Drop(TestDbMeta meta) + { + _log.LogInformation($"Dropping database {meta.Name}"); + using (var connection = new SqlConnection(_masterConnectionString)) + { + connection.Open(); + using (var command = connection.CreateCommand()) + { + SetCommand(command, $@" + ALTER DATABASE{LocalDb.QuotedName(meta.Name)} + SET SINGLE_USER + WITH ROLLBACK IMMEDIATE + "); + command.ExecuteNonQuery(); + + SetCommand(command, $@"DROP DATABASE {LocalDb.QuotedName(meta.Name)}"); + command.ExecuteNonQuery(); + } + } + } + + private void PrepareThread() + { + LocalDbTestDatabase.Retry(10, () => + { + while (_prepareQueue.IsCompleted == false) + { + TestDbMeta meta; + try + { + meta = _prepareQueue.Take(); + } + catch (InvalidOperationException) + { + continue; + } + + using (var conn = new SqlConnection(meta.ConnectionString)) + using (var cmd = conn.CreateCommand()) + { + conn.Open(); + LocalDbTestDatabase.ResetLocalDb(cmd); + + if (!meta.IsEmpty) + { + RebuildSchema(cmd, meta); + } + } + + if (!meta.IsEmpty) + { + _readySchemaQueue.TryAdd(meta); + } + else + { + _readyEmptyQueue.TryAdd(meta); + } + } + }); + } + + public void Finish() + { + if (_prepareQueue == null) + return; + + _prepareQueue.CompleteAdding(); + while (_prepareQueue.TryTake(out _)) { } + + _readyEmptyQueue.CompleteAdding(); + while (_readyEmptyQueue.TryTake(out _)) { } + + _readySchemaQueue.CompleteAdding(); + while (_readySchemaQueue.TryTake(out _)) { } + + foreach (var testDatabase in _testDatabases.Values) + { + Drop(testDatabase); + } + } + + private class TestDbMeta + { + public int Id { get; } + public string Name => $"{_databasePrefix}-{Id}"; + public bool IsEmpty { get; } + public string ConnectionString { get; } + + public TestDbMeta(int id, bool isEmpty, string masterConnectionString) + { + Id = id; + IsEmpty = isEmpty; + ConnectionString = ConstructConnectionString(masterConnectionString, Name); + } + } } } diff --git a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs index 9627fdf42a..a376aff38d 100644 --- a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs +++ b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs @@ -250,7 +250,7 @@ namespace Umbraco.Tests.Integration.Testing var databaseFactory = serviceProvider.GetRequiredService(); // This will create a db, install the schema and ensure the app is configured to run - InstallTestLocalDb(databaseFactory, TestHelper.ConsoleLoggerFactory, state, TestHelper.WorkingDirectory); + InstallTestLocalDb(databaseFactory, serviceProvider.GetRequiredService(), state, TestHelper.WorkingDirectory); TestDBConnectionString = databaseFactory.ConnectionString; InMemoryConfiguration["ConnectionStrings:" + Constants.System.UmbracoConnectionName] = TestDBConnectionString; } From 1b9d1428e6a2b16da21529c2f20e3d44238a2880 Mon Sep 17 00:00:00 2001 From: Paul Johnson Date: Fri, 11 Dec 2020 14:35:12 +0000 Subject: [PATCH 18/27] Update ci pipeline build definition --- build/azure-pipelines.yml | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/build/azure-pipelines.yml b/build/azure-pipelines.yml index 8a99f941b0..d301b9c461 100644 --- a/build/azure-pipelines.yml +++ b/build/azure-pipelines.yml @@ -8,6 +8,19 @@ # Variables & their default values variables: buildConfiguration: 'Release' + SA_PASSWORD: UmbracoIntegration123! + +resources: + containers: + - container: mssql + image: mcr.microsoft.com/mssql/server:2017-latest + env: + ACCEPT_EULA: Y + SA_PASSWORD: $(SA_PASSWORD) + MSSQL_PID: Developer + ports: + - 1433:1433 + options: --name mssql stages: - stage: Linux @@ -31,6 +44,28 @@ stages: command: test projects: '**/*.Tests.UnitTests.csproj' + - job: Integration_Tests + services: + mssql: mssql + timeoutInMinutes: 120 + displayName: 'Integration Tests' + pool: + vmImage: 'ubuntu-latest' + steps: + + - task: UseDotNet@2 + displayName: 'Use .Net Core sdk 3.1.x' + inputs: + version: 3.1.x + + - task: DotNetCoreCLI@2 + displayName: 'dotnet test' + inputs: + command: test + projects: '**/Umbraco.Tests.Integration.csproj' + env: + UmbracoIntegrationTestConnectionString: 'Server=localhost,1433;User Id=sa;Password=$(SA_PASSWORD);' + - stage: macOS_X dependsOn: [] # this removes the implicit dependency on previous stage and causes this to run in parallel jobs: @@ -52,7 +87,6 @@ stages: command: test projects: '**/*.Tests.UnitTests.csproj' - - stage: Windows dependsOn: [] # this removes the implicit dependency on previous stage and causes this to run in parallel jobs: @@ -74,7 +108,6 @@ stages: command: test projects: '**\*.Tests.UnitTests.csproj' - - job: Integration_Tests timeoutInMinutes: 120 displayName: 'Integration Tests' @@ -102,7 +135,6 @@ stages: projects: '**\Umbraco.Tests.Integration.csproj' arguments: '--no-build' - - job: Build_Artifacts displayName: 'Build Artifacts' pool: From ae98983172418d0a0f3e8b12ccb45bfb014bca6d Mon Sep 17 00:00:00 2001 From: Paul Johnson Date: Fri, 11 Dec 2020 16:44:27 +0000 Subject: [PATCH 19/27] Fix PathTests --- .../Repositories/PartialViewRepositoryTests.cs | 11 ++++++----- .../Persistence/Repositories/ScriptRepositoryTest.cs | 12 ++++++------ .../Repositories/StylesheetRepositoryTest.cs | 12 ++++++------ 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/PartialViewRepositoryTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/PartialViewRepositoryTests.cs index 1ae46faa76..ffda46ed0d 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/PartialViewRepositoryTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/PartialViewRepositoryTests.cs @@ -7,6 +7,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Tests.Testing; using System; +using System.IO; using Umbraco.Core.Hosting; using Umbraco.Tests.Integration.Testing; @@ -55,28 +56,28 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Persistence.Repositor partialView = new PartialView(PartialViewType.PartialView, "path-2/test-path-2.cshtml") { Content = "// partialView" }; repository.Save(partialView); Assert.IsTrue(_fileSystem.FileExists("path-2/test-path-2.cshtml")); - Assert.AreEqual("path-2\\test-path-2.cshtml", partialView.Path); // fixed in 7.3 - 7.2.8 does not update the path + Assert.AreEqual("path-2\\test-path-2.cshtml".Replace("\\", $"{Path.DirectorySeparatorChar}"), partialView.Path); // fixed in 7.3 - 7.2.8 does not update the path Assert.AreEqual("/Views/Partials/path-2/test-path-2.cshtml", partialView.VirtualPath); partialView = (PartialView) repository.Get("path-2/test-path-2.cshtml"); Assert.IsNotNull(partialView); - Assert.AreEqual("path-2\\test-path-2.cshtml", partialView.Path); + Assert.AreEqual("path-2\\test-path-2.cshtml".Replace("\\", $"{Path.DirectorySeparatorChar}"), partialView.Path); Assert.AreEqual("/Views/Partials/path-2/test-path-2.cshtml", partialView.VirtualPath); partialView = new PartialView(PartialViewType.PartialView, "path-2\\test-path-3.cshtml") { Content = "// partialView" }; repository.Save(partialView); Assert.IsTrue(_fileSystem.FileExists("path-2/test-path-3.cshtml")); - Assert.AreEqual("path-2\\test-path-3.cshtml", partialView.Path); + Assert.AreEqual("path-2\\test-path-3.cshtml".Replace("\\", $"{Path.DirectorySeparatorChar}"), partialView.Path); Assert.AreEqual("/Views/Partials/path-2/test-path-3.cshtml", partialView.VirtualPath); partialView = (PartialView) repository.Get("path-2/test-path-3.cshtml"); Assert.IsNotNull(partialView); - Assert.AreEqual("path-2\\test-path-3.cshtml", partialView.Path); + Assert.AreEqual("path-2\\test-path-3.cshtml".Replace("\\", $"{Path.DirectorySeparatorChar}"), partialView.Path); Assert.AreEqual("/Views/Partials/path-2/test-path-3.cshtml", partialView.VirtualPath); partialView = (PartialView) repository.Get("path-2\\test-path-3.cshtml"); Assert.IsNotNull(partialView); - Assert.AreEqual("path-2\\test-path-3.cshtml", partialView.Path); + Assert.AreEqual("path-2\\test-path-3.cshtml".Replace("\\", $"{Path.DirectorySeparatorChar}"), partialView.Path); Assert.AreEqual("/Views/Partials/path-2/test-path-3.cshtml", partialView.VirtualPath); partialView = new PartialView(PartialViewType.PartialView, "\\test-path-4.cshtml") { Content = "// partialView" }; diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/ScriptRepositoryTest.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/ScriptRepositoryTest.cs index 9e4ae80ec6..f9084332b7 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/ScriptRepositoryTest.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/ScriptRepositoryTest.cs @@ -280,36 +280,36 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Persistence.Repositor repository.Save(script); Assert.IsTrue(_fileSystem.FileExists("scripts/path-2/test-path-2.js")); - Assert.AreEqual("scripts\\path-2\\test-path-2.js", script.Path); + Assert.AreEqual("scripts\\path-2\\test-path-2.js".Replace("\\", $"{Path.DirectorySeparatorChar}"), script.Path); Assert.AreEqual("/scripts/scripts/path-2/test-path-2.js", script.VirtualPath); script = new Script("path-2/test-path-2.js") { Content = "// script" }; repository.Save(script); Assert.IsTrue(_fileSystem.FileExists("path-2/test-path-2.js")); - Assert.AreEqual("path-2\\test-path-2.js", script.Path); // fixed in 7.3 - 7.2.8 does not update the path + Assert.AreEqual("path-2\\test-path-2.js".Replace("\\", $"{Path.DirectorySeparatorChar}"), script.Path);// fixed in 7.3 - 7.2.8 does not update the path Assert.AreEqual("/scripts/path-2/test-path-2.js", script.VirtualPath); script = repository.Get("path-2/test-path-2.js"); Assert.IsNotNull(script); - Assert.AreEqual("path-2\\test-path-2.js", script.Path); + Assert.AreEqual("path-2\\test-path-2.js".Replace("\\", $"{Path.DirectorySeparatorChar}"), script.Path); Assert.AreEqual("/scripts/path-2/test-path-2.js", script.VirtualPath); script = new Script("path-2\\test-path-3.js") { Content = "// script" }; repository.Save(script); Assert.IsTrue(_fileSystem.FileExists("path-2/test-path-3.js")); - Assert.AreEqual("path-2\\test-path-3.js", script.Path); + Assert.AreEqual("path-2\\test-path-3.js".Replace("\\", $"{Path.DirectorySeparatorChar}"), script.Path); Assert.AreEqual("/scripts/path-2/test-path-3.js", script.VirtualPath); script = repository.Get("path-2/test-path-3.js"); Assert.IsNotNull(script); - Assert.AreEqual("path-2\\test-path-3.js", script.Path); + Assert.AreEqual("path-2\\test-path-3.js".Replace("\\", $"{Path.DirectorySeparatorChar}"), script.Path); Assert.AreEqual("/scripts/path-2/test-path-3.js", script.VirtualPath); script = repository.Get("path-2\\test-path-3.js"); Assert.IsNotNull(script); - Assert.AreEqual("path-2\\test-path-3.js", script.Path); + Assert.AreEqual("path-2\\test-path-3.js".Replace("\\", $"{Path.DirectorySeparatorChar}"), script.Path); Assert.AreEqual("/scripts/path-2/test-path-3.js", script.VirtualPath); script = new Script("\\test-path-4.js") { Content = "// script" }; diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/StylesheetRepositoryTest.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/StylesheetRepositoryTest.cs index a576666e6e..b4b8316f83 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/StylesheetRepositoryTest.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/StylesheetRepositoryTest.cs @@ -135,7 +135,7 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Persistence.Repositor stylesheet = repository.Get(stylesheet.Name); //Assert - Assert.That(stylesheet.Content, Is.EqualTo("body { color:#000; } .bold {font-weight:bold;}\r\n\r\n/**umb_name:Test*/\r\np {\r\n\tfont-size:2em;\r\n}")); + Assert.That(stylesheet.Content, Is.EqualTo("body { color:#000; } .bold {font-weight:bold;}\r\n\r\n/**umb_name:Test*/\r\np {\r\n\tfont-size:2em;\r\n}".Replace("\r\n", Environment.NewLine))); Assert.AreEqual(1, stylesheet.Properties.Count()); } } @@ -281,29 +281,29 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Persistence.Repositor repository.Save(stylesheet); Assert.IsTrue(_fileSystem.FileExists("path-2/test-path-2.css")); - Assert.AreEqual("path-2\\test-path-2.css", stylesheet.Path); // fixed in 7.3 - 7.2.8 does not update the path + Assert.AreEqual("path-2\\test-path-2.css".Replace("\\", $"{Path.DirectorySeparatorChar}"), stylesheet.Path);// fixed in 7.3 - 7.2.8 does not update the path Assert.AreEqual("/css/path-2/test-path-2.css", stylesheet.VirtualPath); stylesheet = repository.Get("path-2/test-path-2.css"); Assert.IsNotNull(stylesheet); - Assert.AreEqual("path-2\\test-path-2.css", stylesheet.Path); + Assert.AreEqual("path-2\\test-path-2.css".Replace("\\", $"{Path.DirectorySeparatorChar}"), stylesheet.Path); Assert.AreEqual("/css/path-2/test-path-2.css", stylesheet.VirtualPath); stylesheet = new Stylesheet("path-2\\test-path-3.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; repository.Save(stylesheet); Assert.IsTrue(_fileSystem.FileExists("path-2/test-path-3.css")); - Assert.AreEqual("path-2\\test-path-3.css", stylesheet.Path); + Assert.AreEqual("path-2\\test-path-3.css".Replace("\\", $"{Path.DirectorySeparatorChar}"), stylesheet.Path); Assert.AreEqual("/css/path-2/test-path-3.css", stylesheet.VirtualPath); stylesheet = repository.Get("path-2/test-path-3.css"); Assert.IsNotNull(stylesheet); - Assert.AreEqual("path-2\\test-path-3.css", stylesheet.Path); + Assert.AreEqual("path-2\\test-path-3.css".Replace("\\", $"{Path.DirectorySeparatorChar}"), stylesheet.Path); Assert.AreEqual("/css/path-2/test-path-3.css", stylesheet.VirtualPath); stylesheet = repository.Get("path-2\\test-path-3.css"); Assert.IsNotNull(stylesheet); - Assert.AreEqual("path-2\\test-path-3.css", stylesheet.Path); + Assert.AreEqual("path-2\\test-path-3.css".Replace("\\", $"{Path.DirectorySeparatorChar}"), stylesheet.Path); Assert.AreEqual("/css/path-2/test-path-3.css", stylesheet.VirtualPath); stylesheet = new Stylesheet("\\test-path-4.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" }; From 312ab962779e75fd4ea6f00c3359cf35105eafff Mon Sep 17 00:00:00 2001 From: Paul Johnson Date: Fri, 11 Dec 2020 18:20:07 +0000 Subject: [PATCH 20/27] Resolve issues with AdvancedMigrationTests --- .../Persistence/UmbracoDatabaseFactory.cs | 11 ----- .../UmbracoTestServerTestBase.cs | 3 +- .../Testing/SqlDeveloperTestDatabase.cs | 3 +- .../Testing/TestDatabaseFactory.cs | 6 +-- .../TestUmbracoDatabaseFactoryProvider.cs | 48 +++++++++++++++++++ .../Testing/UmbracoIntegrationTest.cs | 22 ++++----- 6 files changed, 64 insertions(+), 29 deletions(-) create mode 100644 src/Umbraco.Tests.Integration/Testing/TestUmbracoDatabaseFactoryProvider.cs diff --git a/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs b/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs index 7b98bd150e..5c3c984677 100644 --- a/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs +++ b/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs @@ -327,16 +327,5 @@ namespace Umbraco.Core.Persistence //db?.Dispose(); Volatile.Write(ref _initialized, false); } - - // during tests, the thread static var can leak between tests - // this method provides a way to force-reset the variable - internal void ResetForTests() - { - // TODO: remove all this eventually - //var db = _umbracoDatabaseAccessor.UmbracoDatabase; - //_umbracoDatabaseAccessor.UmbracoDatabase = null; - //db?.Dispose(); - //_databaseScopeAccessor.Scope = null; - } } } diff --git a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs index d60f49971a..93769eaaed 100644 --- a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs +++ b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs @@ -132,11 +132,12 @@ namespace Umbraco.Tests.Integration.TestServerTest public override void ConfigureServices(IServiceCollection services) { + services.AddTransient(); var typeLoader = services.AddTypeLoader(GetType().Assembly, TestHelper.GetWebHostEnvironment(), TestHelper.GetHostingEnvironment(), TestHelper.ConsoleLoggerFactory, AppCaches.NoCache, Configuration, TestHelper.Profiler); var builder = new UmbracoBuilder(services, Configuration, typeLoader); - + builder .AddConfiguration() .AddTestCore(TestHelper) // This is the important one! diff --git a/src/Umbraco.Tests.Integration/Testing/SqlDeveloperTestDatabase.cs b/src/Umbraco.Tests.Integration/Testing/SqlDeveloperTestDatabase.cs index 560bcbe00a..52be6d5472 100644 --- a/src/Umbraco.Tests.Integration/Testing/SqlDeveloperTestDatabase.cs +++ b/src/Umbraco.Tests.Integration/Testing/SqlDeveloperTestDatabase.cs @@ -31,7 +31,7 @@ namespace Umbraco.Tests.Integration.Testing private readonly IUmbracoDatabaseFactory _databaseFactory; private readonly IDictionary _testDatabases; private UmbracoDatabase.CommandInfo[] _cachedDatabaseInitCommands; - + private BlockingCollection _prepareQueue; private BlockingCollection _readySchemaQueue; private BlockingCollection _readyEmptyQueue; @@ -54,7 +54,6 @@ namespace Umbraco.Tests.Integration.Testing new TestDbMeta(2, false, masterConnectionString), new TestDbMeta(3, true, masterConnectionString), - new TestDbMeta(4, true, masterConnectionString), }.ToDictionary(x => x.Id); Instance = this; // For GlobalSetupTeardown.cs diff --git a/src/Umbraco.Tests.Integration/Testing/TestDatabaseFactory.cs b/src/Umbraco.Tests.Integration/Testing/TestDatabaseFactory.cs index 0f403818b7..3ed2b6b49a 100644 --- a/src/Umbraco.Tests.Integration/Testing/TestDatabaseFactory.cs +++ b/src/Umbraco.Tests.Integration/Testing/TestDatabaseFactory.cs @@ -7,11 +7,11 @@ namespace Umbraco.Tests.Integration.Testing { public class TestDatabaseFactory { - public static ITestDatabase Create(string filesPath, ILoggerFactory loggerFactory, IUmbracoDatabaseFactory dbFactory) + public static ITestDatabase Create(string filesPath, ILoggerFactory loggerFactory, TestUmbracoDatabaseFactoryProvider dbFactory) { return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) - ? CreateLocalDb(filesPath, loggerFactory, dbFactory) - : CreateSqlDeveloper(loggerFactory, dbFactory); + ? CreateLocalDb(filesPath, loggerFactory, dbFactory.Create()) + : CreateSqlDeveloper(loggerFactory, dbFactory.Create()); } private static ITestDatabase CreateLocalDb(string filesPath, ILoggerFactory loggerFactory, IUmbracoDatabaseFactory dbFactory) diff --git a/src/Umbraco.Tests.Integration/Testing/TestUmbracoDatabaseFactoryProvider.cs b/src/Umbraco.Tests.Integration/Testing/TestUmbracoDatabaseFactoryProvider.cs new file mode 100644 index 0000000000..3eb3757207 --- /dev/null +++ b/src/Umbraco.Tests.Integration/Testing/TestUmbracoDatabaseFactoryProvider.cs @@ -0,0 +1,48 @@ +using System; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.Mappers; + +namespace Umbraco.Tests.Integration.Testing +{ + /// + /// I want to be able to create a database for integration testsing without setting the connection string on the + /// singleton database factory forever. + /// + public class TestUmbracoDatabaseFactoryProvider + { + private readonly ILoggerFactory _loggerFactory; + private readonly IOptions _globalSettings; + private readonly IOptions _connectionStrings; + private readonly Lazy _mappers; + private readonly IDbProviderFactoryCreator _dbProviderFactoryCreator; + + public TestUmbracoDatabaseFactoryProvider( + ILoggerFactory loggerFactory, + IOptions globalSettings, + IOptions connectionStrings, + Lazy mappers, + IDbProviderFactoryCreator dbProviderFactoryCreator) + { + _loggerFactory = loggerFactory; + _globalSettings = globalSettings; + _connectionStrings = connectionStrings; + _mappers = mappers; + _dbProviderFactoryCreator = dbProviderFactoryCreator; + } + + public IUmbracoDatabaseFactory Create() + { + // ReSharper disable once ArrangeMethodOrOperatorBody + return new UmbracoDatabaseFactory( + _loggerFactory.CreateLogger(), + _loggerFactory, + _globalSettings.Value, + _connectionStrings.Value, + _mappers, + _dbProviderFactoryCreator); + } + } +} diff --git a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs index a376aff38d..3da4ec94d6 100644 --- a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs +++ b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs @@ -165,6 +165,7 @@ namespace Umbraco.Tests.Integration.Testing public virtual void ConfigureServices(IServiceCollection services) { services.AddSingleton(TestHelper.DbProviderFactoryCreator); + services.AddTransient(); var webHostEnvironment = TestHelper.GetWebHostEnvironment(); services.AddRequiredNetCoreServices(TestHelper, webHostEnvironment); @@ -247,10 +248,11 @@ namespace Umbraco.Tests.Integration.Testing protected void UseTestLocalDb(IServiceProvider serviceProvider) { var state = serviceProvider.GetRequiredService(); + var testDatabaseFactoryProvider = serviceProvider.GetRequiredService(); var databaseFactory = serviceProvider.GetRequiredService(); // This will create a db, install the schema and ensure the app is configured to run - InstallTestLocalDb(databaseFactory, serviceProvider.GetRequiredService(), state, TestHelper.WorkingDirectory); + InstallTestLocalDb(testDatabaseFactoryProvider, databaseFactory, serviceProvider.GetRequiredService(), state, TestHelper.WorkingDirectory); TestDBConnectionString = databaseFactory.ConnectionString; InMemoryConfiguration["ConnectionStrings:" + Constants.System.UmbracoConnectionName] = TestDBConnectionString; } @@ -267,7 +269,7 @@ namespace Umbraco.Tests.Integration.Testing /// /// There must only be ONE instance shared between all tests in a session /// - private static ITestDatabase GetOrCreateDatabase(string filesPath, ILoggerFactory loggerFactory, IUmbracoDatabaseFactory dbFactory) + private static ITestDatabase GetOrCreateDatabase(string filesPath, ILoggerFactory loggerFactory, TestUmbracoDatabaseFactoryProvider dbFactory) { lock (_dbLocker) { @@ -282,16 +284,12 @@ namespace Umbraco.Tests.Integration.Testing /// /// Creates a LocalDb instance to use for the test /// - /// - /// - /// - /// - /// - /// - /// private void InstallTestLocalDb( - IUmbracoDatabaseFactory databaseFactory, ILoggerFactory loggerFactory, - IRuntimeState runtimeState, string workingDirectory) + TestUmbracoDatabaseFactoryProvider testUmbracoDatabaseFactoryProvider, + IUmbracoDatabaseFactory databaseFactory, + ILoggerFactory loggerFactory, + IRuntimeState runtimeState, + string workingDirectory) { var dbFilePath = Path.Combine(workingDirectory, "LocalDb"); @@ -307,7 +305,7 @@ namespace Umbraco.Tests.Integration.Testing if (!Directory.Exists(dbFilePath)) Directory.CreateDirectory(dbFilePath); - var db = GetOrCreateDatabase(dbFilePath, loggerFactory, databaseFactory); + var db = GetOrCreateDatabase(dbFilePath, loggerFactory, testUmbracoDatabaseFactoryProvider); switch (testOptions.Database) { From 4dbe5d0c3888c664c0152eb08bbfdc78f72f2953 Mon Sep 17 00:00:00 2001 From: Paul Johnson Date: Sat, 12 Dec 2020 11:33:57 +0000 Subject: [PATCH 21/27] Consolidate LocalDbTestDatabase and SqlDeveloperTestDatabase Resolve issue with multiple empties --- .../GlobalSetupTeardown.cs | 4 +- .../Testing/BaseTestDatabase.cs | 218 +++++++++++ .../Testing/ITestDatabase.cs | 9 +- .../Testing/LocalDbTestDatabase.cs | 351 ++++-------------- .../Testing/SqlDeveloperTestDatabase.cs | 218 ++--------- .../Testing/TestDatabaseFactory.cs | 5 +- .../Testing/TestDbMeta.cs | 39 ++ .../Testing/UmbracoIntegrationTest.cs | 31 +- .../TestHelpers/TestWithDatabaseBase.cs | 3 +- 9 files changed, 367 insertions(+), 511 deletions(-) create mode 100644 src/Umbraco.Tests.Integration/Testing/BaseTestDatabase.cs create mode 100644 src/Umbraco.Tests.Integration/Testing/TestDbMeta.cs diff --git a/src/Umbraco.Tests.Integration/GlobalSetupTeardown.cs b/src/Umbraco.Tests.Integration/GlobalSetupTeardown.cs index 0fdac242d9..6e86e97770 100644 --- a/src/Umbraco.Tests.Integration/GlobalSetupTeardown.cs +++ b/src/Umbraco.Tests.Integration/GlobalSetupTeardown.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; @@ -23,7 +23,7 @@ public class TestsSetup [OneTimeTearDown] public void TearDown() { - LocalDbTestDatabase.KillLocalDb(); + LocalDbTestDatabase.Instance?.Finish(); SqlDeveloperTestDatabase.Instance?.Finish(); Console.WriteLine("TOTAL TESTS DURATION: {0}", _stopwatch.Elapsed); } diff --git a/src/Umbraco.Tests.Integration/Testing/BaseTestDatabase.cs b/src/Umbraco.Tests.Integration/Testing/BaseTestDatabase.cs new file mode 100644 index 0000000000..02a3da676a --- /dev/null +++ b/src/Umbraco.Tests.Integration/Testing/BaseTestDatabase.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using Microsoft.Extensions.Logging; +using Umbraco.Core.Configuration; +using Umbraco.Core.Migrations.Install; +using Umbraco.Core.Persistence; + +namespace Umbraco.Tests.Integration.Testing +{ + public abstract class BaseTestDatabase + { + protected ILoggerFactory _loggerFactory; + protected IUmbracoDatabaseFactory _databaseFactory; + protected IEnumerable _testDatabases; + + protected UmbracoDatabase.CommandInfo[] _cachedDatabaseInitCommands; + + protected BlockingCollection _prepareQueue; + protected BlockingCollection _readySchemaQueue; + protected BlockingCollection _readyEmptyQueue; + + protected abstract void Initialize(); + + public TestDbMeta AttachEmpty() + { + if (_prepareQueue == null) + { + Initialize(); + } + + return _readyEmptyQueue.Take(); + } + + public TestDbMeta AttachSchema() + { + if (_prepareQueue == null) + { + Initialize(); + } + + return _readySchemaQueue.Take(); + } + + public void Detach(TestDbMeta meta) + { + _prepareQueue.TryAdd(meta); + } + + protected void PrepareDatabase() + { + Retry(10, () => + { + while (_prepareQueue.IsCompleted == false) + { + TestDbMeta meta; + try + { + meta = _prepareQueue.Take(); + } + catch (InvalidOperationException) + { + continue; + } + + using (var conn = new SqlConnection(meta.ConnectionString)) + using (var cmd = conn.CreateCommand()) + { + conn.Open(); + ResetTestDatabase(cmd); + + if (!meta.IsEmpty) + { + RebuildSchema(cmd, meta); + } + } + + if (!meta.IsEmpty) + { + _readySchemaQueue.TryAdd(meta); + } + else + { + _readyEmptyQueue.TryAdd(meta); + } + } + }); + } + + protected void RebuildSchema(IDbCommand command, TestDbMeta meta) + { + if (_cachedDatabaseInitCommands != null) + { + foreach (var dbCommand in _cachedDatabaseInitCommands) + { + + if (dbCommand.Text.StartsWith("SELECT ")) + { + continue; + } + + command.CommandText = dbCommand.Text; + command.Parameters.Clear(); + + foreach (var parameterInfo in dbCommand.Parameters) + { + AddParameter(command, parameterInfo); + } + + command.ExecuteNonQuery(); + } + } + else + { + _databaseFactory.Configure(meta.ConnectionString, Core.Constants.DatabaseProviders.SqlServer); + + using (var database = (UmbracoDatabase)_databaseFactory.CreateDatabase()) + { + database.LogCommands = true; + + using (var transaction = database.GetTransaction()) + { + var schemaCreator = new DatabaseSchemaCreator(database, _loggerFactory.CreateLogger(), _loggerFactory, new UmbracoVersion()); + schemaCreator.InitializeDatabaseSchema(); + + transaction.Complete(); + + _cachedDatabaseInitCommands = database.Commands.ToArray(); + } + } + } + } + + protected static void SetCommand(SqlCommand command, string sql, params object[] args) + { + command.CommandType = CommandType.Text; + command.CommandText = sql; + command.Parameters.Clear(); + + for (var i = 0; i < args.Length; i++) + { + command.Parameters.AddWithValue("@" + i, args[i]); + } + } + + protected static void AddParameter(IDbCommand cmd, UmbracoDatabase.ParameterInfo parameterInfo) + { + var p = cmd.CreateParameter(); + p.ParameterName = parameterInfo.Name; + p.Value = parameterInfo.Value; + p.DbType = parameterInfo.DbType; + p.Size = parameterInfo.Size; + cmd.Parameters.Add(p); + } + + protected static void ResetTestDatabase(IDbCommand cmd) + { + // https://stackoverflow.com/questions/536350 + + cmd.CommandType = CommandType.Text; + cmd.CommandText = @" + declare @n char(1); + set @n = char(10); + declare @stmt nvarchar(max); + -- check constraints + select @stmt = isnull( @stmt + @n, '' ) + + 'alter table [' + schema_name(schema_id) + '].[' + object_name( parent_object_id ) + '] drop constraint [' + name + ']' + from sys.check_constraints; + -- foreign keys + select @stmt = isnull( @stmt + @n, '' ) + + 'alter table [' + schema_name(schema_id) + '].[' + object_name( parent_object_id ) + '] drop constraint [' + name + ']' + from sys.foreign_keys; + -- tables + select @stmt = isnull( @stmt + @n, '' ) + + 'drop table [' + schema_name(schema_id) + '].[' + name + ']' + from sys.tables; + exec sp_executesql @stmt; + "; + + // rudimentary retry policy since a db can still be in use when we try to drop + Retry(10, () => cmd.ExecuteNonQuery()); + } + + protected static void Retry(int maxIterations, Action action) + { + for (var i = 0; i < maxIterations; i++) + { + try + { + action(); + return; + } + catch (SqlException) + { + + //Console.Error.WriteLine($"SqlException occured, but we try again {i+1}/{maxIterations}.\n{e}"); + // This can occur when there's a transaction deadlock which means (i think) that the database is still in use and hasn't been closed properly yet + // so we need to just wait a little bit + Thread.Sleep(100 * i); + if (i == maxIterations - 1) + { + Debugger.Launch(); + throw; + } + } + catch (InvalidOperationException) + { + // Ignore + } + } + } + } +} diff --git a/src/Umbraco.Tests.Integration/Testing/ITestDatabase.cs b/src/Umbraco.Tests.Integration/Testing/ITestDatabase.cs index 250e062ee4..28d7e9c8bc 100644 --- a/src/Umbraco.Tests.Integration/Testing/ITestDatabase.cs +++ b/src/Umbraco.Tests.Integration/Testing/ITestDatabase.cs @@ -1,10 +1,9 @@ -namespace Umbraco.Tests.Integration.Testing +namespace Umbraco.Tests.Integration.Testing { public interface ITestDatabase { - string ConnectionString { get; } - int AttachEmpty(); - int AttachSchema(); - void Detach(int id); + TestDbMeta AttachEmpty(); + TestDbMeta AttachSchema(); + void Detach(TestDbMeta id); } } diff --git a/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs b/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs index 0a081f48e9..a9a842cdcd 100644 --- a/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs +++ b/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs @@ -1,18 +1,8 @@ -using System; +using System; using System.Collections.Concurrent; -using System.Configuration; -using System.Data; -using System.Data.Common; -using System.Data.SqlClient; -using System.Diagnostics; using System.IO; -using System.Linq; using System.Threading; using Microsoft.Extensions.Logging; -using Umbraco.Core; -using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; -using Umbraco.Core.Migrations.Install; using Umbraco.Core.Persistence; namespace Umbraco.Tests.Integration.Testing @@ -20,181 +10,104 @@ namespace Umbraco.Tests.Integration.Testing /// /// Manages a pool of LocalDb databases for integration testing /// - public class LocalDbTestDatabase : ITestDatabase + public class LocalDbTestDatabase : BaseTestDatabase, ITestDatabase { public const string InstanceName = "UmbracoTests"; public const string DatabaseName = "UmbracoTests"; - private readonly ILoggerFactory _loggerFactory; private readonly LocalDb _localDb; - private readonly IUmbracoVersion _umbracoVersion; - private static LocalDb.Instance _instance; + private static LocalDb.Instance _localDbInstance; private static string _filesPath; - private readonly IUmbracoDatabaseFactory _dbFactory; - private UmbracoDatabase.CommandInfo[] _dbCommands; - private string _currentCstr; - private static DatabasePool _emptyPool; - private static DatabasePool _schemaPool; - private DatabasePool _currentPool; + + private const int _threadCount = 2; + + public static LocalDbTestDatabase Instance { get; private set; } //It's internal because `Umbraco.Core.Persistence.LocalDb` is internal internal LocalDbTestDatabase(ILoggerFactory loggerFactory, LocalDb localDb, string filesPath, IUmbracoDatabaseFactory dbFactory) { - _umbracoVersion = new UmbracoVersion(); _loggerFactory = loggerFactory; + _databaseFactory = dbFactory; + _localDb = localDb; _filesPath = filesPath; - _dbFactory = dbFactory; - _instance = _localDb.GetInstance(InstanceName); - if (_instance != null) return; + Instance = this; // For GlobalSetupTeardown.cs + + _testDatabases = new[] + { + // With Schema + TestDbMeta.CreateWithoutConnectionString($"{DatabaseName}-1", false), + TestDbMeta.CreateWithoutConnectionString($"{DatabaseName}-2", false), + + // Empty (for migration testing etc) + TestDbMeta.CreateWithoutConnectionString($"{DatabaseName}-3", true), + TestDbMeta.CreateWithoutConnectionString($"{DatabaseName}-4", true), + }; + + _localDbInstance = _localDb.GetInstance(InstanceName); + if (_localDbInstance != null) + { + return; + } if (_localDb.CreateInstance(InstanceName) == false) + { throw new Exception("Failed to create a LocalDb instance."); - _instance = _localDb.GetInstance(InstanceName); + } + + _localDbInstance = _localDb.GetInstance(InstanceName); } - public string ConnectionString => _currentCstr ?? _instance.GetAttachedConnectionString("XXXXXX", _filesPath); - - private void Create() + protected override void Initialize() { var tempName = Guid.NewGuid().ToString("N"); - _instance.CreateDatabase(tempName, _filesPath); - _instance.DetachDatabase(tempName); + _localDbInstance.CreateDatabase(tempName, _filesPath); + _localDbInstance.DetachDatabase(tempName); + _prepareQueue = new BlockingCollection(); + _readySchemaQueue = new BlockingCollection(); + _readyEmptyQueue = new BlockingCollection(); - // there's probably a sweet spot to be found for size / parallel... - - var s = ConfigurationManager.AppSettings["Umbraco.Tests.LocalDbTestDatabase.EmptyPoolSize"]; - var emptySize = s == null ? 1 : int.Parse(s); - s = ConfigurationManager.AppSettings["Umbraco.Tests.LocalDbTestDatabase.EmptyPoolThreadCount"]; - var emptyParallel = s == null ? 1 : int.Parse(s); - s = ConfigurationManager.AppSettings["Umbraco.Tests.LocalDbTestDatabase.SchemaPoolSize"]; - var schemaSize = s == null ? 1 : int.Parse(s); - s = ConfigurationManager.AppSettings["Umbraco.Tests.LocalDbTestDatabase.SchemaPoolThreadCount"]; - var schemaParallel = s == null ? 1 : int.Parse(s); - - _emptyPool = new DatabasePool(_localDb, _instance, DatabaseName + "-Empty", tempName, _filesPath, emptySize, emptyParallel); - _schemaPool = new DatabasePool(_localDb, _instance, DatabaseName + "-Schema", tempName, _filesPath, schemaSize, schemaParallel, delete: true, prepare: RebuildSchema); - } - - public int AttachEmpty() - { - if (_emptyPool == null) - Create(); - - _currentCstr = _emptyPool.AttachDatabase(out var id); - _currentPool = _emptyPool; - return id; - } - - public int AttachSchema() - { - if (_schemaPool == null) - Create(); - - _currentCstr = _schemaPool.AttachDatabase(out var id); - _currentPool = _schemaPool; - return id; - } - - public void Detach(int id) - { - _currentPool.DetachDatabase(id); - } - - private void RebuildSchema(DbConnection conn, IDbCommand cmd) - { - - if (_dbCommands != null) + foreach (var meta in _testDatabases) { - foreach (var dbCommand in _dbCommands) - { - - if (dbCommand.Text.StartsWith("SELECT ")) continue; - - cmd.CommandText = dbCommand.Text; - cmd.Parameters.Clear(); - foreach (var parameterInfo in dbCommand.Parameters) - AddParameter(cmd, parameterInfo); - cmd.ExecuteNonQuery(); - } - } - else - { - _dbFactory.Configure(conn.ConnectionString, Constants.DatabaseProviders.SqlServer); - - using var database = (UmbracoDatabase)_dbFactory.CreateDatabase(); - // track each db command ran as part of creating the database so we can replay these - database.LogCommands = true; - - using var trans = database.GetTransaction(); - - var creator = new DatabaseSchemaCreator(database, _loggerFactory.CreateLogger(), _loggerFactory, _umbracoVersion); - creator.InitializeDatabaseSchema(); - - trans.Complete(); // commit it - - _dbCommands = database.Commands.ToArray(); + _localDb.CopyDatabaseFiles(tempName, _filesPath, targetDatabaseName: meta.Name, overwrite: true, delete: false); + meta.ConnectionString = _localDbInstance.GetAttachedConnectionString(meta.Name, _filesPath); + _prepareQueue.Add(meta); } - } - - internal static void AddParameter(IDbCommand cmd, UmbracoDatabase.ParameterInfo parameterInfo) - { - var p = cmd.CreateParameter(); - p.ParameterName = parameterInfo.Name; - p.Value = parameterInfo.Value; - p.DbType = parameterInfo.DbType; - p.Size = parameterInfo.Size; - cmd.Parameters.Add(p); - } - - - internal static void ResetLocalDb(IDbCommand cmd) - { - // https://stackoverflow.com/questions/536350 - - cmd.CommandType = CommandType.Text; - cmd.CommandText = @" - declare @n char(1); - set @n = char(10); - declare @stmt nvarchar(max); - -- check constraints - select @stmt = isnull( @stmt + @n, '' ) + - 'alter table [' + schema_name(schema_id) + '].[' + object_name( parent_object_id ) + '] drop constraint [' + name + ']' - from sys.check_constraints; - -- foreign keys - select @stmt = isnull( @stmt + @n, '' ) + - 'alter table [' + schema_name(schema_id) + '].[' + object_name( parent_object_id ) + '] drop constraint [' + name + ']' - from sys.foreign_keys; - -- tables - select @stmt = isnull( @stmt + @n, '' ) + - 'drop table [' + schema_name(schema_id) + '].[' + name + ']' - from sys.tables; - exec sp_executesql @stmt; - "; - - // rudimentary retry policy since a db can still be in use when we try to drop - Retry(10, () => + for (var i = 0; i < _threadCount; i++) { - cmd.ExecuteNonQuery(); - }); + var thread = new Thread(PrepareDatabase); + thread.Start(); + } } - public static void KillLocalDb() + public void Finish() { - _emptyPool?.Stop(); - _schemaPool?.Stop(); + if (_prepareQueue == null) + return; + + _prepareQueue.CompleteAdding(); + while (_prepareQueue.TryTake(out _)) + { } + + _readyEmptyQueue.CompleteAdding(); + while (_readyEmptyQueue.TryTake(out _)) + { } + + _readySchemaQueue.CompleteAdding(); + while (_readySchemaQueue.TryTake(out _)) + { } if (_filesPath == null) return; var filename = Path.Combine(_filesPath, DatabaseName).ToUpper(); - foreach (var database in _instance.GetDatabases()) + foreach (var database in _localDbInstance.GetDatabases()) { if (database.StartsWith(filename)) - _instance.DropDatabase(database); + _localDbInstance.DropDatabase(database); } foreach (var file in Directory.EnumerateFiles(_filesPath)) @@ -210,145 +123,5 @@ namespace Umbraco.Tests.Integration.Testing } } } - - internal static void Retry(int maxIterations, Action action) - { - for (var i = 0; i < maxIterations; i++) - { - try - { - action(); - return; - } - catch (SqlException) - { - - //Console.Error.WriteLine($"SqlException occured, but we try again {i+1}/{maxIterations}.\n{e}"); - // This can occur when there's a transaction deadlock which means (i think) that the database is still in use and hasn't been closed properly yet - // so we need to just wait a little bit - Thread.Sleep(100 * i); - if (i == maxIterations - 1) - { - Debugger.Launch(); - throw; - } - } - catch (InvalidOperationException) - { - - } - } - } - - private class DatabasePool - { - private readonly LocalDb _localDb; - private readonly LocalDb.Instance _instance; - private readonly string _filesPath; - private readonly string _name; - private readonly int _size; - private readonly string[] _cstrs; - private readonly BlockingCollection _prepareQueue, _readyQueue; - private readonly Action _prepare; - private int _current; - - public DatabasePool(LocalDb localDb, LocalDb.Instance instance, string name, string tempName, string filesPath, int size, int parallel = 1, Action prepare = null, bool delete = false) - { - _localDb = localDb; - _instance = instance; - _filesPath = filesPath; - _name = name; - _size = size; - _prepare = prepare; - _prepareQueue = new BlockingCollection(); - _readyQueue = new BlockingCollection(); - _cstrs = new string[_size]; - - for (var i = 0; i < size; i++) - localDb.CopyDatabaseFiles(tempName, filesPath, targetDatabaseName: name + "-" + i, overwrite: true, delete: delete && i == size - 1); - - if (prepare == null) - { - for (var i = 0; i < size; i++) - _readyQueue.Add(i); - } - else - { - for (var i = 0; i < size; i++) - _prepareQueue.Add(i); - } - - for (var i = 0; i < parallel; i++) - { - var thread = new Thread(PrepareThread); - thread.Start(); - } - } - - public string AttachDatabase(out int id) - { - _current = _readyQueue.Take(); - id = _current; - - return ConnectionString(_current); - } - - public void DetachDatabase(int id) - { - if (id != _current) - throw new InvalidOperationException("Cannot detatch the non-current db"); - - _prepareQueue.Add(_current); - } - - private string ConnectionString(int i) - { - return _cstrs[i] ?? (_cstrs[i] = _instance.GetAttachedConnectionString(_name + "-" + i, _filesPath)); - } - - private void PrepareThread() - { - Retry(10, () => - { - while (_prepareQueue.IsCompleted == false) - { - int i; - try - { - i = _prepareQueue.Take(); - } - catch (InvalidOperationException) - { - continue; - } - - using (var conn = new SqlConnection(ConnectionString(i))) - using (var cmd = conn.CreateCommand()) - { - conn.Open(); - ResetLocalDb(cmd); - - _prepare?.Invoke(conn, cmd); - - } - - if (!_readyQueue.IsAddingCompleted) - { - _readyQueue.Add(i); - } - } - }); - } - - public void Stop() - { - int i; - _prepareQueue.CompleteAdding(); - while (_prepareQueue.TryTake(out i)) { } - _readyQueue.CompleteAdding(); - while (_readyQueue.TryTake(out i)) { } - } - } - } } diff --git a/src/Umbraco.Tests.Integration/Testing/SqlDeveloperTestDatabase.cs b/src/Umbraco.Tests.Integration/Testing/SqlDeveloperTestDatabase.cs index 52be6d5472..4a7f602ac6 100644 --- a/src/Umbraco.Tests.Integration/Testing/SqlDeveloperTestDatabase.cs +++ b/src/Umbraco.Tests.Integration/Testing/SqlDeveloperTestDatabase.cs @@ -1,15 +1,8 @@ -using System; +using System; using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Data; using System.Data.SqlClient; -using System.Linq; -using System.Text.RegularExpressions; using System.Threading; using Microsoft.Extensions.Logging; -using Umbraco.Core; -using Umbraco.Core.Configuration; -using Umbraco.Core.Migrations.Install; using Umbraco.Core.Persistence; // ReSharper disable ConvertToUsingDeclaration @@ -19,82 +12,57 @@ namespace Umbraco.Tests.Integration.Testing /// /// It's not meant to be pretty, rushed port of LocalDb.cs + LocalDbTestDatabase.cs /// - public class SqlDeveloperTestDatabase : ITestDatabase + public class SqlDeveloperTestDatabase : BaseTestDatabase, ITestDatabase { - - // This is gross but it's how the other one works and I don't want to refactor everything. - public string ConnectionString { get; private set; } - private readonly string _masterConnectionString; - private readonly ILoggerFactory _loggerFactory; - private readonly ILogger _log; - private readonly IUmbracoDatabaseFactory _databaseFactory; - private readonly IDictionary _testDatabases; - private UmbracoDatabase.CommandInfo[] _cachedDatabaseInitCommands; + public const string DatabaseName = "UmbracoTests"; - private BlockingCollection _prepareQueue; - private BlockingCollection _readySchemaQueue; - private BlockingCollection _readyEmptyQueue; - - private const string _databasePrefix = "UmbracoTest"; private const int _threadCount = 2; - public static SqlDeveloperTestDatabase Instance; + public static SqlDeveloperTestDatabase Instance { get; private set; } public SqlDeveloperTestDatabase(ILoggerFactory loggerFactory, IUmbracoDatabaseFactory databaseFactory, string masterConnectionString) { _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); _databaseFactory = databaseFactory ?? throw new ArgumentNullException(nameof(databaseFactory)); + _masterConnectionString = masterConnectionString; - _log = loggerFactory.CreateLogger(); _testDatabases = new[] { - new TestDbMeta(1, false, masterConnectionString), - new TestDbMeta(2, false, masterConnectionString), + // With Schema + TestDbMeta.CreateWithMasterConnectionString($"{DatabaseName}-1", false, masterConnectionString), + TestDbMeta.CreateWithMasterConnectionString($"{DatabaseName}-2", false, masterConnectionString), - new TestDbMeta(3, true, masterConnectionString), - }.ToDictionary(x => x.Id); + // Empty (for migration testing etc) + TestDbMeta.CreateWithMasterConnectionString($"{DatabaseName}-3", true, masterConnectionString), + TestDbMeta.CreateWithMasterConnectionString($"{DatabaseName}-4", true, masterConnectionString), + }; Instance = this; // For GlobalSetupTeardown.cs } - public int AttachEmpty() + protected override void Initialize() { - if (_prepareQueue == null) + _prepareQueue = new BlockingCollection(); + _readySchemaQueue = new BlockingCollection(); + _readyEmptyQueue = new BlockingCollection(); + + foreach (var meta in _testDatabases) { - Initialize(); + CreateDatabase(meta); + _prepareQueue.Add(meta); } - var meta = _readyEmptyQueue.Take(); - - ConnectionString = meta.ConnectionString; - - return meta.Id; - } - - public int AttachSchema() - { - if (_prepareQueue == null) + for (var i = 0; i < _threadCount; i++) { - Initialize(); + var thread = new Thread(PrepareDatabase); + thread.Start(); } - - var meta = _readySchemaQueue.Take(); - - ConnectionString = meta.ConnectionString; - - return meta.Id; - } - - public void Detach(int id) - { - _prepareQueue.TryAdd(_testDatabases[id]); } private void CreateDatabase(TestDbMeta meta) { - _log.LogInformation($"Creating database {meta.Name}"); using (var connection = new SqlConnection(_masterConnectionString)) { connection.Open(); @@ -106,91 +74,8 @@ namespace Umbraco.Tests.Integration.Testing } } - private static string ConstructConnectionString(string masterConnectionString, string databaseName) - { - var prefix = Regex.Replace(masterConnectionString, "Database=.+?;", string.Empty); - var connectionString = $"{prefix};Database={databaseName};"; - return connectionString.Replace(";;", ";"); - } - - private static void SetCommand(SqlCommand command, string sql, params object[] args) - { - command.CommandType = CommandType.Text; - command.CommandText = sql; - command.Parameters.Clear(); - - for (var i = 0; i < args.Length; i++) - { - command.Parameters.AddWithValue("@" + i, args[i]); - } - } - - private void RebuildSchema(IDbCommand command, TestDbMeta meta) - { - if (_cachedDatabaseInitCommands != null) - { - foreach (var dbCommand in _cachedDatabaseInitCommands) - { - - if (dbCommand.Text.StartsWith("SELECT ")) - { - continue; - } - - command.CommandText = dbCommand.Text; - command.Parameters.Clear(); - - foreach (var parameterInfo in dbCommand.Parameters) - { - LocalDbTestDatabase.AddParameter(command, parameterInfo); - } - - command.ExecuteNonQuery(); - } - } - else - { - _databaseFactory.Configure(meta.ConnectionString, Constants.DatabaseProviders.SqlServer); - - using (var database = (UmbracoDatabase)_databaseFactory.CreateDatabase()) - { - database.LogCommands = true; - - using (var transaction = database.GetTransaction()) - { - var schemaCreator = new DatabaseSchemaCreator(database, _loggerFactory.CreateLogger(), _loggerFactory, new UmbracoVersion()); - schemaCreator.InitializeDatabaseSchema(); - - transaction.Complete(); - - _cachedDatabaseInitCommands = database.Commands.ToArray(); - } - } - } - } - - private void Initialize() - { - _prepareQueue = new BlockingCollection(); - _readySchemaQueue = new BlockingCollection(); - _readyEmptyQueue = new BlockingCollection(); - - foreach (var meta in _testDatabases.Values) - { - CreateDatabase(meta); - _prepareQueue.Add(meta); - } - - for (var i = 0; i < _threadCount; i++) - { - var thread = new Thread(PrepareThread); - thread.Start(); - } - } - private void Drop(TestDbMeta meta) { - _log.LogInformation($"Dropping database {meta.Name}"); using (var connection = new SqlConnection(_masterConnectionString)) { connection.Open(); @@ -209,46 +94,6 @@ namespace Umbraco.Tests.Integration.Testing } } - private void PrepareThread() - { - LocalDbTestDatabase.Retry(10, () => - { - while (_prepareQueue.IsCompleted == false) - { - TestDbMeta meta; - try - { - meta = _prepareQueue.Take(); - } - catch (InvalidOperationException) - { - continue; - } - - using (var conn = new SqlConnection(meta.ConnectionString)) - using (var cmd = conn.CreateCommand()) - { - conn.Open(); - LocalDbTestDatabase.ResetLocalDb(cmd); - - if (!meta.IsEmpty) - { - RebuildSchema(cmd, meta); - } - } - - if (!meta.IsEmpty) - { - _readySchemaQueue.TryAdd(meta); - } - else - { - _readyEmptyQueue.TryAdd(meta); - } - } - }); - } - public void Finish() { if (_prepareQueue == null) @@ -263,25 +108,10 @@ namespace Umbraco.Tests.Integration.Testing _readySchemaQueue.CompleteAdding(); while (_readySchemaQueue.TryTake(out _)) { } - foreach (var testDatabase in _testDatabases.Values) + foreach (var testDatabase in _testDatabases) { Drop(testDatabase); } } - - private class TestDbMeta - { - public int Id { get; } - public string Name => $"{_databasePrefix}-{Id}"; - public bool IsEmpty { get; } - public string ConnectionString { get; } - - public TestDbMeta(int id, bool isEmpty, string masterConnectionString) - { - Id = id; - IsEmpty = isEmpty; - ConnectionString = ConstructConnectionString(masterConnectionString, Name); - } - } } } diff --git a/src/Umbraco.Tests.Integration/Testing/TestDatabaseFactory.cs b/src/Umbraco.Tests.Integration/Testing/TestDatabaseFactory.cs index 3ed2b6b49a..9bcbfa4d3a 100644 --- a/src/Umbraco.Tests.Integration/Testing/TestDatabaseFactory.cs +++ b/src/Umbraco.Tests.Integration/Testing/TestDatabaseFactory.cs @@ -1,5 +1,4 @@ -using System; -using System.Runtime.InteropServices; +using System; using Microsoft.Extensions.Logging; using Umbraco.Core.Persistence; @@ -9,7 +8,7 @@ namespace Umbraco.Tests.Integration.Testing { public static ITestDatabase Create(string filesPath, ILoggerFactory loggerFactory, TestUmbracoDatabaseFactoryProvider dbFactory) { - return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + return string.IsNullOrEmpty(Environment.GetEnvironmentVariable("UmbracoIntegrationTestConnectionString")) ? CreateLocalDb(filesPath, loggerFactory, dbFactory.Create()) : CreateSqlDeveloper(loggerFactory, dbFactory.Create()); } diff --git a/src/Umbraco.Tests.Integration/Testing/TestDbMeta.cs b/src/Umbraco.Tests.Integration/Testing/TestDbMeta.cs new file mode 100644 index 0000000000..83702db8e5 --- /dev/null +++ b/src/Umbraco.Tests.Integration/Testing/TestDbMeta.cs @@ -0,0 +1,39 @@ +using System.Text.RegularExpressions; + +namespace Umbraco.Tests.Integration.Testing +{ + public class TestDbMeta + { + + public string Name { get; } + + public bool IsEmpty { get; } + + public string ConnectionString { get; set; } + + private TestDbMeta(string name, bool isEmpty, string connectionString) + { + IsEmpty = isEmpty; + Name = name; + ConnectionString = connectionString; + } + + private static string ConstructConnectionString(string masterConnectionString, string databaseName) + { + var prefix = Regex.Replace(masterConnectionString, "Database=.+?;", string.Empty); + var connectionString = $"{prefix};Database={databaseName};"; + return connectionString.Replace(";;", ";"); + } + + public static TestDbMeta CreateWithMasterConnectionString(string name, bool isEmpty, string masterConnectionString) + { + return new TestDbMeta(name, isEmpty, ConstructConnectionString(masterConnectionString, name)); + } + + // LocalDb mdf funtimes + public static TestDbMeta CreateWithoutConnectionString(string name, bool isEmpty) + { + return new TestDbMeta(name, isEmpty, null); + } + } +} diff --git a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs index 3da4ec94d6..43b2d236c7 100644 --- a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs +++ b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs @@ -244,6 +244,7 @@ namespace Umbraco.Tests.Integration.Testing private static readonly object _dbLocker = new object(); private static ITestDatabase _dbInstance; + private static TestDbMeta _fixtureDbMeta; protected void UseTestLocalDb(IServiceProvider serviceProvider) { @@ -253,8 +254,6 @@ namespace Umbraco.Tests.Integration.Testing // This will create a db, install the schema and ensure the app is configured to run InstallTestLocalDb(testDatabaseFactoryProvider, databaseFactory, serviceProvider.GetRequiredService(), state, TestHelper.WorkingDirectory); - TestDBConnectionString = databaseFactory.ConnectionString; - InMemoryConfiguration["ConnectionStrings:" + Constants.System.UmbracoConnectionName] = TestDBConnectionString; } /// @@ -312,15 +311,15 @@ namespace Umbraco.Tests.Integration.Testing case UmbracoTestOptions.Database.NewSchemaPerTest: // New DB + Schema - var newSchemaDbId = db.AttachSchema(); + var newSchemaDbMeta = db.AttachSchema(); // Add teardown callback - OnTestTearDown(() => db.Detach(newSchemaDbId)); + OnTestTearDown(() => db.Detach(newSchemaDbMeta)); // We must re-configure our current factory since attaching a new LocalDb from the pool changes connection strings if (!databaseFactory.Configured) { - databaseFactory.Configure(db.ConnectionString, Constants.DatabaseProviders.SqlServer); + databaseFactory.Configure(newSchemaDbMeta.ConnectionString, Constants.DatabaseProviders.SqlServer); } // re-run the runtime level check @@ -330,15 +329,15 @@ namespace Umbraco.Tests.Integration.Testing break; case UmbracoTestOptions.Database.NewEmptyPerTest: - var newEmptyDbId = db.AttachEmpty(); + var newEmptyDbMeta = db.AttachEmpty(); // Add teardown callback - OnTestTearDown(() => db.Detach(newEmptyDbId)); + OnTestTearDown(() => db.Detach(newEmptyDbMeta)); // We must re-configure our current factory since attaching a new LocalDb from the pool changes connection strings if (!databaseFactory.Configured) { - databaseFactory.Configure(db.ConnectionString, Constants.DatabaseProviders.SqlServer); + databaseFactory.Configure(newEmptyDbMeta.ConnectionString, Constants.DatabaseProviders.SqlServer); } // re-run the runtime level check @@ -354,16 +353,17 @@ namespace Umbraco.Tests.Integration.Testing if (FirstTestInFixture) { // New DB + Schema - var newSchemaFixtureDbId = db.AttachSchema(); + var newSchemaFixtureDbMeta = db.AttachSchema(); + _fixtureDbMeta = newSchemaFixtureDbMeta; // Add teardown callback - OnFixtureTearDown(() => db.Detach(newSchemaFixtureDbId)); + OnFixtureTearDown(() => db.Detach(newSchemaFixtureDbMeta)); } // We must re-configure our current factory since attaching a new LocalDb from the pool changes connection strings if (!databaseFactory.Configured) { - databaseFactory.Configure(db.ConnectionString, Constants.DatabaseProviders.SqlServer); + databaseFactory.Configure(_fixtureDbMeta.ConnectionString, Constants.DatabaseProviders.SqlServer); } // re-run the runtime level check @@ -377,16 +377,17 @@ namespace Umbraco.Tests.Integration.Testing if (FirstTestInFixture) { // New DB + Schema - var newEmptyFixtureDbId = db.AttachEmpty(); + var newEmptyFixtureDbMeta = db.AttachEmpty(); + _fixtureDbMeta = newEmptyFixtureDbMeta; // Add teardown callback - OnFixtureTearDown(() => db.Detach(newEmptyFixtureDbId)); + OnFixtureTearDown(() => db.Detach(newEmptyFixtureDbMeta)); } // We must re-configure our current factory since attaching a new LocalDb from the pool changes connection strings if (!databaseFactory.Configured) { - databaseFactory.Configure(db.ConnectionString, Constants.DatabaseProviders.SqlServer); + databaseFactory.Configure(_fixtureDbMeta.ConnectionString, Constants.DatabaseProviders.SqlServer); } break; @@ -407,8 +408,6 @@ namespace Umbraco.Tests.Integration.Testing public TestHelper TestHelper = new TestHelper(); - protected virtual string TestDBConnectionString { get; private set; } - protected virtual Action CustomTestSetup => services => { }; /// diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index faf387528d..8c7b9a00e2 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Configuration; using System.Data.SqlServerCe; using System.Threading; @@ -91,7 +91,6 @@ namespace Umbraco.Tests.TestHelpers var lazyMappers = new Lazy(f.GetRequiredService); var factory = new UmbracoDatabaseFactory(f.GetRequiredService>(), f.GetRequiredService(), GetDbConnectionString(), GetDbProviderName(), lazyMappers, TestHelper.DbProviderFactoryCreator); - factory.ResetForTests(); return factory; }); } From cb84a98b9cf5891e0ff94e4e3441af976da00d48 Mon Sep 17 00:00:00 2001 From: Paul Johnson Date: Sat, 12 Dec 2020 13:15:08 +0000 Subject: [PATCH 22/27] Fix indent for MacOS Don't split build and test on Windows. --- build/azure-pipelines.yml | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/build/azure-pipelines.yml b/build/azure-pipelines.yml index d301b9c461..c545d6884e 100644 --- a/build/azure-pipelines.yml +++ b/build/azure-pipelines.yml @@ -66,26 +66,26 @@ stages: env: UmbracoIntegrationTestConnectionString: 'Server=localhost,1433;User Id=sa;Password=$(SA_PASSWORD);' -- stage: macOS_X +- stage: MacOS dependsOn: [] # this removes the implicit dependency on previous stage and causes this to run in parallel jobs: - - job: Unit_Tests - displayName: 'Unit Tests' - pool: - vmImage: 'macOS-latest' - steps: + - job: Unit_Tests + displayName: 'Unit Tests' + pool: + vmImage: 'macOS-latest' + steps: - - task: UseDotNet@2 - displayName: 'Use .Net Core sdk 3.1.x' - inputs: - version: 3.1.x + - task: UseDotNet@2 + displayName: 'Use .Net Core sdk 3.1.x' + inputs: + version: 3.1.x - - task: DotNetCoreCLI@2 - displayName: 'dotnet test' - inputs: - command: test - projects: '**/*.Tests.UnitTests.csproj' + - task: DotNetCoreCLI@2 + displayName: 'dotnet test' + inputs: + command: test + projects: '**/*.Tests.UnitTests.csproj' - stage: Windows dependsOn: [] # this removes the implicit dependency on previous stage and causes this to run in parallel @@ -120,11 +120,6 @@ stages: inputs: version: 3.1.x - - task: DotNetCoreCLI@2 - displayName: 'dotnet build' - inputs: - projects: '**\Umbraco.Tests.Integration.csproj' - - powershell: 'sqllocaldb start mssqllocaldb' displayName: 'Start MSSQL LocalDb' @@ -133,7 +128,6 @@ stages: inputs: command: test projects: '**\Umbraco.Tests.Integration.csproj' - arguments: '--no-build' - job: Build_Artifacts displayName: 'Build Artifacts' From 3927a8db670d51f396740d835f473c8b4b6ffc78 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 14 Dec 2020 12:04:19 +1100 Subject: [PATCH 23/27] Ensure we capture exceptions that occur when trying to create a transaction --- src/Umbraco.Core/Runtime/MainDom.cs | 12 ++- src/Umbraco.Core/Runtime/SqlMainDomLock.cs | 96 +++++++++++++++------- 2 files changed, 76 insertions(+), 32 deletions(-) diff --git a/src/Umbraco.Core/Runtime/MainDom.cs b/src/Umbraco.Core/Runtime/MainDom.cs index e6780ec876..02f37f654e 100644 --- a/src/Umbraco.Core/Runtime/MainDom.cs +++ b/src/Umbraco.Core/Runtime/MainDom.cs @@ -144,8 +144,16 @@ namespace Umbraco.Core.Runtime _logger.Info("Acquiring."); - // Get the lock - var acquired = _mainDomLock.AcquireLockAsync(LockTimeoutMilliseconds).GetAwaiter().GetResult(); + // Get the lock + var acquired = false; + try + { + acquired = _mainDomLock.AcquireLockAsync(LockTimeoutMilliseconds).GetAwaiter().GetResult(); + } + catch (Exception ex) + { + _logger.Error(ex, "Error while acquiring"); + } if (!acquired) { diff --git a/src/Umbraco.Core/Runtime/SqlMainDomLock.cs b/src/Umbraco.Core/Runtime/SqlMainDomLock.cs index 209b99aef1..84d98775d9 100644 --- a/src/Umbraco.Core/Runtime/SqlMainDomLock.cs +++ b/src/Umbraco.Core/Runtime/SqlMainDomLock.cs @@ -1,4 +1,5 @@ -using System; +using NPoco; +using System; using System.Data; using System.Data.SqlClient; using System.Diagnostics; @@ -48,7 +49,9 @@ namespace Umbraco.Core.Runtime } if (!(_dbFactory.SqlContext.SqlSyntax is SqlServerSyntaxProvider sqlServerSyntaxProvider)) + { throw new NotSupportedException("SqlMainDomLock is only supported for Sql Server"); + } _sqlServerSyntax = sqlServerSyntaxProvider; @@ -56,11 +59,13 @@ namespace Umbraco.Core.Runtime var tempId = Guid.NewGuid().ToString(); - using var db = _dbFactory.CreateDatabase(); - using var transaction = db.GetTransaction(IsolationLevel.ReadCommitted); + IUmbracoDatabase db = null; try { + db = _dbFactory.CreateDatabase(); + db.BeginTransaction(IsolationLevel.ReadCommitted); + try { // wait to get a write lock @@ -101,7 +106,8 @@ namespace Umbraco.Core.Runtime } finally { - transaction.Complete(); + db?.CompleteTransaction(); + db?.Dispose(); } @@ -154,11 +160,11 @@ namespace Umbraco.Core.Runtime // new MainDom will just take over. if (_cancellationTokenSource.IsCancellationRequested) return; - - using var db = _dbFactory.CreateDatabase(); - using var transaction = db.GetTransaction(IsolationLevel.ReadCommitted); + IUmbracoDatabase db = null; try { + db = _dbFactory.CreateDatabase(); + db.BeginTransaction(IsolationLevel.ReadCommitted); // get a read lock _sqlServerSyntax.ReadLock(db, Constants.Locks.MainDom); @@ -182,7 +188,8 @@ namespace Umbraco.Core.Runtime } finally { - transaction.Complete(); + db?.CompleteTransaction(); + db?.Dispose(); } } @@ -201,34 +208,47 @@ namespace Umbraco.Core.Runtime return Task.Run(() => { - using var db = _dbFactory.CreateDatabase(); - - var watch = new Stopwatch(); - watch.Start(); - while (true) + try { - // poll very often, we need to take over as fast as we can - // local testing shows the actual query to be executed from client/server is approx 300ms but would change depending on environment/IO - Thread.Sleep(1000); + using var db = _dbFactory.CreateDatabase(); - var acquired = TryAcquire(db, tempId, updatedTempId); - if (acquired.HasValue) - return acquired.Value; - - if (watch.ElapsedMilliseconds >= millisecondsTimeout) + var watch = new Stopwatch(); + watch.Start(); + while (true) { - return AcquireWhenMaxWaitTimeElapsed(db); + // poll very often, we need to take over as fast as we can + // local testing shows the actual query to be executed from client/server is approx 300ms but would change depending on environment/IO + Thread.Sleep(1000); + + var acquired = TryAcquire(db, tempId, updatedTempId); + if (acquired.HasValue) + return acquired.Value; + + if (watch.ElapsedMilliseconds >= millisecondsTimeout) + { + return AcquireWhenMaxWaitTimeElapsed(db); + } } } + catch (Exception ex) + { + _logger.Error(ex, "An error occurred trying to acquire and waiting for existing SqlMainDomLock to shutdown"); + return false; + } + }, _cancellationTokenSource.Token); } private bool? TryAcquire(IUmbracoDatabase db, string tempId, string updatedTempId) { - using var transaction = db.GetTransaction(IsolationLevel.ReadCommitted); + // Creates a separate transaction to the DB instance so we aren't allocating tons of new DB instances for each transaction + // since this is executed in a tight loop + + ITransaction transaction = null; try { + transaction = db.GetTransaction(IsolationLevel.ReadCommitted); // get a read lock _sqlServerSyntax.ReadLock(db, Constants.Locks.MainDom); @@ -274,7 +294,8 @@ namespace Umbraco.Core.Runtime } finally { - transaction.Complete(); + transaction?.Complete(); + transaction?.Dispose(); } return null; // continue @@ -282,6 +303,9 @@ namespace Umbraco.Core.Runtime private bool AcquireWhenMaxWaitTimeElapsed(IUmbracoDatabase db) { + // Creates a separate transaction to the DB instance so we aren't allocating tons of new DB instances for each transaction + // since this is executed in a tight loop + // if the timeout has elapsed, it either means that the other main dom is taking too long to shutdown, // or it could mean that the previous appdomain was terminated and didn't clear out the main dom SQL row // and it's just been left as an orphan row. @@ -291,10 +315,12 @@ namespace Umbraco.Core.Runtime _logger.Debug("Timeout elapsed, assuming orphan row, acquiring MainDom."); - using var transaction = db.GetTransaction(IsolationLevel.ReadCommitted); + ITransaction transaction = null; try { + transaction = db.GetTransaction(IsolationLevel.ReadCommitted); + _sqlServerSyntax.WriteLock(db, Constants.Locks.MainDom); // so now we update the row with our appdomain id @@ -317,7 +343,8 @@ namespace Umbraco.Core.Runtime } finally { - transaction.Complete(); + transaction?.Complete(); + transaction?.Dispose(); } } @@ -368,11 +395,12 @@ namespace Umbraco.Core.Runtime if (_dbFactory.Configured) { - using var db = _dbFactory.CreateDatabase(); - using var transaction = db.GetTransaction(IsolationLevel.ReadCommitted); - + IUmbracoDatabase db = null; try { + db = _dbFactory.CreateDatabase(); + db.BeginTransaction(IsolationLevel.ReadCommitted); + // get a write lock _sqlServerSyntax.WriteLock(db, Constants.Locks.MainDom); @@ -399,7 +427,15 @@ namespace Umbraco.Core.Runtime } finally { - transaction.Complete(); + try + { + db?.CompleteTransaction(); + db?.Dispose(); + } + catch (Exception ex) + { + _logger.Error(ex, "Unexpected error during dispose when completing transaction."); + } } } } From 60dbfb66f74aa6b485264c37d3fd59810faf8181 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 14 Dec 2020 10:21:23 +0100 Subject: [PATCH 24/27] changed wording --- src/Umbraco.Web.UI/Umbraco/config/lang/da.xml | 2 +- src/Umbraco.Web.UI/Umbraco/config/lang/en.xml | 2 +- src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml index 35279a75f3..345a523789 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml @@ -1439,7 +1439,7 @@ Mange hilsner fra Umbraco robotten Dette benyttes ikke for en Element-type Du har lavet ændringer til denne egenskab. Er du sikker på at du vil kassere dem? Visning - Flyt label over editoren + Label hen over (fuld brede) Tilføj sprog diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml index 3c864e2d66..0a9ea1d147 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml @@ -1697,7 +1697,7 @@ To manage your website, simply open the Umbraco back office and start adding con This is not applicable for an Element type You have made changes to this property. Are you sure you want to discard them? Appearance - Display label on top of editor. + Label above (full-width) Add language diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index a5144bf450..621491112e 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -1717,7 +1717,7 @@ To manage your website, simply open the Umbraco back office and start adding con This is not applicable for an element type You have made changes to this property. Are you sure you want to discard them? Appearance - Display label on top of editor. + Label above (full-width) Add language From 734d33fe1cf1f1f1dc02bd58f43a4c54ba12211e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 14 Dec 2020 11:14:12 +0100 Subject: [PATCH 25/27] change dialog --- .../src/preview/preview.controller.js | 19 +++++++++++++++---- .../Umbraco/Views/Preview/Index.cshtml | 6 ++++-- src/Umbraco.Web.UI/Umbraco/config/lang/da.xml | 5 +++-- src/Umbraco.Web.UI/Umbraco/config/lang/en.xml | 7 ++++--- .../Umbraco/config/lang/en_us.xml | 7 ++++--- 5 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/preview/preview.controller.js b/src/Umbraco.Web.UI.Client/src/preview/preview.controller.js index 78f753a8ca..a21ce75c30 100644 --- a/src/Umbraco.Web.UI.Client/src/preview/preview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/preview/preview.controller.js @@ -228,9 +228,10 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi // Ask to re-enter preview mode? const localizeVarsFallback = { - "returnToPreviewHeadline": "Preview content?", - "returnToPreviewDescription":"You have ended preview mode, do you want to continue previewing this content?", - "returnToPreviewButton":"Preview" + "returnToPreviewHeadline": "Preview website?", + "returnToPreviewDescription":"You have ended preview mode, do you want to enable it again to view the latest saved version of your website?", + "returnToPreviewAcceptButton":"Preview latest version", + "returnToPreviewDeclineButton":"View published version" }; const umbLocalizedVars = Object.assign(localizeVarsFallback, $window.umbLocalizedVars); @@ -333,10 +334,20 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi
${umbLocalizedVars.returnToPreviewDescription}
`; con.appendChild(modal); + var declineButton = document.createElement("button"); + declineButton.type = "button"; + declineButton.innerHTML = umbLocalizedVars.returnToPreviewDeclineButton; + declineButton.addEventListener("click", () => { + bodyEl.removeChild(fragment); + $scope.exitPreview(); + hasPreviewDialog = false; + }); + modal.appendChild(declineButton); + var continueButton = document.createElement("button"); continueButton.type = "button"; continueButton.className = "umbraco-preview-dialog__continue"; - continueButton.innerHTML = umbLocalizedVars.returnToPreviewButton; + continueButton.innerHTML = umbLocalizedVars.returnToPreviewAcceptButton; continueButton.addEventListener("click", () => { bodyEl.removeChild(fragment); reenterPreviewMode(); diff --git a/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml b/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml index c3365f06fc..eb89211652 100644 --- a/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml @@ -22,7 +22,8 @@ var OpenWebsiteTitle = textService.Localize("preview", "openWebsiteTitle"); var returnToPreviewHeadline = textService.Localize("preview", "returnToPreviewHeadline"); var returnToPreviewDescription = textService.Localize("preview", "returnToPreviewDescription"); - var returnToPreviewButton = textService.Localize("preview", "returnToPreviewButton"); + var returnToPreviewAcceptButton = textService.Localize("preview", "returnToPreviewAcceptButton"); + var returnToPreviewDeclineButton = textService.Localize("preview", "returnToPreviewDeclineButton"); } @@ -39,7 +40,8 @@ window.umbLocalizedVars = { 'returnToPreviewHeadline': '@returnToPreviewHeadline', 'returnToPreviewDescription':'@returnToPreviewDescription', - 'returnToPreviewButton':'@returnToPreviewButton' + 'returnToPreviewAcceptButton':'@returnToPreviewAcceptButton', + 'returnToPreviewDeclineButton':'@returnToPreviewDeclineButton' }; diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml index 35279a75f3..59ee0eb2d9 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml @@ -1873,8 +1873,9 @@ Mange hilsner fra Umbraco robotten Vis i nyt vindue Åben forhåndsvisning i nyt vindue Forhåndsvisning af indholdet? - Du har afslutet forhåndsvisning, vil du se dette indhold i forhåndsvisning? - Fortsæt + Du har afslutet forhåndsvisning, vil du starte forhåndsvisning igen for at se seneste gemte version af indholdet? + Start forhåndsvisning + Se udgivet indhold Se udgivet indhold? Du er i forhåndsvisning, vil du afslutte for at se den udgivet version? Se udgivet version diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml index 3c864e2d66..687d7f61a0 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml @@ -2531,9 +2531,10 @@ To manage your website, simply open the Umbraco back office and start adding con End preview mode Preview website Open website in preview mode - Preview content? - You have ended preview mode, do you want to continue previewing this content? - Preview + Preview website? + ou have ended preview mode, do you want to enable it again to view the latest saved version of your website? + Preview latest version + View published version View published version? You are in Preview Mode, do you want exit in order to view the published version of your website? View published version diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index a5144bf450..b0987236f3 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -2553,9 +2553,10 @@ To manage your website, simply open the Umbraco back office and start adding con End preview mode Preview website Open website in preview mode - Preview content? - You have ended preview mode, do you want to continue previewing this content? - Preview + Preview website? + ou have ended preview mode, do you want to enable it again to view the latest saved version of your website? + Preview latest version + View published version View published version? You are in Preview Mode, do you want exit in order to view the published version of your website? View published version From b2dac7947fc3bb9718ffbd65385d6661320b7bdd Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Mon, 14 Dec 2020 13:29:53 +0000 Subject: [PATCH 26/27] Bump version to 8.10.0 .\build SetUmbracoVersion 8.10.0 --- src/SolutionInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SolutionInfo.cs b/src/SolutionInfo.cs index 89997c0a01..c503fcd03e 100644 --- a/src/SolutionInfo.cs +++ b/src/SolutionInfo.cs @@ -19,4 +19,4 @@ using System.Resources; // these are FYI and changed automatically [assembly: AssemblyFileVersion("8.10.0")] -[assembly: AssemblyInformationalVersion("8.10.0-rc")] +[assembly: AssemblyInformationalVersion("8.10.0")] From 3a11c21ebc08aaaefc1d6be244987d37fb1539a2 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Mon, 14 Dec 2020 19:21:35 +0100 Subject: [PATCH 27/27] revert connection string --- src/Umbraco.Web.UI.NetCore/appsettings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.NetCore/appsettings.json b/src/Umbraco.Web.UI.NetCore/appsettings.json index 43ae07d5d6..caa563fe8e 100644 --- a/src/Umbraco.Web.UI.NetCore/appsettings.json +++ b/src/Umbraco.Web.UI.NetCore/appsettings.json @@ -39,7 +39,7 @@ }, "RuntimeMinification": { "dataFolder": "App_Data/TEMP/Smidge", - "version": "637429346786793415" + "version": "637432008251409860" }, "Security": { "KeepUserLoggedIn": false,