From cf2b9a0f21dd1a4b37f955c9787f87d5f42f3151 Mon Sep 17 00:00:00 2001 From: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com> Date: Fri, 29 Apr 2022 11:52:58 +0200 Subject: [PATCH] V10: Move core services to core project (#12314) * Move AuditService to core project * Move two factor login service to core * Move ServerRegistrationService to core * Move BasicAuthService to Core project * Move IdKeyMap to core project * Added CacheInstructionService to the infrastructure namespace * Move DataTypeService to core namespace * Update CacheInstructionService.cs to use CoreScopeProvider * Move core editors to core * Move more Property editors and configuration * Remove obsoleted constructors in internal classes * Update PropertyEditors to use new ctors * Fix propertyEditors to use new ctors * Use the right property editor constructors * add DI in the property method * Update grid to use new ctor * Fix non-assignment of variable * Apply suggestions from code review Co-authored-by: Mole * Fix suggestions from code review Co-authored-by: Nikolaj Geisle Co-authored-by: Kevin Jump Co-authored-by: Mole --- src/Umbraco.Core/Constants-Audit.cs | 11 + .../Repositories/IIdKeyMapRepository.cs | 10 + .../IServerRegistrationRepository.cs | 2 + .../ConfigurationEditorOfTConfiguration.cs | 77 +-- .../ContentPickerConfigurationEditor.cs | 6 +- .../ContentPickerPropertyEditor.cs | 17 +- .../DateTimeConfigurationEditor.cs | 12 +- .../EmailAddressConfigurationEditor.cs | 28 + ...yeDropperColorPickerConfigurationEditor.cs | 5 +- .../EyeDropperColorPickerPropertyEditor.cs | 20 +- .../FileUploadConfigurationEditor.cs | 25 + .../LabelConfigurationEditor.cs | 13 +- .../PropertyEditors/LabelPropertyEditor.cs | 17 +- .../ListViewConfigurationEditor.cs | 28 + .../MarkdownConfigurationEditor.cs | 3 +- .../PropertyEditors/MarkdownPropertyEditor.cs | 22 +- .../MediaPicker3ConfigurationEditor.cs | 15 +- .../MediaPickerConfigurationEditor.cs | 13 +- .../MultiNodePickerConfigurationEditor.cs | 13 +- .../MultiUrlPickerConfigurationEditor.cs | 26 + .../NestedContentConfigurationEditor.cs | 28 + .../RichTextConfigurationEditor.cs | 28 + .../SliderConfigurationEditor.cs | 28 + .../PropertyEditors/TagConfigurationEditor.cs | 11 +- .../TextAreaConfigurationEditor.cs | 28 + .../TextboxConfigurationEditor.cs | 28 + .../TrueFalseConfigurationEditor.cs | 28 + .../Security/BackOfficeIdentityOptions.cs | 0 .../Security/ITwoFactorProvider.cs | 0 .../Services}/AuditService.cs | 15 +- .../Services}/BasicAuthService.cs | 14 +- .../Services}/DataTypeService.cs | 0 .../Services/IEditorConfigurationParser.cs | 11 + .../Services/IIpAddressUtilities.cs | 8 + .../Services/IdKeyMap.cs | 38 +- .../Services}/ServerRegistrationService.cs | 7 +- .../Services}/TwoFactorLoginService.cs | 0 src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../UmbracoBuilder.CoreServices.cs | 2 +- .../UmbracoBuilder.Repositories.cs | 1 + .../UmbracoBuilder.Services.cs | 4 + .../DropDownPropertyEditorsMigration.cs | 16 +- .../MergeDateAndDateTimePropertyEditor.cs | 16 +- .../V_8_0_0/PropertyEditorsMigrationBase.cs | 3 +- ...adioAndCheckboxPropertyEditorsMigration.cs | 16 +- .../Persistence/Dtos/AuditEntryDto.cs | 14 +- .../Implement/IdKeyMapRepository.cs | 53 ++ .../BlockListConfigurationEditor.cs | 7 +- .../BlockListPropertyEditor.cs | 17 +- .../CheckBoxListPropertyEditor.cs | 24 +- .../ColorPickerConfigurationEditor.cs | 7 +- .../ColorPickerPropertyEditor.cs | 20 +- .../PropertyEditors/DateTimePropertyEditor.cs | 12 +- .../DropDownFlexibleConfigurationEditor.cs | 2 +- .../DropDownFlexiblePropertyEditor.cs | 24 +- .../EmailAddressConfigurationEditor.cs | 17 - .../FileUploadConfigurationEditor.cs | 15 - .../FileUploadPropertyEditor.cs | 29 +- .../GridConfigurationEditor.cs | 14 +- .../PropertyEditors/GridPropertyEditor.cs | 56 +- .../ImageCropperConfigurationEditor.cs | 6 +- .../ImageCropperPropertyEditor.cs | 32 +- .../ListViewConfigurationEditor.cs | 17 - .../PropertyEditors/ListViewPropertyEditor.cs | 20 +- .../MediaPicker3PropertyEditor.cs | 17 +- .../MediaPickerPropertyEditor.cs | 22 +- .../MultiNodeTreePickerPropertyEditor.cs | 19 +- .../MultiUrlPickerConfigurationEditor.cs | 14 - .../MultiUrlPickerPropertyEditor.cs | 23 +- .../MultipleTextStringConfigurationEditor.cs | 6 +- .../MultipleTextStringPropertyEditor.cs | 19 +- .../NestedContentConfigurationEditor.cs | 17 - .../NestedContentPropertyEditor.cs | 18 +- .../RadioButtonsPropertyEditor.cs | 24 +- .../RichTextConfigurationEditor.cs | 17 - .../PropertyEditors/RichTextPropertyEditor.cs | 56 +- .../SliderConfigurationEditor.cs | 17 - .../PropertyEditors/SliderPropertyEditor.cs | 19 +- .../PropertyEditors/TagsPropertyEditor.cs | 25 +- .../TextAreaConfigurationEditor.cs | 17 - .../PropertyEditors/TextAreaPropertyEditor.cs | 22 +- .../TextboxConfigurationEditor.cs | 17 - .../PropertyEditors/TextboxPropertyEditor.cs | 22 +- .../TrueFalseConfigurationEditor.cs | 17 - .../TrueFalsePropertyEditor.cs | 22 +- .../ValueListConfigurationEditor.cs | 13 +- .../Services/CacheInstructionService.cs | 533 ++++++++++++++++++ .../Services/EditorConfigurationParser.cs | 70 +++ .../Implement/CacheInstructionService.cs | 491 ---------------- .../UmbracoBuilderExtensions.cs | 4 +- .../UmbracoBuilderExtensions.cs | 1 + .../Mvc/IpAddressUtilities.cs | 17 + .../Filters/ContentModelValidatorTests.cs | 5 +- .../Umbraco.Core/Models/VariationTests.cs | 4 +- .../PropertyEditors/ColorListValidatorTest.cs | 3 +- ...ataValueReferenceFactoryCollectionTests.cs | 11 +- .../EnsureUniqueValuesValidatorTest.cs | 6 +- .../MultiValuePropertyEditorTests.cs | 6 +- .../Published/NestedContentTests.cs | 4 +- .../Services/BasicAuthServiceTests.cs | 7 +- 100 files changed, 1775 insertions(+), 910 deletions(-) create mode 100644 src/Umbraco.Core/Constants-Audit.cs create mode 100644 src/Umbraco.Core/Persistence/Repositories/IIdKeyMapRepository.cs rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/ConfigurationEditorOfTConfiguration.cs (71%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/ContentPickerConfigurationEditor.cs (82%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/ContentPickerPropertyEditor.cs (75%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/DateTimeConfigurationEditor.cs (59%) create mode 100644 src/Umbraco.Core/PropertyEditors/EmailAddressConfigurationEditor.cs rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/EyeDropperColorPickerConfigurationEditor.cs (92%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/EyeDropperColorPickerPropertyEditor.cs (54%) create mode 100644 src/Umbraco.Core/PropertyEditors/FileUploadConfigurationEditor.cs rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/LabelConfigurationEditor.cs (65%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/LabelPropertyEditor.cs (74%) create mode 100644 src/Umbraco.Core/PropertyEditors/ListViewConfigurationEditor.cs rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/MarkdownConfigurationEditor.cs (65%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/MarkdownPropertyEditor.cs (56%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/MediaPicker3ConfigurationEditor.cs (62%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/MediaPickerConfigurationEditor.cs (69%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/MultiNodePickerConfigurationEditor.cs (70%) create mode 100644 src/Umbraco.Core/PropertyEditors/MultiUrlPickerConfigurationEditor.cs create mode 100644 src/Umbraco.Core/PropertyEditors/NestedContentConfigurationEditor.cs create mode 100644 src/Umbraco.Core/PropertyEditors/RichTextConfigurationEditor.cs create mode 100644 src/Umbraco.Core/PropertyEditors/SliderConfigurationEditor.cs rename src/{Umbraco.Infrastructure => Umbraco.Core}/PropertyEditors/TagConfigurationEditor.cs (76%) create mode 100644 src/Umbraco.Core/PropertyEditors/TextAreaConfigurationEditor.cs create mode 100644 src/Umbraco.Core/PropertyEditors/TextboxConfigurationEditor.cs create mode 100644 src/Umbraco.Core/PropertyEditors/TrueFalseConfigurationEditor.cs rename src/{Umbraco.Infrastructure => Umbraco.Core}/Security/BackOfficeIdentityOptions.cs (100%) rename src/{Umbraco.Infrastructure => Umbraco.Core}/Security/ITwoFactorProvider.cs (100%) rename src/{Umbraco.Infrastructure/Services/Implement => Umbraco.Core/Services}/AuditService.cs (94%) rename src/{Umbraco.Infrastructure/Services/Implement => Umbraco.Core/Services}/BasicAuthService.cs (57%) rename src/{Umbraco.Infrastructure/Services/Implement => Umbraco.Core/Services}/DataTypeService.cs (100%) create mode 100644 src/Umbraco.Core/Services/IEditorConfigurationParser.cs create mode 100644 src/Umbraco.Core/Services/IIpAddressUtilities.cs rename src/{Umbraco.Infrastructure => Umbraco.Core}/Services/IdKeyMap.cs (85%) rename src/{Umbraco.Infrastructure/Services/Implement => Umbraco.Core/Services}/ServerRegistrationService.cs (94%) rename src/{Umbraco.Infrastructure/Services/Implement => Umbraco.Core/Services}/TwoFactorLoginService.cs (100%) create mode 100644 src/Umbraco.Infrastructure/Persistence/Repositories/Implement/IdKeyMapRepository.cs delete mode 100644 src/Umbraco.Infrastructure/PropertyEditors/EmailAddressConfigurationEditor.cs delete mode 100644 src/Umbraco.Infrastructure/PropertyEditors/FileUploadConfigurationEditor.cs delete mode 100644 src/Umbraco.Infrastructure/PropertyEditors/ListViewConfigurationEditor.cs delete mode 100644 src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerConfigurationEditor.cs delete mode 100644 src/Umbraco.Infrastructure/PropertyEditors/NestedContentConfigurationEditor.cs delete mode 100644 src/Umbraco.Infrastructure/PropertyEditors/RichTextConfigurationEditor.cs delete mode 100644 src/Umbraco.Infrastructure/PropertyEditors/SliderConfigurationEditor.cs delete mode 100644 src/Umbraco.Infrastructure/PropertyEditors/TextAreaConfigurationEditor.cs delete mode 100644 src/Umbraco.Infrastructure/PropertyEditors/TextboxConfigurationEditor.cs delete mode 100644 src/Umbraco.Infrastructure/PropertyEditors/TrueFalseConfigurationEditor.cs create mode 100644 src/Umbraco.Infrastructure/Services/CacheInstructionService.cs create mode 100644 src/Umbraco.Infrastructure/Services/EditorConfigurationParser.cs delete mode 100644 src/Umbraco.Infrastructure/Services/Implement/CacheInstructionService.cs create mode 100644 src/Umbraco.Web.Common/Mvc/IpAddressUtilities.cs diff --git a/src/Umbraco.Core/Constants-Audit.cs b/src/Umbraco.Core/Constants-Audit.cs new file mode 100644 index 0000000000..54c51c95ff --- /dev/null +++ b/src/Umbraco.Core/Constants-Audit.cs @@ -0,0 +1,11 @@ +namespace Umbraco.Cms.Core; + +public static partial class Constants +{ + public static class Audit + { + public const int IpLength = 64; + public const int EventTypeLength = 256; + public const int DetailsLength = 1024; + } +} diff --git a/src/Umbraco.Core/Persistence/Repositories/IIdKeyMapRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IIdKeyMapRepository.cs new file mode 100644 index 0000000000..b2c7bc9aa1 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Repositories/IIdKeyMapRepository.cs @@ -0,0 +1,10 @@ +using System; +using Umbraco.Cms.Core.Models; + +namespace Umbraco.Cms.Core.Persistence.Repositories; + +public interface IIdKeyMapRepository +{ + int? GetIdForKey(Guid key, UmbracoObjectTypes umbracoObjectType); + Guid? GetIdForKey(int id, UmbracoObjectTypes umbracoObjectType); +} diff --git a/src/Umbraco.Core/Persistence/Repositories/IServerRegistrationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IServerRegistrationRepository.cs index b76b46a82a..af3555160e 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IServerRegistrationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IServerRegistrationRepository.cs @@ -6,5 +6,7 @@ namespace Umbraco.Cms.Core.Persistence.Repositories public interface IServerRegistrationRepository : IReadWriteQueryRepository { void DeactiveStaleServers(TimeSpan staleTimeout); + + void ClearCache(); } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ConfigurationEditorOfTConfiguration.cs b/src/Umbraco.Core/PropertyEditors/ConfigurationEditorOfTConfiguration.cs similarity index 71% rename from src/Umbraco.Infrastructure/PropertyEditors/ConfigurationEditorOfTConfiguration.cs rename to src/Umbraco.Core/PropertyEditors/ConfigurationEditorOfTConfiguration.cs index 63aed0de76..fa2427a048 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ConfigurationEditorOfTConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/ConfigurationEditorOfTConfiguration.cs @@ -4,11 +4,12 @@ using System; using System.Collections.Generic; using System.Reflection; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.Composing; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Serialization; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors @@ -19,12 +20,21 @@ namespace Umbraco.Cms.Core.PropertyEditors public abstract class ConfigurationEditor : ConfigurationEditor where TConfiguration : new() { + private readonly IEditorConfigurationParser _editorConfigurationParser; + + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + protected ConfigurationEditor(IIOHelper ioHelper) + : this(ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + /// /// Initializes a new instance of the class. /// - protected ConfigurationEditor(IIOHelper ioHelper) - : base(DiscoverFields(ioHelper)) - { } + protected ConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) + : base(DiscoverFields(ioHelper)) => + _editorConfigurationParser = editorConfigurationParser; /// /// Discovers fields from configuration properties marked with the field attribute. @@ -135,43 +145,7 @@ namespace Umbraco.Cms.Core.PropertyEditors /// /// The configuration object posted by the editor. /// The current configuration object. - public virtual TConfiguration? FromConfigurationEditor(IDictionary? editorValues, TConfiguration? configuration) - { - // note - editorValue contains a mix of CLR types (string, int...) and JToken - // turning everything back into a JToken... might not be fastest but is simplest - // for now - - var o = new JObject(); - - foreach (var field in Fields) - { - // field only, JsonPropertyAttribute is ignored here - // only keep fields that have a non-null/empty value - // rest will fall back to default during ToObject() - if (editorValues is not null && editorValues.TryGetValue(field.Key!, out var value) && value != null && (!(value is string stringValue) || !string.IsNullOrWhiteSpace(stringValue))) - { - if (value is JToken jtoken) - { - //if it's a jtoken then set it - o[field.PropertyName!] = jtoken; - } - else if (field.PropertyType == typeof(bool) && value is string sBool) - { - //if it's a boolean property type but a string is found, try to do a conversion - var converted = sBool.TryConvertTo(); - if (converted.Success) - o[field.PropertyName!] = converted.Result; - } - else - { - //default behavior - o[field.PropertyName!] = JToken.FromObject(value); - } - } - } - - return o.ToObject(); - } + public virtual TConfiguration? FromConfigurationEditor(IDictionary? editorValues, TConfiguration? configuration) => _editorConfigurationParser.ParseFromConfigurationEditor(editorValues, Fields); /// public sealed override IDictionary ToConfigurationEditor(object? configuration) @@ -183,23 +157,6 @@ namespace Umbraco.Cms.Core.PropertyEditors /// Converts configuration values to values for the editor. /// /// The configuration. - public virtual Dictionary ToConfigurationEditor(TConfiguration? configuration) - { - string FieldNamer(PropertyInfo property) - { - // try the field - var field = property.GetCustomAttribute(); - if (field is not null && field.Key is not null) - { - return field.Key; - } - - // but the property may not be a field just an extra thing - var json = property.GetCustomAttribute(); - return json?.PropertyName ?? property.Name; - } - - return ObjectJsonExtensions.ToObjectDictionary(configuration, FieldNamer); - } + public virtual Dictionary ToConfigurationEditor(TConfiguration? configuration) => _editorConfigurationParser.ParseToConfigurationEditor(configuration); } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ContentPickerConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/ContentPickerConfigurationEditor.cs similarity index 82% rename from src/Umbraco.Infrastructure/PropertyEditors/ContentPickerConfigurationEditor.cs rename to src/Umbraco.Core/PropertyEditors/ContentPickerConfigurationEditor.cs index d50efe7f61..4932030db2 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ContentPickerConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/ContentPickerConfigurationEditor.cs @@ -1,14 +1,18 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using System; using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { internal class ContentPickerConfigurationEditor : ConfigurationEditor { - public ContentPickerConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) + public ContentPickerConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) { // configure fields // this is not part of ContentPickerConfiguration, diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ContentPickerPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/ContentPickerPropertyEditor.cs similarity index 75% rename from src/Umbraco.Infrastructure/PropertyEditors/ContentPickerPropertyEditor.cs rename to src/Umbraco.Core/PropertyEditors/ContentPickerPropertyEditor.cs index f3dfaaf1c1..5ca0564e69 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ContentPickerPropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/ContentPickerPropertyEditor.cs @@ -1,7 +1,9 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using System; using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.Hosting; using Umbraco.Cms.Core.IO; @@ -10,6 +12,7 @@ using Umbraco.Cms.Core.Models.Editors; using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -26,18 +29,30 @@ namespace Umbraco.Cms.Core.PropertyEditors public class ContentPickerPropertyEditor : DataEditor { private readonly IIOHelper _ioHelper; + private readonly IEditorConfigurationParser _editorConfigurationParser; + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] public ContentPickerPropertyEditor( IDataValueEditorFactory dataValueEditorFactory, IIOHelper ioHelper) + : this(dataValueEditorFactory, ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public ContentPickerPropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + IIOHelper ioHelper, + IEditorConfigurationParser editorConfigurationParser) : base(dataValueEditorFactory) { _ioHelper = ioHelper; + _editorConfigurationParser = editorConfigurationParser; } protected override IConfigurationEditor CreateConfigurationEditor() { - return new ContentPickerConfigurationEditor(_ioHelper); + return new ContentPickerConfigurationEditor(_ioHelper, _editorConfigurationParser); } protected override IDataValueEditor CreateValueEditor() => DataValueEditorFactory.Create(Attribute!); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/DateTimeConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/DateTimeConfigurationEditor.cs similarity index 59% rename from src/Umbraco.Infrastructure/PropertyEditors/DateTimeConfigurationEditor.cs rename to src/Umbraco.Core/PropertyEditors/DateTimeConfigurationEditor.cs index bc33b16809..36c82175c2 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/DateTimeConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/DateTimeConfigurationEditor.cs @@ -1,8 +1,12 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using System; using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors @@ -23,7 +27,13 @@ namespace Umbraco.Cms.Core.PropertyEditors return d; } - public DateTimeConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public DateTimeConfigurationEditor(IIOHelper ioHelper) : this(ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public DateTimeConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) { } } diff --git a/src/Umbraco.Core/PropertyEditors/EmailAddressConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/EmailAddressConfigurationEditor.cs new file mode 100644 index 0000000000..e1e528dda2 --- /dev/null +++ b/src/Umbraco.Core/PropertyEditors/EmailAddressConfigurationEditor.cs @@ -0,0 +1,28 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + +using System; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; + +namespace Umbraco.Cms.Core.PropertyEditors +{ + /// + /// Represents the configuration editor for the email address value editor. + /// + public class EmailAddressConfigurationEditor : ConfigurationEditor + { + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public EmailAddressConfigurationEditor(IIOHelper ioHelper) + : this(ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public EmailAddressConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) + { + } + } +} diff --git a/src/Umbraco.Infrastructure/PropertyEditors/EyeDropperColorPickerConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/EyeDropperColorPickerConfigurationEditor.cs similarity index 92% rename from src/Umbraco.Infrastructure/PropertyEditors/EyeDropperColorPickerConfigurationEditor.cs rename to src/Umbraco.Core/PropertyEditors/EyeDropperColorPickerConfigurationEditor.cs index 34e3354367..49611f09b9 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/EyeDropperColorPickerConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/EyeDropperColorPickerConfigurationEditor.cs @@ -1,14 +1,13 @@ - using System.Collections.Generic; using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors { internal class EyeDropperColorPickerConfigurationEditor : ConfigurationEditor { - public EyeDropperColorPickerConfigurationEditor(IIOHelper ioHelper) - : base(ioHelper) + public EyeDropperColorPickerConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) { } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/EyeDropperColorPickerPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/EyeDropperColorPickerPropertyEditor.cs similarity index 54% rename from src/Umbraco.Infrastructure/PropertyEditors/EyeDropperColorPickerPropertyEditor.cs rename to src/Umbraco.Core/PropertyEditors/EyeDropperColorPickerPropertyEditor.cs index 98929bdf4d..e19a380334 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/EyeDropperColorPickerPropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/EyeDropperColorPickerPropertyEditor.cs @@ -1,8 +1,11 @@ -using Microsoft.Extensions.Logging; +using System; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -16,17 +19,30 @@ namespace Umbraco.Cms.Core.PropertyEditors public class EyeDropperColorPickerPropertyEditor : DataEditor { private readonly IIOHelper _ioHelper; + private readonly IEditorConfigurationParser _editorConfigurationParser; + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] public EyeDropperColorPickerPropertyEditor( IDataValueEditorFactory dataValueEditorFactory, IIOHelper ioHelper, EditorType type = EditorType.PropertyValue) + : this(dataValueEditorFactory, ioHelper, StaticServiceProvider.Instance.GetRequiredService(), type) + { + } + + public EyeDropperColorPickerPropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + IIOHelper ioHelper, + IEditorConfigurationParser editorConfigurationParser, + EditorType type = EditorType.PropertyValue) : base(dataValueEditorFactory, type) { _ioHelper = ioHelper; + _editorConfigurationParser = editorConfigurationParser; } /// - protected override IConfigurationEditor CreateConfigurationEditor() => new EyeDropperColorPickerConfigurationEditor(_ioHelper); + protected override IConfigurationEditor CreateConfigurationEditor() => new EyeDropperColorPickerConfigurationEditor(_ioHelper, _editorConfigurationParser); } } diff --git a/src/Umbraco.Core/PropertyEditors/FileUploadConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/FileUploadConfigurationEditor.cs new file mode 100644 index 0000000000..e8aa86e5d8 --- /dev/null +++ b/src/Umbraco.Core/PropertyEditors/FileUploadConfigurationEditor.cs @@ -0,0 +1,25 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; + +namespace Umbraco.Cms.Core.PropertyEditors +{ + /// + /// Represents the configuration editor for the file upload value editor. + /// + public class FileUploadConfigurationEditor : ConfigurationEditor + { + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public FileUploadConfigurationEditor(IIOHelper ioHelper) + : this(ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public FileUploadConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) + { + } + } +} diff --git a/src/Umbraco.Infrastructure/PropertyEditors/LabelConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/LabelConfigurationEditor.cs similarity index 65% rename from src/Umbraco.Infrastructure/PropertyEditors/LabelConfigurationEditor.cs rename to src/Umbraco.Core/PropertyEditors/LabelConfigurationEditor.cs index c34a1451d4..b2a214f729 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/LabelConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/LabelConfigurationEditor.cs @@ -1,8 +1,12 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using System; using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -11,7 +15,14 @@ namespace Umbraco.Cms.Core.PropertyEditors /// public class LabelConfigurationEditor : ConfigurationEditor { - public LabelConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes and IEditorConfigurationParser instead")] + public LabelConfigurationEditor(IIOHelper ioHelper) + : this(ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public LabelConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) { } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/LabelPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/LabelPropertyEditor.cs similarity index 74% rename from src/Umbraco.Infrastructure/PropertyEditors/LabelPropertyEditor.cs rename to src/Umbraco.Core/PropertyEditors/LabelPropertyEditor.cs index aa21790e60..7986b1cc0c 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/LabelPropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/LabelPropertyEditor.cs @@ -1,8 +1,7 @@ // Copyright (c) Umbraco. // See LICENSE for more details. -using Microsoft.Extensions.Logging; -using Umbraco.Cms.Core.Hosting; +using System; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Serialization; @@ -22,23 +21,33 @@ namespace Umbraco.Cms.Core.PropertyEditors public class LabelPropertyEditor : DataEditor { private readonly IIOHelper _ioHelper; + private readonly IEditorConfigurationParser _editorConfigurationParser; + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public LabelPropertyEditor(IDataValueEditorFactory dataValueEditorFactory, + IIOHelper ioHelper) + : base(dataValueEditorFactory) + { + } /// /// Initializes a new instance of the class. /// public LabelPropertyEditor(IDataValueEditorFactory dataValueEditorFactory, - IIOHelper ioHelper) + IIOHelper ioHelper, + IEditorConfigurationParser editorConfigurationParser) : base(dataValueEditorFactory) { _ioHelper = ioHelper; + _editorConfigurationParser = editorConfigurationParser; } /// protected override IDataValueEditor CreateValueEditor() => DataValueEditorFactory.Create(Attribute!); /// - protected override IConfigurationEditor CreateConfigurationEditor() => new LabelConfigurationEditor(_ioHelper); + protected override IConfigurationEditor CreateConfigurationEditor() => new LabelConfigurationEditor(_ioHelper, _editorConfigurationParser); // provides the property value editor internal class LabelPropertyValueEditor : DataValueEditor diff --git a/src/Umbraco.Core/PropertyEditors/ListViewConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/ListViewConfigurationEditor.cs new file mode 100644 index 0000000000..d673ce4ee6 --- /dev/null +++ b/src/Umbraco.Core/PropertyEditors/ListViewConfigurationEditor.cs @@ -0,0 +1,28 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + +using System; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; + +namespace Umbraco.Cms.Core.PropertyEditors +{ + /// + /// Represents the configuration editor for the listview value editor. + /// + public class ListViewConfigurationEditor : ConfigurationEditor + { + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public ListViewConfigurationEditor(IIOHelper ioHelper) + : this(ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public ListViewConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) + { + } + } +} diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MarkdownConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/MarkdownConfigurationEditor.cs similarity index 65% rename from src/Umbraco.Infrastructure/PropertyEditors/MarkdownConfigurationEditor.cs rename to src/Umbraco.Core/PropertyEditors/MarkdownConfigurationEditor.cs index 088a36b6c8..3f9bc61275 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MarkdownConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/MarkdownConfigurationEditor.cs @@ -2,6 +2,7 @@ // See LICENSE for more details. using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; namespace Umbraco.Cms.Core.PropertyEditors { @@ -10,7 +11,7 @@ namespace Umbraco.Cms.Core.PropertyEditors /// internal class MarkdownConfigurationEditor : ConfigurationEditor { - public MarkdownConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) + public MarkdownConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) { } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MarkdownPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/MarkdownPropertyEditor.cs similarity index 56% rename from src/Umbraco.Infrastructure/PropertyEditors/MarkdownPropertyEditor.cs rename to src/Umbraco.Core/PropertyEditors/MarkdownPropertyEditor.cs index 01dab994f9..6db2ac552e 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MarkdownPropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/MarkdownPropertyEditor.cs @@ -1,11 +1,11 @@ // Copyright (c) Umbraco. // See LICENSE for more details. -using Microsoft.Extensions.Logging; +using System; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; -using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Core.Strings; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -22,19 +22,31 @@ namespace Umbraco.Cms.Core.PropertyEditors public class MarkdownPropertyEditor : DataEditor { private readonly IIOHelper _ioHelper; + private readonly IEditorConfigurationParser _editorConfigurationParser; + + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public MarkdownPropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + IIOHelper ioHelper) + : this(dataValueEditorFactory, ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } /// /// Initializes a new instance of the class. /// public MarkdownPropertyEditor( IDataValueEditorFactory dataValueEditorFactory, - IIOHelper ioHelper) + IIOHelper ioHelper, + IEditorConfigurationParser editorConfigurationParser) : base(dataValueEditorFactory) { _ioHelper = ioHelper; + _editorConfigurationParser = editorConfigurationParser; } /// - protected override IConfigurationEditor CreateConfigurationEditor() => new MarkdownConfigurationEditor(_ioHelper); + protected override IConfigurationEditor CreateConfigurationEditor() => new MarkdownConfigurationEditor(_ioHelper, _editorConfigurationParser); } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MediaPicker3ConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/MediaPicker3ConfigurationEditor.cs similarity index 62% rename from src/Umbraco.Infrastructure/PropertyEditors/MediaPicker3ConfigurationEditor.cs rename to src/Umbraco.Core/PropertyEditors/MediaPicker3ConfigurationEditor.cs index faa171eb40..c5ab1c403c 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MediaPicker3ConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/MediaPicker3ConfigurationEditor.cs @@ -1,5 +1,9 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -8,10 +12,17 @@ namespace Umbraco.Cms.Core.PropertyEditors /// public class MediaPicker3ConfigurationEditor : ConfigurationEditor { + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public MediaPicker3ConfigurationEditor(IIOHelper ioHelper) + : this(ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + /// /// Initializes a new instance of the class. /// - public MediaPicker3ConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) + public MediaPicker3ConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) { // configure fields // this is not part of ContentPickerConfiguration, diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MediaPickerConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/MediaPickerConfigurationEditor.cs similarity index 69% rename from src/Umbraco.Infrastructure/PropertyEditors/MediaPickerConfigurationEditor.cs rename to src/Umbraco.Core/PropertyEditors/MediaPickerConfigurationEditor.cs index f0e009f3ac..a3dbbc04d7 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MediaPickerConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/MediaPickerConfigurationEditor.cs @@ -1,8 +1,12 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using System; using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -11,10 +15,17 @@ namespace Umbraco.Cms.Core.PropertyEditors /// public class MediaPickerConfigurationEditor : ConfigurationEditor { + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public MediaPickerConfigurationEditor(IIOHelper ioHelper) + : this(ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + /// /// Initializes a new instance of the class. /// - public MediaPickerConfigurationEditor(IIOHelper ioHelper): base(ioHelper) + public MediaPickerConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) { // configure fields // this is not part of ContentPickerConfiguration, diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MultiNodePickerConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/MultiNodePickerConfigurationEditor.cs similarity index 70% rename from src/Umbraco.Infrastructure/PropertyEditors/MultiNodePickerConfigurationEditor.cs rename to src/Umbraco.Core/PropertyEditors/MultiNodePickerConfigurationEditor.cs index 41d2861cb3..aa66be9d39 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MultiNodePickerConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/MultiNodePickerConfigurationEditor.cs @@ -1,8 +1,12 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using System; using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -11,7 +15,14 @@ namespace Umbraco.Cms.Core.PropertyEditors /// public class MultiNodePickerConfigurationEditor : ConfigurationEditor { - public MultiNodePickerConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public MultiNodePickerConfigurationEditor(IIOHelper ioHelper) + : this(ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public MultiNodePickerConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) { Field(nameof(MultiNodePickerConfiguration.TreeSource)) .Config = new Dictionary { { "idType", "udi" } }; diff --git a/src/Umbraco.Core/PropertyEditors/MultiUrlPickerConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/MultiUrlPickerConfigurationEditor.cs new file mode 100644 index 0000000000..f5baa18c04 --- /dev/null +++ b/src/Umbraco.Core/PropertyEditors/MultiUrlPickerConfigurationEditor.cs @@ -0,0 +1,26 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + +using System; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; + +namespace Umbraco.Cms.Core.PropertyEditors +{ + public class MultiUrlPickerConfigurationEditor : ConfigurationEditor + { + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public MultiUrlPickerConfigurationEditor(IIOHelper ioHelper) + : this(ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + + { + } + + public MultiUrlPickerConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) + { + } + } +} diff --git a/src/Umbraco.Core/PropertyEditors/NestedContentConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/NestedContentConfigurationEditor.cs new file mode 100644 index 0000000000..bab2038d2d --- /dev/null +++ b/src/Umbraco.Core/PropertyEditors/NestedContentConfigurationEditor.cs @@ -0,0 +1,28 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + +using System; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; + +namespace Umbraco.Cms.Core.PropertyEditors +{ + /// + /// Represents the configuration editor for the nested content value editor. + /// + public class NestedContentConfigurationEditor : ConfigurationEditor + { + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public NestedContentConfigurationEditor(IIOHelper ioHelper) + : this(ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public NestedContentConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) + { + } + } +} diff --git a/src/Umbraco.Core/PropertyEditors/RichTextConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/RichTextConfigurationEditor.cs new file mode 100644 index 0000000000..a967ec2367 --- /dev/null +++ b/src/Umbraco.Core/PropertyEditors/RichTextConfigurationEditor.cs @@ -0,0 +1,28 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + +using System; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; + +namespace Umbraco.Cms.Core.PropertyEditors +{ + /// + /// Represents the configuration editor for the rich text value editor. + /// + public class RichTextConfigurationEditor : ConfigurationEditor + { + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public RichTextConfigurationEditor(IIOHelper ioHelper) + : this(ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public RichTextConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) + { + } + } +} diff --git a/src/Umbraco.Core/PropertyEditors/SliderConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/SliderConfigurationEditor.cs new file mode 100644 index 0000000000..6cd9db8399 --- /dev/null +++ b/src/Umbraco.Core/PropertyEditors/SliderConfigurationEditor.cs @@ -0,0 +1,28 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + +using System; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; + +namespace Umbraco.Cms.Core.PropertyEditors +{ + /// + /// Represents the configuration editor for the slider value editor. + /// + public class SliderConfigurationEditor : ConfigurationEditor + { + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public SliderConfigurationEditor(IIOHelper ioHelper) + : this(ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public SliderConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) + { + } + } +} diff --git a/src/Umbraco.Infrastructure/PropertyEditors/TagConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/TagConfigurationEditor.cs similarity index 76% rename from src/Umbraco.Infrastructure/PropertyEditors/TagConfigurationEditor.cs rename to src/Umbraco.Core/PropertyEditors/TagConfigurationEditor.cs index 7cd33e0066..2f77642e5f 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/TagConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/TagConfigurationEditor.cs @@ -3,10 +3,12 @@ using System; using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.PropertyEditors.Validators; using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -15,7 +17,14 @@ namespace Umbraco.Cms.Core.PropertyEditors /// public class TagConfigurationEditor : ConfigurationEditor { - public TagConfigurationEditor(ManifestValueValidatorCollection validators, IIOHelper ioHelper, ILocalizedTextService localizedTextService) : base(ioHelper) + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public TagConfigurationEditor(ManifestValueValidatorCollection validators, IIOHelper ioHelper, ILocalizedTextService localizedTextService) + : this(validators, ioHelper, localizedTextService, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public TagConfigurationEditor(ManifestValueValidatorCollection validators, IIOHelper ioHelper, ILocalizedTextService localizedTextService, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) { Field(nameof(TagConfiguration.Group)).Validators.Add(new RequiredValidator(localizedTextService)); Field(nameof(TagConfiguration.StorageType)).Validators.Add(new RequiredValidator(localizedTextService)); diff --git a/src/Umbraco.Core/PropertyEditors/TextAreaConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/TextAreaConfigurationEditor.cs new file mode 100644 index 0000000000..4fa4e7908c --- /dev/null +++ b/src/Umbraco.Core/PropertyEditors/TextAreaConfigurationEditor.cs @@ -0,0 +1,28 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + +using System; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; + +namespace Umbraco.Cms.Core.PropertyEditors +{ + /// + /// Represents the configuration editor for the textarea value editor. + /// + public class TextAreaConfigurationEditor : ConfigurationEditor + { + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public TextAreaConfigurationEditor(IIOHelper ioHelper) + : this(ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public TextAreaConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) + { + } + } +} diff --git a/src/Umbraco.Core/PropertyEditors/TextboxConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/TextboxConfigurationEditor.cs new file mode 100644 index 0000000000..81ea1f07b8 --- /dev/null +++ b/src/Umbraco.Core/PropertyEditors/TextboxConfigurationEditor.cs @@ -0,0 +1,28 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + +using System; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; + +namespace Umbraco.Cms.Core.PropertyEditors +{ + /// + /// Represents the configuration editor for the textbox value editor. + /// + public class TextboxConfigurationEditor : ConfigurationEditor + { + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public TextboxConfigurationEditor(IIOHelper ioHelper) + : this(ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public TextboxConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) + { + } + } +} diff --git a/src/Umbraco.Core/PropertyEditors/TrueFalseConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/TrueFalseConfigurationEditor.cs new file mode 100644 index 0000000000..d5210edc87 --- /dev/null +++ b/src/Umbraco.Core/PropertyEditors/TrueFalseConfigurationEditor.cs @@ -0,0 +1,28 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + +using System; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; + +namespace Umbraco.Cms.Core.PropertyEditors +{ + /// + /// Represents the configuration editor for the boolean value editor. + /// + public class TrueFalseConfigurationEditor : ConfigurationEditor + { + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public TrueFalseConfigurationEditor(IIOHelper ioHelper) + : this(ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public TrueFalseConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) + { + } + } +} diff --git a/src/Umbraco.Infrastructure/Security/BackOfficeIdentityOptions.cs b/src/Umbraco.Core/Security/BackOfficeIdentityOptions.cs similarity index 100% rename from src/Umbraco.Infrastructure/Security/BackOfficeIdentityOptions.cs rename to src/Umbraco.Core/Security/BackOfficeIdentityOptions.cs diff --git a/src/Umbraco.Infrastructure/Security/ITwoFactorProvider.cs b/src/Umbraco.Core/Security/ITwoFactorProvider.cs similarity index 100% rename from src/Umbraco.Infrastructure/Security/ITwoFactorProvider.cs rename to src/Umbraco.Core/Security/ITwoFactorProvider.cs diff --git a/src/Umbraco.Infrastructure/Services/Implement/AuditService.cs b/src/Umbraco.Core/Services/AuditService.cs similarity index 94% rename from src/Umbraco.Infrastructure/Services/Implement/AuditService.cs rename to src/Umbraco.Core/Services/AuditService.cs index 339ac1adee..e9a35f80ba 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/AuditService.cs +++ b/src/Umbraco.Core/Services/AuditService.cs @@ -7,7 +7,6 @@ using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Persistence.Querying; using Umbraco.Cms.Core.Persistence.Repositories; using Umbraco.Cms.Core.Scoping; -using Umbraco.Cms.Infrastructure.Persistence.Dtos; namespace Umbraco.Cms.Core.Services.Implement { @@ -164,17 +163,17 @@ namespace Umbraco.Cms.Core.Services.Implement if (string.IsNullOrWhiteSpace(eventDetails)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(eventDetails)); //we need to truncate the data else we'll get SQL errors - affectedDetails = affectedDetails?.Substring(0, Math.Min(affectedDetails.Length, AuditEntryDto.DetailsLength)); - eventDetails = eventDetails.Substring(0, Math.Min(eventDetails.Length, AuditEntryDto.DetailsLength)); + affectedDetails = affectedDetails?.Substring(0, Math.Min(affectedDetails.Length, Constants.Audit.DetailsLength)); + eventDetails = eventDetails.Substring(0, Math.Min(eventDetails.Length, Constants.Audit.DetailsLength)); //validate the eventType - must contain a forward slash, no spaces, no special chars var eventTypeParts = eventType.ToCharArray(); if (eventTypeParts.Contains('/') == false || eventTypeParts.All(c => char.IsLetterOrDigit(c) || c == '/' || c == '-') == false) throw new ArgumentException(nameof(eventType) + " must contain only alphanumeric characters, hyphens and at least one '/' defining a category"); - if (eventType.Length > AuditEntryDto.EventTypeLength) - throw new ArgumentException($"Must be max {AuditEntryDto.EventTypeLength} chars.", nameof(eventType)); - if (performingIp != null && performingIp.Length > AuditEntryDto.IpLength) - throw new ArgumentException($"Must be max {AuditEntryDto.EventTypeLength} chars.", nameof(performingIp)); + if (eventType.Length > Constants.Audit.EventTypeLength) + throw new ArgumentException($"Must be max {Constants.Audit.EventTypeLength} chars.", nameof(eventType)); + if (performingIp != null && performingIp.Length > Constants.Audit.IpLength) + throw new ArgumentException($"Must be max {Constants.Audit.EventTypeLength} chars.", nameof(performingIp)); var entry = new AuditEntry { @@ -185,7 +184,7 @@ namespace Umbraco.Cms.Core.Services.Implement AffectedUserId = affectedUserId, AffectedDetails = affectedDetails, EventType = eventType, - EventDetails = eventDetails + EventDetails = eventDetails, }; if (_isAvailable.Value == false) return entry; diff --git a/src/Umbraco.Infrastructure/Services/Implement/BasicAuthService.cs b/src/Umbraco.Core/Services/BasicAuthService.cs similarity index 57% rename from src/Umbraco.Infrastructure/Services/Implement/BasicAuthService.cs rename to src/Umbraco.Core/Services/BasicAuthService.cs index 9e413b7162..ebc102b093 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/BasicAuthService.cs +++ b/src/Umbraco.Core/Services/BasicAuthService.cs @@ -1,3 +1,4 @@ +using System; using System.Net; using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Configuration.Models; @@ -6,8 +7,11 @@ namespace Umbraco.Cms.Core.Services.Implement { public class BasicAuthService : IBasicAuthService { + private readonly IIpAddressUtilities _ipAddressUtilities; private BasicAuthSettings _basicAuthSettings; + // Scheduled for removal in v12 + [Obsolete("Please use the contructor that takes an IIpadressUtilities instead")] public BasicAuthService(IOptionsMonitor optionsMonitor) { _basicAuthSettings = optionsMonitor.CurrentValue; @@ -15,13 +19,21 @@ namespace Umbraco.Cms.Core.Services.Implement optionsMonitor.OnChange(basicAuthSettings => _basicAuthSettings = basicAuthSettings); } + public BasicAuthService(IOptionsMonitor optionsMonitor, IIpAddressUtilities ipAddressUtilities) + { + _ipAddressUtilities = ipAddressUtilities; + _basicAuthSettings = optionsMonitor.CurrentValue; + + optionsMonitor.OnChange(basicAuthSettings => _basicAuthSettings = basicAuthSettings); + } + public bool IsBasicAuthEnabled() => _basicAuthSettings.Enabled; public bool IsIpAllowListed(IPAddress clientIpAddress) { foreach (var allowedIpString in _basicAuthSettings.AllowedIPs) { - if (IPNetwork.TryParse(allowedIpString, out IPNetwork allowedIp) && allowedIp.Contains(clientIpAddress)) + if (_ipAddressUtilities.IsAllowListed(clientIpAddress, allowedIpString)) { return true; } diff --git a/src/Umbraco.Infrastructure/Services/Implement/DataTypeService.cs b/src/Umbraco.Core/Services/DataTypeService.cs similarity index 100% rename from src/Umbraco.Infrastructure/Services/Implement/DataTypeService.cs rename to src/Umbraco.Core/Services/DataTypeService.cs diff --git a/src/Umbraco.Core/Services/IEditorConfigurationParser.cs b/src/Umbraco.Core/Services/IEditorConfigurationParser.cs new file mode 100644 index 0000000000..8dc1210d11 --- /dev/null +++ b/src/Umbraco.Core/Services/IEditorConfigurationParser.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using Umbraco.Cms.Core.PropertyEditors; + +namespace Umbraco.Cms.Core.Services; + +public interface IEditorConfigurationParser +{ + TConfiguration? ParseFromConfigurationEditor(IDictionary? editorValues, IEnumerable fields); + + Dictionary ParseToConfigurationEditor(TConfiguration? configuration); +} diff --git a/src/Umbraco.Core/Services/IIpAddressUtilities.cs b/src/Umbraco.Core/Services/IIpAddressUtilities.cs new file mode 100644 index 0000000000..7c68bcfa9f --- /dev/null +++ b/src/Umbraco.Core/Services/IIpAddressUtilities.cs @@ -0,0 +1,8 @@ +using System.Net; + +namespace Umbraco.Cms.Core.Services; + +public interface IIpAddressUtilities +{ + bool IsAllowListed(IPAddress clientIpAddress, string allowedIpString); +} diff --git a/src/Umbraco.Infrastructure/Services/IdKeyMap.cs b/src/Umbraco.Core/Services/IdKeyMap.cs similarity index 85% rename from src/Umbraco.Infrastructure/Services/IdKeyMap.cs rename to src/Umbraco.Core/Services/IdKeyMap.cs index 2ca1508d0b..00acb7ad04 100644 --- a/src/Umbraco.Infrastructure/Services/IdKeyMap.cs +++ b/src/Umbraco.Core/Services/IdKeyMap.cs @@ -3,24 +3,24 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Persistence.Repositories; using Umbraco.Cms.Core.Scoping; -using Umbraco.Cms.Infrastructure.Scoping; namespace Umbraco.Cms.Core.Services { public class IdKeyMap : IIdKeyMap,IDisposable { private readonly ICoreScopeProvider _scopeProvider; - private readonly IScopeAccessor _scopeAccessor; + private readonly IIdKeyMapRepository _idKeyMapRepository; private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim(); private readonly Dictionary> _id2Key = new Dictionary>(); private readonly Dictionary> _key2Id = new Dictionary>(); - public IdKeyMap(ICoreScopeProvider scopeProvider, IScopeAccessor scopeAccessor) + public IdKeyMap(ICoreScopeProvider scopeProvider, IIdKeyMapRepository idKeyMapRepository) { _scopeProvider = scopeProvider; - _scopeAccessor = scopeAccessor; + _idKeyMapRepository = idKeyMapRepository; } // note - for pure read-only we might want to *not* enforce a transaction? @@ -170,16 +170,7 @@ namespace Umbraco.Cms.Core.Services { using (var scope = _scopeProvider.CreateCoreScope()) { - //if it's unknown don't include the nodeObjectType in the query - if (umbracoObjectType == UmbracoObjectTypes.Unknown) - { - val = _scopeAccessor.AmbientScope?.Database.ExecuteScalar("SELECT id FROM umbracoNode WHERE uniqueId=@id", new { id = key}); - } - else - { - val = _scopeAccessor.AmbientScope?.Database.ExecuteScalar("SELECT id FROM umbracoNode WHERE uniqueId=@id AND (nodeObjectType=@type OR nodeObjectType=@reservation)", - new { id = key, type = GetNodeObjectTypeGuid(umbracoObjectType), reservation = Cms.Core.Constants.ObjectTypes.IdReservation }); - } + val = _idKeyMapRepository.GetIdForKey(key, umbracoObjectType); scope.Complete(); } } @@ -258,16 +249,7 @@ namespace Umbraco.Cms.Core.Services { using (var scope = _scopeProvider.CreateCoreScope()) { - //if it's unknown don't include the nodeObjectType in the query - if (umbracoObjectType == UmbracoObjectTypes.Unknown) - { - val = _scopeAccessor.AmbientScope?.Database.ExecuteScalar("SELECT uniqueId FROM umbracoNode WHERE id=@id", new { id }); - } - else - { - val = _scopeAccessor.AmbientScope?.Database.ExecuteScalar("SELECT uniqueId FROM umbracoNode WHERE id=@id AND (nodeObjectType=@type OR nodeObjectType=@reservation)", - new { id, type = GetNodeObjectTypeGuid(umbracoObjectType), reservation = Cms.Core.Constants.ObjectTypes.IdReservation }); - } + val = _idKeyMapRepository.GetIdForKey(id, umbracoObjectType); scope.Complete(); } } @@ -293,14 +275,6 @@ namespace Umbraco.Cms.Core.Services return Attempt.Succeed(val.Value); } - private static Guid GetNodeObjectTypeGuid(UmbracoObjectTypes umbracoObjectType) - { - var guid = umbracoObjectType.GetGuid(); - if (guid == Guid.Empty) - throw new NotSupportedException("Unsupported object type (" + umbracoObjectType + ")."); - return guid; - } - // invoked on UnpublishedPageCacheRefresher.RefreshAll // anything else will use the id-specific overloads public void ClearCache() diff --git a/src/Umbraco.Infrastructure/Services/Implement/ServerRegistrationService.cs b/src/Umbraco.Core/Services/ServerRegistrationService.cs similarity index 94% rename from src/Umbraco.Infrastructure/Services/Implement/ServerRegistrationService.cs rename to src/Umbraco.Core/Services/ServerRegistrationService.cs index 38ec668c85..c92977aab0 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/ServerRegistrationService.cs +++ b/src/Umbraco.Core/Services/ServerRegistrationService.cs @@ -8,7 +8,6 @@ using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Persistence.Repositories; using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Core.Sync; -using Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement; using Umbraco.Extensions; namespace Umbraco.Cms.Core.Services.Implement @@ -50,7 +49,7 @@ namespace Umbraco.Cms.Core.Services.Implement { scope.WriteLock(Cms.Core.Constants.Locks.Servers); - ((ServerRegistrationRepository) _serverRegistrationRepository).ClearCache(); // ensure we have up-to-date cache + _serverRegistrationRepository.ClearCache(); // ensure we have up-to-date cache var regs = _serverRegistrationRepository.GetMany()?.ToArray(); var hasSchedulingPublisher = regs?.Any(x => ((ServerRegistration) x).IsSchedulingPublisher); @@ -99,7 +98,7 @@ namespace Umbraco.Cms.Core.Services.Implement { scope.WriteLock(Cms.Core.Constants.Locks.Servers); - ((ServerRegistrationRepository) _serverRegistrationRepository).ClearCache(); // ensure we have up-to-date cache // ensure we have up-to-date cache + _serverRegistrationRepository.ClearCache(); // ensure we have up-to-date cache // ensure we have up-to-date cache var server = _serverRegistrationRepository.GetMany()?.FirstOrDefault(x => x.ServerIdentity?.InvariantEquals(serverIdentity) ?? false); if (server == null) return; @@ -151,7 +150,7 @@ namespace Umbraco.Cms.Core.Services.Implement scope.ReadLock(Cms.Core.Constants.Locks.Servers); if (refresh) { - ((ServerRegistrationRepository)_serverRegistrationRepository).ClearCache(); + _serverRegistrationRepository.ClearCache(); } return _serverRegistrationRepository.GetMany().ToArray(); // fast, cached // fast, cached diff --git a/src/Umbraco.Infrastructure/Services/Implement/TwoFactorLoginService.cs b/src/Umbraco.Core/Services/TwoFactorLoginService.cs similarity index 100% rename from src/Umbraco.Infrastructure/Services/Implement/TwoFactorLoginService.cs rename to src/Umbraco.Core/Services/TwoFactorLoginService.cs diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 448c2b1c6f..9a6cffeb97 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -20,6 +20,7 @@ + diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs index 2a429fc6c5..a2ab3ca861 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs @@ -55,6 +55,7 @@ using Umbraco.Cms.Infrastructure.Runtime; using Umbraco.Cms.Infrastructure.Scoping; using Umbraco.Cms.Infrastructure.Search; using Umbraco.Cms.Infrastructure.Serialization; +using Umbraco.Cms.Infrastructure.Services; using Umbraco.Cms.Infrastructure.Services.Implement; using Umbraco.Extensions; @@ -209,7 +210,6 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection // Services required to run background jobs (with out the handler) builder.Services.AddSingleton(); - return builder; } diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Repositories.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Repositories.cs index 7ae70440cc..f1d3e38ac2 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Repositories.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Repositories.cs @@ -66,6 +66,7 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection builder.Services.AddUnique(); builder.Services.AddUnique(); builder.Services.AddUnique(); + builder.Services.AddUnique(); return builder; } diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs index d31a81b402..c9d132c296 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs @@ -16,10 +16,12 @@ using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Services.Implement; using Umbraco.Cms.Infrastructure.Packaging; using Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement; +using Umbraco.Cms.Infrastructure.Services; using Umbraco.Cms.Infrastructure.Services.Implement; using Umbraco.Cms.Infrastructure.Telemetry.Providers; using Umbraco.Cms.Infrastructure.Templates; using Umbraco.Extensions; +using CacheInstructionService = Umbraco.Cms.Core.Services.Implement.CacheInstructionService; namespace Umbraco.Cms.Infrastructure.DependencyInjection { @@ -52,6 +54,8 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection builder.Services.AddTransient(); builder.Services.AddUnique(); builder.Services.AddTransient(); + builder.Services.AddTransient(); + return builder; } diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs index b4f6b5cf9d..0d4b6020a9 100644 --- a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs +++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_8_0_0/DropDownPropertyEditorsMigration.cs @@ -1,13 +1,16 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.PropertyEditors; using Umbraco.Cms.Core.Serialization; +using Umbraco.Cms.Core.Services; using Umbraco.Cms.Infrastructure.Migrations.PostMigrations; using Umbraco.Cms.Infrastructure.Persistence.Dtos; +using Umbraco.Cms.Web.Common.DependencyInjection; using Umbraco.Extensions; namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0 @@ -16,12 +19,23 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0 { private readonly IIOHelper _ioHelper; private readonly IConfigurationEditorJsonSerializer _configurationEditorJsonSerializer; + private readonly IEditorConfigurationParser _editorConfigurationParser; public DropDownPropertyEditorsMigration(IMigrationContext context, IIOHelper ioHelper, IConfigurationEditorJsonSerializer configurationEditorJsonSerializer) + : this(context, ioHelper, configurationEditorJsonSerializer, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public DropDownPropertyEditorsMigration( + IMigrationContext context, + IIOHelper ioHelper, + IConfigurationEditorJsonSerializer configurationEditorJsonSerializer, + IEditorConfigurationParser editorConfigurationParser) : base(context) { _ioHelper = ioHelper; _configurationEditorJsonSerializer = configurationEditorJsonSerializer; + _editorConfigurationParser = editorConfigurationParser; } protected override void Migrate() @@ -47,7 +61,7 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0 { // parse configuration, and update everything accordingly if (configurationEditor == null) - configurationEditor = new ValueListConfigurationEditor(_ioHelper); + configurationEditor = new ValueListConfigurationEditor(_ioHelper, _editorConfigurationParser); try { config = (ValueListConfiguration) configurationEditor.FromDatabase(dataType.Configuration, _configurationEditorJsonSerializer); diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_8_0_0/MergeDateAndDateTimePropertyEditor.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_8_0_0/MergeDateAndDateTimePropertyEditor.cs index a324204921..db7766213c 100644 --- a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_8_0_0/MergeDateAndDateTimePropertyEditor.cs +++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_8_0_0/MergeDateAndDateTimePropertyEditor.cs @@ -1,10 +1,13 @@ using System; using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.PropertyEditors; using Umbraco.Cms.Core.Serialization; +using Umbraco.Cms.Core.Services; using Umbraco.Cms.Infrastructure.Persistence.Dtos; +using Umbraco.Cms.Web.Common.DependencyInjection; using Umbraco.Extensions; namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0 @@ -13,12 +16,21 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0 { private readonly IIOHelper _ioHelper; private readonly IConfigurationEditorJsonSerializer _configurationEditorJsonSerializer; + private readonly IEditorConfigurationParser _editorConfigurationParser; + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] public MergeDateAndDateTimePropertyEditor(IMigrationContext context, IIOHelper ioHelper, IConfigurationEditorJsonSerializer configurationEditorJsonSerializer) + : this(context, ioHelper, configurationEditorJsonSerializer, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public MergeDateAndDateTimePropertyEditor(IMigrationContext context, IIOHelper ioHelper, IConfigurationEditorJsonSerializer configurationEditorJsonSerializer, IEditorConfigurationParser editorConfigurationParser) : base(context) { _ioHelper = ioHelper; _configurationEditorJsonSerializer = configurationEditorJsonSerializer; + _editorConfigurationParser = editorConfigurationParser; } protected override void Migrate() @@ -30,7 +42,7 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0 DateTimeConfiguration config; try { - config = (DateTimeConfiguration) new CustomDateTimeConfigurationEditor(_ioHelper).FromDatabase( + config = (DateTimeConfiguration) new CustomDateTimeConfigurationEditor(_ioHelper, _editorConfigurationParser).FromDatabase( dataType.Configuration, _configurationEditorJsonSerializer); // If the Umbraco.Date type is the default from V7 and it has never been updated, then the @@ -76,7 +88,7 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0 private class CustomDateTimeConfigurationEditor : ConfigurationEditor { - public CustomDateTimeConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) + public CustomDateTimeConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) { } } diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_8_0_0/PropertyEditorsMigrationBase.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_8_0_0/PropertyEditorsMigrationBase.cs index 92f2e7d4b5..321da13df8 100644 --- a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_8_0_0/PropertyEditorsMigrationBase.cs +++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_8_0_0/PropertyEditorsMigrationBase.cs @@ -7,6 +7,7 @@ using Newtonsoft.Json; using Umbraco.Cms.Core; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.PropertyEditors; +using Umbraco.Cms.Core.Services; using Umbraco.Cms.Infrastructure.Persistence.Dtos; using Umbraco.Extensions; @@ -96,7 +97,7 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0 // dummy editor for deserialization protected class ValueListConfigurationEditor : ConfigurationEditor { - public ValueListConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) + public ValueListConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) { } } diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_8_0_0/RadioAndCheckboxPropertyEditorsMigration.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_8_0_0/RadioAndCheckboxPropertyEditorsMigration.cs index f462510a2a..f7114fb0bd 100644 --- a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_8_0_0/RadioAndCheckboxPropertyEditorsMigration.cs +++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_8_0_0/RadioAndCheckboxPropertyEditorsMigration.cs @@ -1,13 +1,16 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.PropertyEditors; using Umbraco.Cms.Core.Serialization; +using Umbraco.Cms.Core.Services; using Umbraco.Cms.Infrastructure.Migrations.PostMigrations; using Umbraco.Cms.Infrastructure.Persistence.Dtos; +using Umbraco.Cms.Web.Common.DependencyInjection; using Umbraco.Extensions; namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0 @@ -16,15 +19,26 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0 { private readonly IIOHelper _ioHelper; private readonly IConfigurationEditorJsonSerializer _configurationEditorJsonSerializer; + private readonly IEditorConfigurationParser _editorConfigurationParser; public RadioAndCheckboxPropertyEditorsMigration( IMigrationContext context, IIOHelper ioHelper, IConfigurationEditorJsonSerializer configurationEditorJsonSerializer) + : this(context, ioHelper, configurationEditorJsonSerializer, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public RadioAndCheckboxPropertyEditorsMigration( + IMigrationContext context, + IIOHelper ioHelper, + IConfigurationEditorJsonSerializer configurationEditorJsonSerializer, + IEditorConfigurationParser editorConfigurationParser) : base(context) { _ioHelper = ioHelper; _configurationEditorJsonSerializer = configurationEditorJsonSerializer; + _editorConfigurationParser = editorConfigurationParser; } protected override void Migrate() @@ -54,7 +68,7 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0 // parse configuration, and update everything accordingly if (configurationEditor == null) - configurationEditor = new ValueListConfigurationEditor(_ioHelper); + configurationEditor = new ValueListConfigurationEditor(_ioHelper, _editorConfigurationParser); try { config = (ValueListConfiguration) configurationEditor.FromDatabase(dataType.Configuration, _configurationEditorJsonSerializer); diff --git a/src/Umbraco.Infrastructure/Persistence/Dtos/AuditEntryDto.cs b/src/Umbraco.Infrastructure/Persistence/Dtos/AuditEntryDto.cs index 0bfc517aa6..18ffda302e 100644 --- a/src/Umbraco.Infrastructure/Persistence/Dtos/AuditEntryDto.cs +++ b/src/Umbraco.Infrastructure/Persistence/Dtos/AuditEntryDto.cs @@ -1,5 +1,6 @@ using System; using NPoco; +using Umbraco.Cms.Core; using Umbraco.Cms.Infrastructure.Persistence.DatabaseAnnotations; using Umbraco.Cms.Infrastructure.Persistence.DatabaseModelDefinitions; @@ -10,9 +11,6 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Dtos [ExplicitColumns] internal class AuditEntryDto { - public const int IpLength = 64; - public const int EventTypeLength = 256; - public const int DetailsLength = 1024; [Column("id")] [PrimaryKeyColumn] @@ -27,12 +25,12 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Dtos [Column("performingDetails")] [NullSetting(NullSetting = NullSettings.Null)] - [Length(DetailsLength)] + [Length(Constants.Audit.DetailsLength)] public string? PerformingDetails { get; set; } [Column("performingIp")] [NullSetting(NullSetting = NullSettings.Null)] - [Length(IpLength)] + [Length(Constants.Audit.IpLength)] public string? PerformingIp { get; set; } [Column("eventDateUtc")] @@ -44,16 +42,16 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Dtos [Column("affectedDetails")] [NullSetting(NullSetting = NullSettings.Null)] - [Length(DetailsLength)] + [Length(Constants.Audit.DetailsLength)] public string? AffectedDetails { get; set; } [Column("eventType")] - [Length(EventTypeLength)] + [Length(Constants.Audit.EventTypeLength)] public string? EventType { get; set; } [Column("eventDetails")] [NullSetting(NullSetting = NullSettings.Null)] - [Length(DetailsLength)] + [Length(Constants.Audit.DetailsLength)] public string? EventDetails { get; set; } } } diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/IdKeyMapRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/IdKeyMapRepository.cs new file mode 100644 index 0000000000..007e09c4a2 --- /dev/null +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/IdKeyMapRepository.cs @@ -0,0 +1,53 @@ +using System; +using Umbraco.Cms.Core; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Persistence.Repositories; +using Umbraco.Cms.Infrastructure.Scoping; + +namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement; + +public class IdKeyMapRepository : IIdKeyMapRepository +{ + private readonly IScopeAccessor _scopeAccessor; + + public IdKeyMapRepository(IScopeAccessor scopeAccessor) + { + _scopeAccessor = scopeAccessor; + } + + public int? GetIdForKey(Guid key, UmbracoObjectTypes umbracoObjectType) + { + //if it's unknown don't include the nodeObjectType in the query + if (umbracoObjectType == UmbracoObjectTypes.Unknown) + { + return _scopeAccessor.AmbientScope?.Database.ExecuteScalar("SELECT id FROM umbracoNode WHERE uniqueId=@id", new { id = key}); + } + else + { + return _scopeAccessor.AmbientScope?.Database.ExecuteScalar("SELECT id FROM umbracoNode WHERE uniqueId=@id AND (nodeObjectType=@type OR nodeObjectType=@reservation)", + new { id = key, type = GetNodeObjectTypeGuid(umbracoObjectType), reservation = Cms.Core.Constants.ObjectTypes.IdReservation }); + } + } + + public Guid? GetIdForKey(int id, UmbracoObjectTypes umbracoObjectType) + { + //if it's unknown don't include the nodeObjectType in the query + if (umbracoObjectType == UmbracoObjectTypes.Unknown) + { + return _scopeAccessor.AmbientScope?.Database.ExecuteScalar("SELECT uniqueId FROM umbracoNode WHERE id=@id", new { id }); + } + else + { + return _scopeAccessor.AmbientScope?.Database.ExecuteScalar("SELECT uniqueId FROM umbracoNode WHERE id=@id AND (nodeObjectType=@type OR nodeObjectType=@reservation)", + new { id, type = GetNodeObjectTypeGuid(umbracoObjectType), reservation = Cms.Core.Constants.ObjectTypes.IdReservation }); + } + } + + private Guid GetNodeObjectTypeGuid(UmbracoObjectTypes umbracoObjectType) + { + var guid = umbracoObjectType.GetGuid(); + if (guid == Guid.Empty) + throw new NotSupportedException("Unsupported object type (" + umbracoObjectType + ")."); + return guid; + } +} diff --git a/src/Umbraco.Infrastructure/PropertyEditors/BlockListConfigurationEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/BlockListConfigurationEditor.cs index 68c3f778dc..a3b3d62338 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/BlockListConfigurationEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/BlockListConfigurationEditor.cs @@ -1,15 +1,18 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using System; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { internal class BlockListConfigurationEditor : ConfigurationEditor { - public BlockListConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) + public BlockListConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) { - } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/BlockListPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/BlockListPropertyEditor.cs index 0955aa5198..c8be6adf40 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/BlockListPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/BlockListPropertyEditor.cs @@ -2,12 +2,14 @@ // See LICENSE for more details. using System; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.Hosting; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -24,19 +26,32 @@ namespace Umbraco.Cms.Core.PropertyEditors public class BlockListPropertyEditor : BlockEditorPropertyEditor { private readonly IIOHelper _ioHelper; + private readonly IEditorConfigurationParser _editorConfigurationParser; + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] public BlockListPropertyEditor( IDataValueEditorFactory dataValueEditorFactory, PropertyEditorCollection propertyEditors, IIOHelper ioHelper) + : this(dataValueEditorFactory, propertyEditors, ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public BlockListPropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + PropertyEditorCollection propertyEditors, + IIOHelper ioHelper, + IEditorConfigurationParser editorConfigurationParser) : base(dataValueEditorFactory, propertyEditors) { _ioHelper = ioHelper; + _editorConfigurationParser = editorConfigurationParser; } #region Pre Value Editor - protected override IConfigurationEditor CreateConfigurationEditor() => new BlockListConfigurationEditor(_ioHelper); + protected override IConfigurationEditor CreateConfigurationEditor() => new BlockListConfigurationEditor(_ioHelper, _editorConfigurationParser); #endregion } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/CheckBoxListPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/CheckBoxListPropertyEditor.cs index 1f0888690a..226024f8b9 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/CheckBoxListPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/CheckBoxListPropertyEditor.cs @@ -1,13 +1,12 @@ // Copyright (c) Umbraco. // See LICENSE for more details. -using Microsoft.Extensions.Logging; -using Umbraco.Cms.Core.Hosting; +using System; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Models; -using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Core.Strings; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -24,6 +23,17 @@ namespace Umbraco.Cms.Core.PropertyEditors { private readonly ILocalizedTextService _textService; private readonly IIOHelper _ioHelper; + private readonly IEditorConfigurationParser _editorConfigurationParser; + + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public CheckBoxListPropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + ILocalizedTextService textService, + IIOHelper ioHelper) + : this(dataValueEditorFactory, textService, ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } /// /// The constructor will setup the property editor based on the attribute if one is found @@ -31,15 +41,17 @@ namespace Umbraco.Cms.Core.PropertyEditors public CheckBoxListPropertyEditor( IDataValueEditorFactory dataValueEditorFactory, ILocalizedTextService textService, - IIOHelper ioHelper) + IIOHelper ioHelper, + IEditorConfigurationParser editorConfigurationParser) : base(dataValueEditorFactory) { _textService = textService; _ioHelper = ioHelper; + _editorConfigurationParser = editorConfigurationParser; } /// - protected override IConfigurationEditor CreateConfigurationEditor() => new ValueListConfigurationEditor(_textService, _ioHelper); + protected override IConfigurationEditor CreateConfigurationEditor() => new ValueListConfigurationEditor(_textService, _ioHelper, _editorConfigurationParser); /// protected override IDataValueEditor CreateValueEditor() => DataValueEditorFactory.Create(Attribute!); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ColorPickerConfigurationEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/ColorPickerConfigurationEditor.cs index 9f5aa14949..ff72a77788 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ColorPickerConfigurationEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ColorPickerConfigurationEditor.cs @@ -1,15 +1,16 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using System; 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.Cms.Core.IO; using Umbraco.Cms.Core.Serialization; +using Umbraco.Cms.Core.Services; using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors @@ -17,8 +18,8 @@ namespace Umbraco.Cms.Core.PropertyEditors internal class ColorPickerConfigurationEditor : ConfigurationEditor { private readonly IJsonSerializer _jsonSerializer; - - public ColorPickerConfigurationEditor(IIOHelper ioHelper, IJsonSerializer jsonSerializer) : base(ioHelper) + public ColorPickerConfigurationEditor(IIOHelper ioHelper, IJsonSerializer jsonSerializer, IEditorConfigurationParser editorConfigurationParser) + : base(ioHelper, editorConfigurationParser) { _jsonSerializer = jsonSerializer; var items = Fields.First(x => x.Key == "items"); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ColorPickerPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/ColorPickerPropertyEditor.cs index 71eef56225..6101d9d2a6 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ColorPickerPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ColorPickerPropertyEditor.cs @@ -1,9 +1,12 @@ // Copyright (c) Umbraco. // See LICENSE for more details. -using Microsoft.Extensions.Logging; +using System; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Serialization; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -17,18 +20,31 @@ namespace Umbraco.Cms.Core.PropertyEditors { private readonly IIOHelper _ioHelper; private readonly IJsonSerializer _jsonSerializer; + private readonly IEditorConfigurationParser _editorConfigurationParser; + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] public ColorPickerPropertyEditor( IDataValueEditorFactory dataValueEditorFactory, IIOHelper ioHelper, IJsonSerializer jsonSerializer) + : this(dataValueEditorFactory, ioHelper, jsonSerializer, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public ColorPickerPropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + IIOHelper ioHelper, + IJsonSerializer jsonSerializer, + IEditorConfigurationParser editorConfigurationParser) : base(dataValueEditorFactory) { _ioHelper = ioHelper; _jsonSerializer = jsonSerializer; + _editorConfigurationParser = editorConfigurationParser; } /// - protected override IConfigurationEditor CreateConfigurationEditor() => new ColorPickerConfigurationEditor(_ioHelper, _jsonSerializer); + protected override IConfigurationEditor CreateConfigurationEditor() => new ColorPickerConfigurationEditor(_ioHelper, _jsonSerializer, _editorConfigurationParser); } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/DateTimePropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/DateTimePropertyEditor.cs index 8a6b670435..eb5cf307fb 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/DateTimePropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/DateTimePropertyEditor.cs @@ -1,6 +1,7 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Models; @@ -8,6 +9,7 @@ using Umbraco.Cms.Core.PropertyEditors.Validators; using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -23,15 +25,21 @@ namespace Umbraco.Cms.Core.PropertyEditors public class DateTimePropertyEditor : DataEditor { private readonly IIOHelper _ioHelper; + private readonly IEditorConfigurationParser _editorConfigurationParser; + public DateTimePropertyEditor(IDataValueEditorFactory dataValueEditorFactory, IIOHelper ioHelper) + : this(dataValueEditorFactory, ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } /// /// Initializes a new instance of the class. /// /// - public DateTimePropertyEditor(IDataValueEditorFactory dataValueEditorFactory, IIOHelper ioHelper) + public DateTimePropertyEditor(IDataValueEditorFactory dataValueEditorFactory, IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(dataValueEditorFactory) { _ioHelper = ioHelper; + _editorConfigurationParser = editorConfigurationParser; } /// @@ -43,6 +51,6 @@ namespace Umbraco.Cms.Core.PropertyEditors } /// - protected override IConfigurationEditor CreateConfigurationEditor() => new DateTimeConfigurationEditor(_ioHelper); + protected override IConfigurationEditor CreateConfigurationEditor() => new DateTimeConfigurationEditor(_ioHelper, _editorConfigurationParser); } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/DropDownFlexibleConfigurationEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/DropDownFlexibleConfigurationEditor.cs index eb12ebfaa5..23fed74088 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/DropDownFlexibleConfigurationEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/DropDownFlexibleConfigurationEditor.cs @@ -12,7 +12,7 @@ namespace Umbraco.Cms.Core.PropertyEditors { internal class DropDownFlexibleConfigurationEditor : ConfigurationEditor { - public DropDownFlexibleConfigurationEditor(ILocalizedTextService textService, IIOHelper ioHelper): base(ioHelper) + public DropDownFlexibleConfigurationEditor(ILocalizedTextService textService, IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) { var items = Fields.First(x => x.Key == "items"); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/DropDownFlexiblePropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/DropDownFlexiblePropertyEditor.cs index a8b46cdb44..a3511de0e9 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/DropDownFlexiblePropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/DropDownFlexiblePropertyEditor.cs @@ -1,12 +1,12 @@ // Copyright (c) Umbraco. // See LICENSE for more details. -using Microsoft.Extensions.Logging; +using System; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Models; -using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Core.Strings; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -20,15 +20,31 @@ namespace Umbraco.Cms.Core.PropertyEditors { private readonly ILocalizedTextService _textService; private readonly IIOHelper _ioHelper; + private readonly IEditorConfigurationParser _editorConfigurationParser; + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] public DropDownFlexiblePropertyEditor( IDataValueEditorFactory dataValueEditorFactory, ILocalizedTextService textService, IIOHelper ioHelper) + : this(dataValueEditorFactory, + textService, + ioHelper, + StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public DropDownFlexiblePropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + ILocalizedTextService textService, + IIOHelper ioHelper, + IEditorConfigurationParser editorConfigurationParser) : base(dataValueEditorFactory) { _textService = textService; _ioHelper = ioHelper; + _editorConfigurationParser = editorConfigurationParser; } protected override IDataValueEditor CreateValueEditor() @@ -36,6 +52,6 @@ namespace Umbraco.Cms.Core.PropertyEditors return DataValueEditorFactory.Create(Attribute!); } - protected override IConfigurationEditor CreateConfigurationEditor() => new DropDownFlexibleConfigurationEditor(_textService, _ioHelper); + protected override IConfigurationEditor CreateConfigurationEditor() => new DropDownFlexibleConfigurationEditor(_textService, _ioHelper, _editorConfigurationParser); } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/EmailAddressConfigurationEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/EmailAddressConfigurationEditor.cs deleted file mode 100644 index 1f05ab45af..0000000000 --- a/src/Umbraco.Infrastructure/PropertyEditors/EmailAddressConfigurationEditor.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - -using Umbraco.Cms.Core.IO; - -namespace Umbraco.Cms.Core.PropertyEditors -{ - /// - /// Represents the configuration editor for the email address value editor. - /// - public class EmailAddressConfigurationEditor : ConfigurationEditor - { - public EmailAddressConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) - { - } - } -} diff --git a/src/Umbraco.Infrastructure/PropertyEditors/FileUploadConfigurationEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/FileUploadConfigurationEditor.cs deleted file mode 100644 index a1290624c3..0000000000 --- a/src/Umbraco.Infrastructure/PropertyEditors/FileUploadConfigurationEditor.cs +++ /dev/null @@ -1,15 +0,0 @@ - -using Umbraco.Cms.Core.IO; - -namespace Umbraco.Cms.Core.PropertyEditors -{ - /// - /// Represents the configuration editor for the file upload value editor. - /// - public class FileUploadConfigurationEditor : ConfigurationEditor - { - public FileUploadConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) - { - } - } -} diff --git a/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyEditor.cs index 1ccd1831cc..a6c28b9e24 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyEditor.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Events; @@ -13,6 +14,7 @@ using Umbraco.Cms.Core.Media; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Notifications; using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors @@ -34,7 +36,10 @@ namespace Umbraco.Cms.Core.PropertyEditors private readonly ILocalizedTextService _localizedTextService; private readonly IContentService _contentService; private readonly IIOHelper _ioHelper; + private readonly IEditorConfigurationParser _editorConfigurationParser; + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] public FileUploadPropertyEditor( IDataValueEditorFactory dataValueEditorFactory, MediaFileManager mediaFileManager, @@ -43,6 +48,27 @@ namespace Umbraco.Cms.Core.PropertyEditors UploadAutoFillProperties uploadAutoFillProperties, IContentService contentService, IIOHelper ioHelper) + : this( + dataValueEditorFactory, + mediaFileManager, + contentSettings, + localizedTextService, + uploadAutoFillProperties, + contentService, + ioHelper, + StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public FileUploadPropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + MediaFileManager mediaFileManager, + IOptionsMonitor contentSettings, + ILocalizedTextService localizedTextService, + UploadAutoFillProperties uploadAutoFillProperties, + IContentService contentService, + IIOHelper ioHelper, + IEditorConfigurationParser editorConfigurationParser) : base(dataValueEditorFactory) { _mediaFileManager = mediaFileManager ?? throw new ArgumentNullException(nameof(mediaFileManager)); @@ -51,9 +77,10 @@ namespace Umbraco.Cms.Core.PropertyEditors _uploadAutoFillProperties = uploadAutoFillProperties; _contentService = contentService; _ioHelper = ioHelper; + _editorConfigurationParser = editorConfigurationParser; } /// - protected override IConfigurationEditor CreateConfigurationEditor() => new FileUploadConfigurationEditor(_ioHelper); + protected override IConfigurationEditor CreateConfigurationEditor() => new FileUploadConfigurationEditor(_ioHelper, _editorConfigurationParser); /// diff --git a/src/Umbraco.Infrastructure/PropertyEditors/GridConfigurationEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/GridConfigurationEditor.cs index 788a4ae496..5635303018 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/GridConfigurationEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/GridConfigurationEditor.cs @@ -1,11 +1,15 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; +using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -14,7 +18,15 @@ namespace Umbraco.Cms.Core.PropertyEditors /// public class GridConfigurationEditor : ConfigurationEditor { - public GridConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public GridConfigurationEditor(IIOHelper ioHelper) + : this(ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public GridConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) + : base(ioHelper, editorConfigurationParser) { var items = Fields.First(x => x.Key == "items"); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs index f1a391901f..ca2dcefbbf 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs @@ -41,7 +41,10 @@ namespace Umbraco.Cms.Core.PropertyEditors private readonly HtmlLocalLinkParser _localLinkParser; private readonly IImageUrlGenerator _imageUrlGenerator; private readonly IHtmlMacroParameterParser _macroParameterParser; + private readonly IEditorConfigurationParser _editorConfigurationParser; + // Scheduled for removal in v12 + [Obsolete("Use the constructor which takes an IHtmlMacroParameterParser instead")] public GridPropertyEditor( IDataValueEditorFactory dataValueEditorFactory, IBackOfficeSecurityAccessor backOfficeSecurityAccessor, @@ -51,15 +54,17 @@ namespace Umbraco.Cms.Core.PropertyEditors IIOHelper ioHelper, IImageUrlGenerator imageUrlGenerator, IHtmlMacroParameterParser macroParameterParser) - : base(dataValueEditorFactory) + : this( + dataValueEditorFactory, + backOfficeSecurityAccessor, + imageSourceParser, + pastedImages, + localLinkParser, + ioHelper, + imageUrlGenerator, + macroParameterParser, + StaticServiceProvider.Instance.GetRequiredService()) { - _backOfficeSecurityAccessor = backOfficeSecurityAccessor; - _ioHelper = ioHelper; - _imageSourceParser = imageSourceParser; - _pastedImages = pastedImages; - _localLinkParser = localLinkParser; - _imageUrlGenerator = imageUrlGenerator; - _macroParameterParser = macroParameterParser; } [Obsolete("Use the constructor which takes an IHtmlMacroParameterParser instead")] @@ -71,10 +76,41 @@ namespace Umbraco.Cms.Core.PropertyEditors HtmlLocalLinkParser localLinkParser, IIOHelper ioHelper, IImageUrlGenerator imageUrlGenerator) - : this (dataValueEditorFactory, backOfficeSecurityAccessor, imageSourceParser, pastedImages, localLinkParser, ioHelper, imageUrlGenerator, StaticServiceProvider.Instance.GetRequiredService()) + : this( + dataValueEditorFactory, + backOfficeSecurityAccessor, + imageSourceParser, + pastedImages, + localLinkParser, + ioHelper, + imageUrlGenerator, + StaticServiceProvider.Instance.GetRequiredService(), + StaticServiceProvider.Instance.GetRequiredService()) { } + public GridPropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + IBackOfficeSecurityAccessor backOfficeSecurityAccessor, + HtmlImageSourceParser imageSourceParser, + RichTextEditorPastedImages pastedImages, + HtmlLocalLinkParser localLinkParser, + IIOHelper ioHelper, + IImageUrlGenerator imageUrlGenerator, + IHtmlMacroParameterParser macroParameterParser, + IEditorConfigurationParser editorConfigurationParser) + : base(dataValueEditorFactory) + { + _backOfficeSecurityAccessor = backOfficeSecurityAccessor; + _ioHelper = ioHelper; + _imageSourceParser = imageSourceParser; + _pastedImages = pastedImages; + _localLinkParser = localLinkParser; + _imageUrlGenerator = imageUrlGenerator; + _macroParameterParser = macroParameterParser; + _editorConfigurationParser = editorConfigurationParser; + } + public override IPropertyIndexValueFactory PropertyIndexValueFactory => new GridPropertyIndexValueFactory(); /// @@ -83,7 +119,7 @@ namespace Umbraco.Cms.Core.PropertyEditors /// protected override IDataValueEditor CreateValueEditor() => DataValueEditorFactory.Create(Attribute!); - protected override IConfigurationEditor CreateConfigurationEditor() => new GridConfigurationEditor(_ioHelper); + protected override IConfigurationEditor CreateConfigurationEditor() => new GridConfigurationEditor(_ioHelper, _editorConfigurationParser); internal class GridPropertyValueEditor : DataValueEditor, IDataValueReference { diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperConfigurationEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperConfigurationEditor.cs index a63abd6fc5..40e81dfbfe 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperConfigurationEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperConfigurationEditor.cs @@ -1,8 +1,12 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using System; using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -20,7 +24,7 @@ namespace Umbraco.Cms.Core.PropertyEditors return d; } - public ImageCropperConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) + public ImageCropperConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) { } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs index 1af95a02a2..6a7b71ca83 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Newtonsoft.Json; @@ -15,6 +16,7 @@ using Umbraco.Cms.Core.Media; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Notifications; using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors @@ -42,7 +44,31 @@ namespace Umbraco.Cms.Core.PropertyEditors private readonly UploadAutoFillProperties _autoFillProperties; private readonly ILogger _logger; private readonly IContentService _contentService; + private readonly IEditorConfigurationParser _editorConfigurationParser; + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public ImageCropperPropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + ILoggerFactory loggerFactory, + MediaFileManager mediaFileManager, + IOptionsMonitor contentSettings, + IDataTypeService dataTypeService, + IIOHelper ioHelper, + UploadAutoFillProperties uploadAutoFillProperties, + IContentService contentService) + : this( + dataValueEditorFactory, + loggerFactory, + mediaFileManager, + contentSettings, + dataTypeService, + ioHelper, + uploadAutoFillProperties, + contentService, + StaticServiceProvider.Instance.GetRequiredService()) + { + } /// /// Initializes a new instance of the class. /// @@ -54,7 +80,8 @@ namespace Umbraco.Cms.Core.PropertyEditors IDataTypeService dataTypeService, IIOHelper ioHelper, UploadAutoFillProperties uploadAutoFillProperties, - IContentService contentService) + IContentService contentService, + IEditorConfigurationParser editorConfigurationParser) : base(dataValueEditorFactory) { _mediaFileManager = mediaFileManager ?? throw new ArgumentNullException(nameof(mediaFileManager)); @@ -63,6 +90,7 @@ namespace Umbraco.Cms.Core.PropertyEditors _ioHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper)); _autoFillProperties = uploadAutoFillProperties ?? throw new ArgumentNullException(nameof(uploadAutoFillProperties)); _contentService = contentService; + _editorConfigurationParser = editorConfigurationParser; _logger = loggerFactory.CreateLogger(); contentSettings.OnChange(x => _contentSettings = x); @@ -92,7 +120,7 @@ namespace Umbraco.Cms.Core.PropertyEditors /// Creates the corresponding preValue editor. /// /// The corresponding preValue editor. - protected override IConfigurationEditor CreateConfigurationEditor() => new ImageCropperConfigurationEditor(_ioHelper); + protected override IConfigurationEditor CreateConfigurationEditor() => new ImageCropperConfigurationEditor(_ioHelper, _editorConfigurationParser); /// /// Gets a value indicating whether a property is an image cropper field. diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ListViewConfigurationEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/ListViewConfigurationEditor.cs deleted file mode 100644 index 8c84cff632..0000000000 --- a/src/Umbraco.Infrastructure/PropertyEditors/ListViewConfigurationEditor.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - -using Umbraco.Cms.Core.IO; - -namespace Umbraco.Cms.Core.PropertyEditors -{ - /// - /// Represents the configuration editor for the listview value editor. - /// - public class ListViewConfigurationEditor : ConfigurationEditor - { - public ListViewConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) - { - } - } -} diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ListViewPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/ListViewPropertyEditor.cs index f9b862c9f0..01ddd8b8a5 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ListViewPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ListViewPropertyEditor.cs @@ -1,11 +1,14 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using System; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -22,19 +25,28 @@ namespace Umbraco.Cms.Core.PropertyEditors public class ListViewPropertyEditor : DataEditor { private readonly IIOHelper _iioHelper; + private readonly IEditorConfigurationParser _editorConfigurationParser; - /// - /// Initializes a new instance of the class. - /// + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] public ListViewPropertyEditor( IDataValueEditorFactory dataValueEditorFactory, IIOHelper iioHelper) + : this(dataValueEditorFactory, iioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public ListViewPropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + IIOHelper iioHelper, + IEditorConfigurationParser editorConfigurationParser) : base(dataValueEditorFactory) { _iioHelper = iioHelper; + _editorConfigurationParser = editorConfigurationParser; } /// - protected override IConfigurationEditor CreateConfigurationEditor() => new ListViewConfigurationEditor(_iioHelper); + protected override IConfigurationEditor CreateConfigurationEditor() => new ListViewConfigurationEditor(_iioHelper, _editorConfigurationParser); } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MediaPicker3PropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/MediaPicker3PropertyEditor.cs index 7376ff6d2f..d1d8d36762 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MediaPicker3PropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/MediaPicker3PropertyEditor.cs @@ -12,7 +12,9 @@ using Newtonsoft.Json; using System; using System.Linq; using System.Runtime.Serialization; +using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json.Linq; +using Umbraco.Cms.Web.Common.DependencyInjection; using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors @@ -31,6 +33,17 @@ namespace Umbraco.Cms.Core.PropertyEditors public class MediaPicker3PropertyEditor : DataEditor { private readonly IIOHelper _ioHelper; + private readonly IEditorConfigurationParser _editorConfigurationParser; + + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public MediaPicker3PropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + IIOHelper ioHelper, + EditorType type = EditorType.PropertyValue) + : this(dataValueEditorFactory, ioHelper, StaticServiceProvider.Instance.GetRequiredService(), type) + { + } /// /// Initializes a new instance of the class. @@ -38,16 +51,18 @@ namespace Umbraco.Cms.Core.PropertyEditors public MediaPicker3PropertyEditor( IDataValueEditorFactory dataValueEditorFactory, IIOHelper ioHelper, + IEditorConfigurationParser editorConfigurationParser, EditorType type = EditorType.PropertyValue) : base(dataValueEditorFactory, type) { _ioHelper = ioHelper; + _editorConfigurationParser = editorConfigurationParser; } /// protected override IConfigurationEditor CreateConfigurationEditor() => - new MediaPicker3ConfigurationEditor(_ioHelper); + new MediaPicker3ConfigurationEditor(_ioHelper, _editorConfigurationParser); /// protected override IDataValueEditor CreateValueEditor() => diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MediaPickerPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/MediaPickerPropertyEditor.cs index 221242d8c2..121a7ac117 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MediaPickerPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/MediaPickerPropertyEditor.cs @@ -1,15 +1,16 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using System; using System.Collections.Generic; -using Microsoft.Extensions.Logging; -using Umbraco.Cms.Core.Hosting; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Editors; using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -31,20 +32,33 @@ namespace Umbraco.Cms.Core.PropertyEditors public class MediaPickerPropertyEditor : DataEditor { private readonly IIOHelper _ioHelper; + private readonly IEditorConfigurationParser _editorConfigurationParser; + + + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public MediaPickerPropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + IIOHelper ioHelper) + : this(dataValueEditorFactory, ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } /// /// Initializes a new instance of the class. /// public MediaPickerPropertyEditor( IDataValueEditorFactory dataValueEditorFactory, - IIOHelper ioHelper) + IIOHelper ioHelper, + IEditorConfigurationParser editorConfigurationParser) : base(dataValueEditorFactory) { _ioHelper = ioHelper; + _editorConfigurationParser = editorConfigurationParser; } /// - protected override IConfigurationEditor CreateConfigurationEditor() => new MediaPickerConfigurationEditor(_ioHelper); + protected override IConfigurationEditor CreateConfigurationEditor() => new MediaPickerConfigurationEditor(_ioHelper, _editorConfigurationParser); protected override IDataValueEditor CreateValueEditor() => DataValueEditorFactory.Create(Attribute!); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs index 9d097cb8c0..094a54a2ca 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs @@ -1,15 +1,16 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using System; using System.Collections.Generic; -using Microsoft.Extensions.Logging; -using Umbraco.Cms.Core.Hosting; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Editors; using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -23,16 +24,28 @@ namespace Umbraco.Cms.Core.PropertyEditors public class MultiNodeTreePickerPropertyEditor : DataEditor { private readonly IIOHelper _ioHelper; + private readonly IEditorConfigurationParser _editorConfigurationParser; + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] public MultiNodeTreePickerPropertyEditor( IDataValueEditorFactory dataValueEditorFactory, IIOHelper ioHelper) + : this(dataValueEditorFactory, ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public MultiNodeTreePickerPropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + IIOHelper ioHelper, + IEditorConfigurationParser editorConfigurationParser) : base(dataValueEditorFactory) { _ioHelper = ioHelper; + _editorConfigurationParser = editorConfigurationParser; } - protected override IConfigurationEditor CreateConfigurationEditor() => new MultiNodePickerConfigurationEditor(_ioHelper); + protected override IConfigurationEditor CreateConfigurationEditor() => new MultiNodePickerConfigurationEditor(_ioHelper, _editorConfigurationParser); protected override IDataValueEditor CreateValueEditor() => DataValueEditorFactory.Create(Attribute!); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerConfigurationEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerConfigurationEditor.cs deleted file mode 100644 index d79e0d57f1..0000000000 --- a/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerConfigurationEditor.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - -using Umbraco.Cms.Core.IO; - -namespace Umbraco.Cms.Core.PropertyEditors -{ - public class MultiUrlPickerConfigurationEditor : ConfigurationEditor - { - public MultiUrlPickerConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) - { - } - } -} diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerPropertyEditor.cs index c32e73e7aa..6622a0a36a 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerPropertyEditor.cs @@ -2,16 +2,11 @@ // See LICENSE for more details. using System; -using Microsoft.Extensions.Logging; -using Umbraco.Cms.Core.Hosting; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Models; -using Umbraco.Cms.Core.PublishedCache; -using Umbraco.Cms.Core.Routing; -using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Core.Strings; -using Umbraco.Cms.Core.Web; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -26,16 +21,28 @@ namespace Umbraco.Cms.Core.PropertyEditors public class MultiUrlPickerPropertyEditor : DataEditor { private readonly IIOHelper _ioHelper; + private readonly IEditorConfigurationParser _editorConfigurationParser; + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] public MultiUrlPickerPropertyEditor( IIOHelper ioHelper, IDataValueEditorFactory dataValueEditorFactory) + : this(ioHelper, dataValueEditorFactory, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public MultiUrlPickerPropertyEditor( + IIOHelper ioHelper, + IDataValueEditorFactory dataValueEditorFactory, + IEditorConfigurationParser editorConfigurationParser) : base(dataValueEditorFactory, EditorType.PropertyValue) { _ioHelper = ioHelper; + _editorConfigurationParser = editorConfigurationParser; } - protected override IConfigurationEditor CreateConfigurationEditor() => new MultiUrlPickerConfigurationEditor(_ioHelper); + protected override IConfigurationEditor CreateConfigurationEditor() => new MultiUrlPickerConfigurationEditor(_ioHelper, _editorConfigurationParser); protected override IDataValueEditor CreateValueEditor() => DataValueEditorFactory.Create(Attribute!); } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MultipleTextStringConfigurationEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/MultipleTextStringConfigurationEditor.cs index 60777010d6..6031852ee4 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MultipleTextStringConfigurationEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/MultipleTextStringConfigurationEditor.cs @@ -1,9 +1,13 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using System; using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.PropertyEditors.Validators; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors @@ -13,7 +17,7 @@ namespace Umbraco.Cms.Core.PropertyEditors /// internal class MultipleTextStringConfigurationEditor : ConfigurationEditor { - public MultipleTextStringConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) + public MultipleTextStringConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) : base(ioHelper, editorConfigurationParser) { Fields.Add(new ConfigurationField(new IntegerValidator()) { diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MultipleTextStringPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/MultipleTextStringPropertyEditor.cs index a9245581b8..0398b3d894 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/MultipleTextStringPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/MultipleTextStringPropertyEditor.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; +using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json.Linq; using Umbraco.Cms.Core.Exceptions; using Umbraco.Cms.Core.IO; @@ -14,6 +15,7 @@ using Umbraco.Cms.Core.PropertyEditors.Validators; using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -30,23 +32,36 @@ namespace Umbraco.Cms.Core.PropertyEditors public class MultipleTextStringPropertyEditor : DataEditor { private readonly IIOHelper _ioHelper; + private readonly IEditorConfigurationParser _editorConfigurationParser; + + + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public MultipleTextStringPropertyEditor( + IIOHelper ioHelper, + IDataValueEditorFactory dataValueEditorFactory) + : this(ioHelper, dataValueEditorFactory, StaticServiceProvider.Instance.GetRequiredService()) + { + } /// /// Initializes a new instance of the class. /// public MultipleTextStringPropertyEditor( IIOHelper ioHelper, - IDataValueEditorFactory dataValueEditorFactory) + IDataValueEditorFactory dataValueEditorFactory, + IEditorConfigurationParser editorConfigurationParser) : base(dataValueEditorFactory) { _ioHelper = ioHelper; + _editorConfigurationParser = editorConfigurationParser; } /// protected override IDataValueEditor CreateValueEditor() => DataValueEditorFactory.Create(Attribute!); /// - protected override IConfigurationEditor CreateConfigurationEditor() => new MultipleTextStringConfigurationEditor(_ioHelper); + protected override IConfigurationEditor CreateConfigurationEditor() => new MultipleTextStringConfigurationEditor(_ioHelper, _editorConfigurationParser); /// /// Custom value editor so we can format the value for the editor and the database diff --git a/src/Umbraco.Infrastructure/PropertyEditors/NestedContentConfigurationEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/NestedContentConfigurationEditor.cs deleted file mode 100644 index 1ce9e2a235..0000000000 --- a/src/Umbraco.Infrastructure/PropertyEditors/NestedContentConfigurationEditor.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - -using Umbraco.Cms.Core.IO; - -namespace Umbraco.Cms.Core.PropertyEditors -{ - /// - /// Represents the configuration editor for the nested content value editor. - /// - public class NestedContentConfigurationEditor : ConfigurationEditor - { - public NestedContentConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) - { - } - } -} diff --git a/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyEditor.cs index 11ceef15d4..59ee489d2d 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyEditor.cs @@ -4,17 +4,17 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using Umbraco.Cms.Core.Hosting; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Editors; using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Core.Services.Implement; using Umbraco.Cms.Core.Strings; +using Umbraco.Cms.Web.Common.DependencyInjection; using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors @@ -32,21 +32,33 @@ namespace Umbraco.Cms.Core.PropertyEditors public class NestedContentPropertyEditor : DataEditor { private readonly IIOHelper _ioHelper; + private readonly IEditorConfigurationParser _editorConfigurationParser; public const string ContentTypeAliasPropertyKey = "ncContentTypeAlias"; + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] public NestedContentPropertyEditor( IDataValueEditorFactory dataValueEditorFactory, IIOHelper ioHelper) + : this(dataValueEditorFactory, ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public NestedContentPropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + IIOHelper ioHelper, + IEditorConfigurationParser editorConfigurationParser) : base (dataValueEditorFactory) { _ioHelper = ioHelper; + _editorConfigurationParser = editorConfigurationParser; } #region Pre Value Editor - protected override IConfigurationEditor CreateConfigurationEditor() => new NestedContentConfigurationEditor(_ioHelper); + protected override IConfigurationEditor CreateConfigurationEditor() => new NestedContentConfigurationEditor(_ioHelper, _editorConfigurationParser); #endregion diff --git a/src/Umbraco.Infrastructure/PropertyEditors/RadioButtonsPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/RadioButtonsPropertyEditor.cs index 25b96e3ee6..411d6a75c2 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/RadioButtonsPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/RadioButtonsPropertyEditor.cs @@ -1,6 +1,7 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using System; using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Serialization; @@ -23,10 +24,10 @@ namespace Umbraco.Cms.Core.PropertyEditors { private readonly IIOHelper _ioHelper; private readonly ILocalizedTextService _localizedTextService; + private readonly IEditorConfigurationParser _editorConfigurationParser; - /// - /// The constructor will setup the property editor based on the attribute if one is found - /// + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] public RadioButtonsPropertyEditor( IDataValueEditorFactory dataValueEditorFactory, IIOHelper ioHelper, @@ -37,10 +38,25 @@ namespace Umbraco.Cms.Core.PropertyEditors _localizedTextService = localizedTextService; } + /// + /// The constructor will setup the property editor based on the attribute if one is found + /// + public RadioButtonsPropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + IIOHelper ioHelper, + ILocalizedTextService localizedTextService, + IEditorConfigurationParser editorConfigurationParser) + : base(dataValueEditorFactory) + { + _ioHelper = ioHelper; + _localizedTextService = localizedTextService; + _editorConfigurationParser = editorConfigurationParser; + } + /// /// Return a custom pre-value editor /// /// - protected override IConfigurationEditor CreateConfigurationEditor() => new ValueListConfigurationEditor(_localizedTextService, _ioHelper); + protected override IConfigurationEditor CreateConfigurationEditor() => new ValueListConfigurationEditor(_localizedTextService, _ioHelper, _editorConfigurationParser); } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/RichTextConfigurationEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/RichTextConfigurationEditor.cs deleted file mode 100644 index 09d6290605..0000000000 --- a/src/Umbraco.Infrastructure/PropertyEditors/RichTextConfigurationEditor.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - -using Umbraco.Cms.Core.IO; - -namespace Umbraco.Cms.Core.PropertyEditors -{ - /// - /// Represents the configuration editor for the rich text value editor. - /// - public class RichTextConfigurationEditor : ConfigurationEditor - { - public RichTextConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) - { - } - } -} diff --git a/src/Umbraco.Infrastructure/PropertyEditors/RichTextPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/RichTextPropertyEditor.cs index 7fdf314924..a0471a0c3f 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/RichTextPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/RichTextPropertyEditor.cs @@ -38,13 +38,12 @@ namespace Umbraco.Cms.Core.PropertyEditors private readonly HtmlImageSourceParser _imageSourceParser; private readonly HtmlLocalLinkParser _localLinkParser; private readonly IHtmlMacroParameterParser _macroParameterParser; + private readonly IEditorConfigurationParser _editorConfigurationParser; private readonly RichTextEditorPastedImages _pastedImages; private readonly IIOHelper _ioHelper; private readonly IImageUrlGenerator _imageUrlGenerator; - /// - /// The constructor will setup the property editor based on the attribute if one is found. - /// + [Obsolete("Use the constructor which takes an IHtmlMacroParameterParser instead")] public RichTextPropertyEditor( IDataValueEditorFactory dataValueEditorFactory, IBackOfficeSecurityAccessor backOfficeSecurityAccessor, @@ -54,7 +53,16 @@ namespace Umbraco.Cms.Core.PropertyEditors IIOHelper ioHelper, IImageUrlGenerator imageUrlGenerator, IHtmlMacroParameterParser macroParameterParser) - : base(dataValueEditorFactory) + : this( + dataValueEditorFactory, + backOfficeSecurityAccessor, + imageSourceParser, + localLinkParser, + pastedImages, + ioHelper, + imageUrlGenerator, + macroParameterParser, + StaticServiceProvider.Instance.GetRequiredService()) { _backOfficeSecurityAccessor = backOfficeSecurityAccessor; _imageSourceParser = imageSourceParser; @@ -74,10 +82,46 @@ namespace Umbraco.Cms.Core.PropertyEditors RichTextEditorPastedImages pastedImages, IIOHelper ioHelper, IImageUrlGenerator imageUrlGenerator) - : this (dataValueEditorFactory, backOfficeSecurityAccessor, imageSourceParser, localLinkParser, pastedImages, ioHelper, imageUrlGenerator, StaticServiceProvider.Instance.GetRequiredService()) + : this( + dataValueEditorFactory, + backOfficeSecurityAccessor, + imageSourceParser, + localLinkParser, + pastedImages, + ioHelper, + imageUrlGenerator, + StaticServiceProvider.Instance.GetRequiredService(), + StaticServiceProvider.Instance.GetRequiredService()) { } + /// + /// The constructor will setup the property editor based on the attribute if one is found. + /// + public RichTextPropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + IBackOfficeSecurityAccessor backOfficeSecurityAccessor, + HtmlImageSourceParser imageSourceParser, + HtmlLocalLinkParser localLinkParser, + RichTextEditorPastedImages pastedImages, + IIOHelper ioHelper, + IImageUrlGenerator imageUrlGenerator, + IHtmlMacroParameterParser macroParameterParser, + IEditorConfigurationParser editorConfigurationParser) + : base(dataValueEditorFactory) + { + _backOfficeSecurityAccessor = backOfficeSecurityAccessor; + _imageSourceParser = imageSourceParser; + _localLinkParser = localLinkParser; + _pastedImages = pastedImages; + _ioHelper = ioHelper; + _imageUrlGenerator = imageUrlGenerator; + _macroParameterParser = macroParameterParser; + _editorConfigurationParser = editorConfigurationParser; + } + + + /// /// Create a custom value editor /// @@ -86,7 +130,7 @@ namespace Umbraco.Cms.Core.PropertyEditors DataValueEditorFactory.Create(Attribute!); protected override IConfigurationEditor CreateConfigurationEditor() => - new RichTextConfigurationEditor(_ioHelper); + new RichTextConfigurationEditor(_ioHelper, _editorConfigurationParser); public override IPropertyIndexValueFactory PropertyIndexValueFactory => new RichTextPropertyIndexValueFactory(); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/SliderConfigurationEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/SliderConfigurationEditor.cs deleted file mode 100644 index aa3014c98d..0000000000 --- a/src/Umbraco.Infrastructure/PropertyEditors/SliderConfigurationEditor.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - -using Umbraco.Cms.Core.IO; - -namespace Umbraco.Cms.Core.PropertyEditors -{ - /// - /// Represents the configuration editor for the slider value editor. - /// - public class SliderConfigurationEditor : ConfigurationEditor - { - public SliderConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) - { - } - } -} diff --git a/src/Umbraco.Infrastructure/PropertyEditors/SliderPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/SliderPropertyEditor.cs index ca4072950f..54a5896b8c 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/SliderPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/SliderPropertyEditor.cs @@ -1,11 +1,14 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using System; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -20,22 +23,34 @@ namespace Umbraco.Cms.Core.PropertyEditors public class SliderPropertyEditor : DataEditor { private readonly IIOHelper _ioHelper; + private readonly IEditorConfigurationParser _editorConfigurationParser; + + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public SliderPropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + IIOHelper ioHelper) + : this(dataValueEditorFactory, ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } /// /// Initializes a new instance of the class. /// public SliderPropertyEditor( IDataValueEditorFactory dataValueEditorFactory, - IIOHelper ioHelper) + IIOHelper ioHelper, + IEditorConfigurationParser editorConfigurationParser) : base(dataValueEditorFactory) { _ioHelper = ioHelper; + _editorConfigurationParser = editorConfigurationParser; } /// protected override IConfigurationEditor CreateConfigurationEditor() { - return new SliderConfigurationEditor(_ioHelper); + return new SliderConfigurationEditor(_ioHelper, _editorConfigurationParser); } } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/TagsPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/TagsPropertyEditor.cs index 58270913ae..e75f66be58 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/TagsPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/TagsPropertyEditor.cs @@ -5,15 +5,15 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json.Linq; -using Umbraco.Cms.Core.Hosting; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Editors; using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; +using Umbraco.Cms.Web.Common.DependencyInjection; using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors @@ -32,23 +32,42 @@ namespace Umbraco.Cms.Core.PropertyEditors private readonly ManifestValueValidatorCollection _validators; private readonly IIOHelper _ioHelper; private readonly ILocalizedTextService _localizedTextService; + private readonly IEditorConfigurationParser _editorConfigurationParser; + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] public TagsPropertyEditor( IDataValueEditorFactory dataValueEditorFactory, ManifestValueValidatorCollection validators, IIOHelper ioHelper, ILocalizedTextService localizedTextService) + : this( + dataValueEditorFactory, + validators, + ioHelper, + localizedTextService, + StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public TagsPropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + ManifestValueValidatorCollection validators, + IIOHelper ioHelper, + ILocalizedTextService localizedTextService, + IEditorConfigurationParser editorConfigurationParser) : base(dataValueEditorFactory) { _validators = validators; _ioHelper = ioHelper; _localizedTextService = localizedTextService; + _editorConfigurationParser = editorConfigurationParser; } protected override IDataValueEditor CreateValueEditor() => DataValueEditorFactory.Create(Attribute!); - protected override IConfigurationEditor CreateConfigurationEditor() => new TagConfigurationEditor(_validators, _ioHelper, _localizedTextService); + protected override IConfigurationEditor CreateConfigurationEditor() => new TagConfigurationEditor(_validators, _ioHelper, _localizedTextService, _editorConfigurationParser); internal class TagPropertyValueEditor : DataValueEditor { diff --git a/src/Umbraco.Infrastructure/PropertyEditors/TextAreaConfigurationEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/TextAreaConfigurationEditor.cs deleted file mode 100644 index f8f87a7fb0..0000000000 --- a/src/Umbraco.Infrastructure/PropertyEditors/TextAreaConfigurationEditor.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - -using Umbraco.Cms.Core.IO; - -namespace Umbraco.Cms.Core.PropertyEditors -{ - /// - /// Represents the configuration editor for the textarea value editor. - /// - public class TextAreaConfigurationEditor : ConfigurationEditor - { - public TextAreaConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) - { - } - } -} diff --git a/src/Umbraco.Infrastructure/PropertyEditors/TextAreaPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/TextAreaPropertyEditor.cs index 69173ed690..ceaf98911f 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/TextAreaPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/TextAreaPropertyEditor.cs @@ -1,12 +1,12 @@ // Copyright (c) Umbraco. // See LICENSE for more details. -using Microsoft.Extensions.Logging; +using System; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Models; -using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Core.Strings; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -23,22 +23,34 @@ namespace Umbraco.Cms.Core.PropertyEditors public class TextAreaPropertyEditor : DataEditor { private readonly IIOHelper _ioHelper; + private readonly IEditorConfigurationParser _editorConfigurationParser; + + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public TextAreaPropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + IIOHelper ioHelper) + : this(dataValueEditorFactory, ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } /// /// Initializes a new instance of the class. /// public TextAreaPropertyEditor( IDataValueEditorFactory dataValueEditorFactory, - IIOHelper ioHelper) + IIOHelper ioHelper, + IEditorConfigurationParser editorConfigurationParser) : base(dataValueEditorFactory) { _ioHelper = ioHelper; + _editorConfigurationParser = editorConfigurationParser; } /// protected override IDataValueEditor CreateValueEditor() => DataValueEditorFactory.Create(Attribute!); /// - protected override IConfigurationEditor CreateConfigurationEditor() => new TextAreaConfigurationEditor(_ioHelper); + protected override IConfigurationEditor CreateConfigurationEditor() => new TextAreaConfigurationEditor(_ioHelper, _editorConfigurationParser); } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/TextboxConfigurationEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/TextboxConfigurationEditor.cs deleted file mode 100644 index 0e6da0f2d1..0000000000 --- a/src/Umbraco.Infrastructure/PropertyEditors/TextboxConfigurationEditor.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - -using Umbraco.Cms.Core.IO; - -namespace Umbraco.Cms.Core.PropertyEditors -{ - /// - /// Represents the configuration editor for the textbox value editor. - /// - public class TextboxConfigurationEditor : ConfigurationEditor - { - public TextboxConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) - { - } - } -} diff --git a/src/Umbraco.Infrastructure/PropertyEditors/TextboxPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/TextboxPropertyEditor.cs index bd456b2d58..bbb536a38c 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/TextboxPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/TextboxPropertyEditor.cs @@ -1,12 +1,12 @@ // Copyright (c) Umbraco. // See LICENSE for more details. -using Microsoft.Extensions.Logging; +using System; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Models; -using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Core.Strings; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -22,16 +22,28 @@ namespace Umbraco.Cms.Core.PropertyEditors public class TextboxPropertyEditor : DataEditor { private readonly IIOHelper _ioHelper; + private readonly IEditorConfigurationParser _editorConfigurationParser; + + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public TextboxPropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + IIOHelper ioHelper) + : this(dataValueEditorFactory, ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } /// /// Initializes a new instance of the class. /// public TextboxPropertyEditor( IDataValueEditorFactory dataValueEditorFactory, - IIOHelper ioHelper) + IIOHelper ioHelper, + IEditorConfigurationParser editorConfigurationParser) : base(dataValueEditorFactory) { _ioHelper = ioHelper; + _editorConfigurationParser = editorConfigurationParser; } /// @@ -39,6 +51,6 @@ namespace Umbraco.Cms.Core.PropertyEditors DataValueEditorFactory.Create(Attribute!); /// - protected override IConfigurationEditor CreateConfigurationEditor() => new TextboxConfigurationEditor(_ioHelper); + protected override IConfigurationEditor CreateConfigurationEditor() => new TextboxConfigurationEditor(_ioHelper, _editorConfigurationParser); } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/TrueFalseConfigurationEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/TrueFalseConfigurationEditor.cs deleted file mode 100644 index 0b46402ca8..0000000000 --- a/src/Umbraco.Infrastructure/PropertyEditors/TrueFalseConfigurationEditor.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - -using Umbraco.Cms.Core.IO; - -namespace Umbraco.Cms.Core.PropertyEditors -{ - /// - /// Represents the configuration editor for the boolean value editor. - /// - public class TrueFalseConfigurationEditor : ConfigurationEditor - { - public TrueFalseConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) - { - } - } -} diff --git a/src/Umbraco.Infrastructure/PropertyEditors/TrueFalsePropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/TrueFalsePropertyEditor.cs index a594f946d5..0616a14df4 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/TrueFalsePropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/TrueFalsePropertyEditor.cs @@ -1,11 +1,11 @@ // Copyright (c) Umbraco. // See LICENSE for more details. -using Microsoft.Extensions.Logging; +using System; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; -using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Core.Strings; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Core.PropertyEditors { @@ -23,20 +23,32 @@ namespace Umbraco.Cms.Core.PropertyEditors public class TrueFalsePropertyEditor : DataEditor { private readonly IIOHelper _ioHelper; + private readonly IEditorConfigurationParser _editorConfigurationParser; + + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public TrueFalsePropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + IIOHelper ioHelper) + : this(dataValueEditorFactory, ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } /// /// Initializes a new instance of the class. /// public TrueFalsePropertyEditor( IDataValueEditorFactory dataValueEditorFactory, - IIOHelper ioHelper) + IIOHelper ioHelper, + IEditorConfigurationParser editorConfigurationParser) : base(dataValueEditorFactory) { _ioHelper = ioHelper; + _editorConfigurationParser = editorConfigurationParser; } /// - protected override IConfigurationEditor CreateConfigurationEditor() => new TrueFalseConfigurationEditor(_ioHelper); + protected override IConfigurationEditor CreateConfigurationEditor() => new TrueFalseConfigurationEditor(_ioHelper, _editorConfigurationParser); } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueListConfigurationEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueListConfigurationEditor.cs index fcb6dd8ae2..89bbd2642c 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ValueListConfigurationEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueListConfigurationEditor.cs @@ -1,11 +1,14 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json.Linq; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Web.Common.DependencyInjection; using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors @@ -18,7 +21,15 @@ namespace Umbraco.Cms.Core.PropertyEditors /// public class ValueListConfigurationEditor : ConfigurationEditor { - public ValueListConfigurationEditor(ILocalizedTextService textService, IIOHelper ioHelper) : base(ioHelper) + // Scheduled for removal in v12 + [Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")] + public ValueListConfigurationEditor(ILocalizedTextService textService, IIOHelper ioHelper) + : this(textService, ioHelper, StaticServiceProvider.Instance.GetRequiredService()) + { + } + + public ValueListConfigurationEditor(ILocalizedTextService textService, IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) + : base(ioHelper, editorConfigurationParser) { var items = Fields.First(x => x.Key == "items"); diff --git a/src/Umbraco.Infrastructure/Services/CacheInstructionService.cs b/src/Umbraco.Infrastructure/Services/CacheInstructionService.cs new file mode 100644 index 0000000000..12fd97acab --- /dev/null +++ b/src/Umbraco.Infrastructure/Services/CacheInstructionService.cs @@ -0,0 +1,533 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Umbraco.Cms.Core.Cache; +using Umbraco.Cms.Core.Configuration.Models; +using Umbraco.Cms.Core.Events; +using Umbraco.Cms.Core.Logging; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Persistence.Repositories; +using Umbraco.Cms.Core.Scoping; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Core.Sync; +using Umbraco.Extensions; + +namespace Umbraco.Cms +{ + namespace Core.Services.Implement + { + [Obsolete("Scheduled for removal in v12")] + public class CacheInstructionService : Infrastructure.Services.CacheInstructionService + { + public CacheInstructionService( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + ICacheInstructionRepository cacheInstructionRepository, + IProfilingLogger profilingLogger, + ILogger logger, + IOptions globalSettings) + : base( + provider, + loggerFactory, + eventMessagesFactory, + cacheInstructionRepository, + profilingLogger, + logger, + globalSettings) + { + } + } + } + + namespace Infrastructure.Services + { + /// + /// Implements providing a service for retrieving and saving cache instructions. + /// + public class CacheInstructionService : RepositoryService, ICacheInstructionService + { + private readonly ICacheInstructionRepository _cacheInstructionRepository; + private readonly IProfilingLogger _profilingLogger; + private readonly ILogger _logger; + private readonly GlobalSettings _globalSettings; + + /// + /// Initializes a new instance of the class. + /// + public CacheInstructionService( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + ICacheInstructionRepository cacheInstructionRepository, + IProfilingLogger profilingLogger, + ILogger logger, + IOptions globalSettings) + : base(provider, loggerFactory, eventMessagesFactory) + { + _cacheInstructionRepository = cacheInstructionRepository; + _profilingLogger = profilingLogger; + _logger = logger; + _globalSettings = globalSettings.Value; + } + + /// + public bool IsColdBootRequired(int lastId) + { + using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) + { + if (lastId <= 0) + { + var count = _cacheInstructionRepository.CountAll(); + + // If there are instructions but we haven't synced, then a cold boot is necessary. + if (count > 0) + { + return true; + } + } + else + { + // If the last synced instruction is not found in the db, then a cold boot is necessary. + if (!_cacheInstructionRepository.Exists(lastId)) + { + return true; + } + } + + return false; + } + } + + /// + public bool IsInstructionCountOverLimit(int lastId, int limit, out int count) + { + using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) + { + // Check for how many instructions there are to process, each row contains a count of the number of instructions contained in each + // row so we will sum these numbers to get the actual count. + count = _cacheInstructionRepository.CountPendingInstructions(lastId); + return count > limit; + } + } + + /// + public int GetMaxInstructionId() + { + using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) + { + return _cacheInstructionRepository.GetMaxId(); + } + } + + /// + public void DeliverInstructions(IEnumerable instructions, string localIdentity) + { + CacheInstruction entity = CreateCacheInstruction(instructions, localIdentity); + + using (ICoreScope scope = ScopeProvider.CreateCoreScope()) + { + _cacheInstructionRepository.Add(entity); + scope.Complete(); + } + } + + /// + public void DeliverInstructionsInBatches(IEnumerable instructions, string localIdentity) + { + // Write the instructions but only create JSON blobs with a max instruction count equal to MaxProcessingInstructionCount. + using (ICoreScope scope = ScopeProvider.CreateCoreScope()) + { + foreach (IEnumerable instructionsBatch in instructions.InGroupsOf( + _globalSettings.DatabaseServerMessenger.MaxProcessingInstructionCount)) + { + CacheInstruction entity = CreateCacheInstruction(instructionsBatch, localIdentity); + _cacheInstructionRepository.Add(entity); + } + + scope.Complete(); + } + } + + private CacheInstruction CreateCacheInstruction(IEnumerable instructions, + string localIdentity) => + new CacheInstruction(0, DateTime.UtcNow, JsonConvert.SerializeObject(instructions, Formatting.None), + localIdentity, instructions.Sum(x => x.JsonIdCount)); + + /// + public ProcessInstructionsResult ProcessInstructions( + CacheRefresherCollection cacheRefreshers, + ServerRole serverRole, + CancellationToken cancellationToken, + string localIdentity, + DateTime lastPruned, + int lastId) + { + using (_profilingLogger.DebugDuration("Syncing from database...")) + using (ICoreScope scope = ScopeProvider.CreateCoreScope()) + { + var numberOfInstructionsProcessed = ProcessDatabaseInstructions(cacheRefreshers, cancellationToken, + localIdentity, ref lastId); + + // Check for pruning throttling. + if (cancellationToken.IsCancellationRequested || (DateTime.UtcNow - lastPruned) <= + _globalSettings.DatabaseServerMessenger.TimeBetweenPruneOperations) + { + scope.Complete(); + return ProcessInstructionsResult.AsCompleted(numberOfInstructionsProcessed, lastId); + } + + var instructionsWerePruned = false; + switch (serverRole) + { + case ServerRole.Single: + case ServerRole.SchedulingPublisher: + PruneOldInstructions(); + instructionsWerePruned = true; + break; + } + + scope.Complete(); + + return instructionsWerePruned + ? ProcessInstructionsResult.AsCompletedAndPruned(numberOfInstructionsProcessed, lastId) + : ProcessInstructionsResult.AsCompleted(numberOfInstructionsProcessed, lastId); + } + } + + /// + /// Process instructions from the database. + /// + /// + /// Thread safety: this is NOT thread safe. Because it is NOT meant to run multi-threaded. + /// + /// Number of instructions processed. + private int ProcessDatabaseInstructions(CacheRefresherCollection cacheRefreshers, + CancellationToken cancellationToken, string localIdentity, ref int lastId) + { + // NOTE: + // We 'could' recurse to ensure that no remaining instructions are pending in the table before proceeding but I don't think that + // would be a good idea since instructions could keep getting added and then all other threads will probably get stuck from serving requests + // (depending on what the cache refreshers are doing). I think it's best we do the one time check, process them and continue, if there are + // pending requests after being processed, they'll just be processed on the next poll. + // + // TODO: not true if we're running on a background thread, assuming we can? + + // Only retrieve the top 100 (just in case there are tons). + // Even though MaxProcessingInstructionCount is by default 1000 we still don't want to process that many + // rows in one request thread since each row can contain a ton of instructions (until 7.5.5 in which case + // a row can only contain MaxProcessingInstructionCount). + const int MaxInstructionsToRetrieve = 100; + + // Only process instructions coming from a remote server, and ignore instructions coming from + // the local server as they've already been processed. We should NOT assume that the sequence of + // instructions in the database makes any sense whatsoever, because it's all async. + + // Tracks which ones have already been processed to avoid duplicates + var processed = new HashSet(); + var numberOfInstructionsProcessed = 0; + + // It would have been nice to do this in a Query instead of Fetch using a data reader to save + // some memory however we cannot do that because inside of this loop the cache refreshers are also + // performing some lookups which cannot be done with an active reader open. + IEnumerable pendingInstructions = + _cacheInstructionRepository.GetPendingInstructions(lastId, MaxInstructionsToRetrieve); + lastId = 0; + foreach (CacheInstruction instruction in pendingInstructions) + { + // If this flag gets set it means we're shutting down! In this case, we need to exit asap and cannot + // continue processing anything otherwise we'll hold up the app domain shutdown. + if (cancellationToken.IsCancellationRequested) + { + break; + } + + if (instruction.OriginIdentity == localIdentity) + { + // Just skip that local one but update lastId nevertheless. + lastId = instruction.Id; + continue; + } + + // Deserialize remote instructions & skip if it fails. + if (!TryDeserializeInstructions(instruction, out JArray? jsonInstructions)) + { + lastId = instruction.Id; // skip + continue; + } + + List instructionBatch = GetAllInstructions(jsonInstructions); + + // Process as per-normal. + var success = ProcessDatabaseInstructions(cacheRefreshers, instructionBatch, instruction, processed, + cancellationToken, ref lastId); + + // If they couldn't be all processed (i.e. we're shutting down) then exit. + if (success == false) + { + _logger.LogInformation( + "The current batch of instructions was not processed, app is shutting down"); + break; + } + + numberOfInstructionsProcessed++; + } + + return numberOfInstructionsProcessed; + } + + /// + /// Attempts to deserialize the instructions to a JArray. + /// + private bool TryDeserializeInstructions(CacheInstruction instruction, out JArray? jsonInstructions) + { + if (instruction.Instructions is null) + { + _logger.LogError("Failed to deserialize instructions ({DtoId}: 'null').", instruction.Id); + jsonInstructions = null; + return false; + } + + try + { + jsonInstructions = JsonConvert.DeserializeObject(instruction.Instructions); + return true; + } + catch (JsonException ex) + { + _logger.LogError(ex, "Failed to deserialize instructions ({DtoId}: '{DtoInstructions}').", + instruction.Id, + instruction.Instructions); + jsonInstructions = null; + return false; + } + } + + /// + /// Parses out the individual instructions to be processed. + /// + private static List GetAllInstructions(IEnumerable? jsonInstructions) + { + var result = new List(); + if (jsonInstructions is not null) + { + return result; + } + + foreach (JToken jsonItem in jsonInstructions!) + { + // Could be a JObject in which case we can convert to a RefreshInstruction. + // Otherwise it could be another JArray - in which case we'll iterate that. + if (jsonItem is JObject jsonObj) + { + RefreshInstruction? instruction = jsonObj.ToObject(); + if (instruction is not null) + { + result.Add(instruction); + } + } + else + { + var jsonInnerArray = (JArray)jsonItem; + result.AddRange(GetAllInstructions(jsonInnerArray)); // recurse + } + } + + return result; + } + + /// + /// Processes the instruction batch and checks for errors. + /// + /// + /// Tracks which instructions have already been processed to avoid duplicates + /// + /// Returns true if all instructions in the batch were processed, otherwise false if they could not be due to the app being shut down + /// + private bool ProcessDatabaseInstructions( + CacheRefresherCollection cacheRefreshers, + IReadOnlyCollection instructionBatch, + CacheInstruction instruction, + HashSet processed, + CancellationToken cancellationToken, + ref int lastId) + { + // Execute remote instructions & update lastId. + try + { + var result = NotifyRefreshers(cacheRefreshers, instructionBatch, processed, cancellationToken); + if (result) + { + // If all instructions were processed, set the last id. + lastId = instruction.Id; + } + + return result; + } + catch (Exception ex) + { + _logger.LogError( + ex, + "DISTRIBUTED CACHE IS NOT UPDATED. Failed to execute instructions ({DtoId}: '{DtoInstructions}'). Instruction is being skipped/ignored", + instruction.Id, + instruction.Instructions); + + // We cannot throw here because this invalid instruction will just keep getting processed over and over and errors + // will be thrown over and over. The only thing we can do is ignore and move on. + lastId = instruction.Id; + return false; + } + } + + /// + /// Executes the instructions against the cache refresher instances. + /// + /// + /// Returns true if all instructions were processed, otherwise false if the processing was interrupted (i.e. by app shutdown). + /// + private bool NotifyRefreshers( + CacheRefresherCollection cacheRefreshers, + IEnumerable instructions, + HashSet processed, + CancellationToken cancellationToken) + { + foreach (RefreshInstruction instruction in instructions) + { + // Check if the app is shutting down, we need to exit if this happens. + if (cancellationToken.IsCancellationRequested) + { + return false; + } + + // This has already been processed. + if (processed.Contains(instruction)) + { + continue; + } + + switch (instruction.RefreshType) + { + case RefreshMethodType.RefreshAll: + RefreshAll(cacheRefreshers, instruction.RefresherId); + break; + case RefreshMethodType.RefreshByGuid: + RefreshByGuid(cacheRefreshers, instruction.RefresherId, instruction.GuidId); + break; + case RefreshMethodType.RefreshById: + RefreshById(cacheRefreshers, instruction.RefresherId, instruction.IntId); + break; + case RefreshMethodType.RefreshByIds: + RefreshByIds(cacheRefreshers, instruction.RefresherId, instruction.JsonIds); + break; + case RefreshMethodType.RefreshByJson: + RefreshByJson(cacheRefreshers, instruction.RefresherId, instruction.JsonPayload); + break; + case RefreshMethodType.RemoveById: + RemoveById(cacheRefreshers, instruction.RefresherId, instruction.IntId); + break; + } + + processed.Add(instruction); + } + + return true; + } + + private void RefreshAll(CacheRefresherCollection cacheRefreshers, Guid uniqueIdentifier) + { + ICacheRefresher refresher = GetRefresher(cacheRefreshers, uniqueIdentifier); + refresher.RefreshAll(); + } + + private void RefreshByGuid(CacheRefresherCollection cacheRefreshers, Guid uniqueIdentifier, Guid id) + { + ICacheRefresher refresher = GetRefresher(cacheRefreshers, uniqueIdentifier); + refresher.Refresh(id); + } + + private void RefreshById(CacheRefresherCollection cacheRefreshers, Guid uniqueIdentifier, int id) + { + ICacheRefresher refresher = GetRefresher(cacheRefreshers, uniqueIdentifier); + refresher.Refresh(id); + } + + private void RefreshByIds(CacheRefresherCollection cacheRefreshers, Guid uniqueIdentifier, string? jsonIds) + { + ICacheRefresher refresher = GetRefresher(cacheRefreshers, uniqueIdentifier); + if (jsonIds is null) + { + return; + } + + var ids = JsonConvert.DeserializeObject(jsonIds); + if (ids is not null) + { + foreach (var id in ids) + { + refresher.Refresh(id); + } + } + } + + private void RefreshByJson(CacheRefresherCollection cacheRefreshers, Guid uniqueIdentifier, + string? jsonPayload) + { + IJsonCacheRefresher refresher = GetJsonRefresher(cacheRefreshers, uniqueIdentifier); + if (jsonPayload is not null) + { + refresher.Refresh(jsonPayload); + } + } + + private void RemoveById(CacheRefresherCollection cacheRefreshers, Guid uniqueIdentifier, int id) + { + ICacheRefresher refresher = GetRefresher(cacheRefreshers, uniqueIdentifier); + refresher.Remove(id); + } + + private ICacheRefresher GetRefresher(CacheRefresherCollection cacheRefreshers, Guid id) + { + ICacheRefresher? refresher = cacheRefreshers[id]; + if (refresher == null) + { + throw new InvalidOperationException("Cache refresher with ID \"" + id + "\" does not exist."); + } + + return refresher; + } + + private IJsonCacheRefresher GetJsonRefresher(CacheRefresherCollection cacheRefreshers, Guid id) => + GetJsonRefresher(GetRefresher(cacheRefreshers, id)); + + private static IJsonCacheRefresher GetJsonRefresher(ICacheRefresher refresher) + { + if (refresher is not IJsonCacheRefresher jsonRefresher) + { + throw new InvalidOperationException("Cache refresher with ID \"" + refresher.RefresherUniqueId + + "\" does not implement " + typeof(IJsonCacheRefresher) + "."); + } + + return jsonRefresher; + } + + /// + /// Remove old instructions from the database + /// + /// + /// Always leave the last (most recent) record in the db table, this is so that not all instructions are removed which would cause + /// the site to cold boot if there's been no instruction activity for more than TimeToRetainInstructions. + /// See: http://issues.umbraco.org/issue/U4-7643#comment=67-25085 + /// + private void PruneOldInstructions() + { + DateTime pruneDate = DateTime.UtcNow - _globalSettings.DatabaseServerMessenger.TimeToRetainInstructions; + _cacheInstructionRepository.DeleteInstructionsOlderThan(pruneDate); + } + } + } +} diff --git a/src/Umbraco.Infrastructure/Services/EditorConfigurationParser.cs b/src/Umbraco.Infrastructure/Services/EditorConfigurationParser.cs new file mode 100644 index 0000000000..d0b25e48aa --- /dev/null +++ b/src/Umbraco.Infrastructure/Services/EditorConfigurationParser.cs @@ -0,0 +1,70 @@ +using System.Collections.Generic; +using System.Reflection; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Umbraco.Cms.Core.PropertyEditors; +using Umbraco.Cms.Core.Services; +using Umbraco.Extensions; + +namespace Umbraco.Cms.Infrastructure.Services; + +public class EditorConfigurationParser : IEditorConfigurationParser +{ + public TConfiguration? ParseFromConfigurationEditor(IDictionary? editorValues, + IEnumerable fields) + { + // note - editorValue contains a mix of CLR types (string, int...) and JToken + // turning everything back into a JToken... might not be fastest but is simplest + // for now + + var o = new JObject(); + + foreach (var field in fields) + { + // field only, JsonPropertyAttribute is ignored here + // only keep fields that have a non-null/empty value + // rest will fall back to default during ToObject() + if (editorValues is not null && editorValues.TryGetValue(field.Key!, out var value) && value != null && (!(value is string stringValue) || !string.IsNullOrWhiteSpace(stringValue))) + { + if (value is JToken jtoken) + { + //if it's a jtoken then set it + o[field.PropertyName!] = jtoken; + } + else if (field.PropertyType == typeof(bool) && value is string sBool) + { + //if it's a boolean property type but a string is found, try to do a conversion + var converted = sBool.TryConvertTo(); + if (converted.Success) + o[field.PropertyName!] = converted.Result; + } + else + { + //default behavior + o[field.PropertyName!] = JToken.FromObject(value); + } + } + } + + return o.ToObject(); + } + + public Dictionary ParseToConfigurationEditor(TConfiguration? configuration) + { + string FieldNamer(PropertyInfo property) + { + // try the field + var field = property.GetCustomAttribute(); + if (field is not null && field.Key is not null) + { + return field.Key; + } + + // but the property may not be a field just an extra thing + var json = property.GetCustomAttribute(); + return json?.PropertyName ?? property.Name; + } + + return ObjectJsonExtensions.ToObjectDictionary(configuration, FieldNamer); + } +} diff --git a/src/Umbraco.Infrastructure/Services/Implement/CacheInstructionService.cs b/src/Umbraco.Infrastructure/Services/Implement/CacheInstructionService.cs deleted file mode 100644 index 1a6cc125cf..0000000000 --- a/src/Umbraco.Infrastructure/Services/Implement/CacheInstructionService.cs +++ /dev/null @@ -1,491 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Umbraco.Cms.Core.Cache; -using Umbraco.Cms.Core.Configuration.Models; -using Umbraco.Cms.Core.Events; -using Umbraco.Cms.Core.Logging; -using Umbraco.Cms.Core.Models; -using Umbraco.Cms.Core.Persistence.Repositories; -using Umbraco.Cms.Core.Scoping; -using Umbraco.Cms.Core.Sync; -using Umbraco.Extensions; - -namespace Umbraco.Cms.Core.Services.Implement -{ - /// - /// Implements providing a service for retrieving and saving cache instructions. - /// - public class CacheInstructionService : RepositoryService, ICacheInstructionService - { - private readonly ICacheInstructionRepository _cacheInstructionRepository; - private readonly IProfilingLogger _profilingLogger; - private readonly ILogger _logger; - private readonly GlobalSettings _globalSettings; - - /// - /// Initializes a new instance of the class. - /// - public CacheInstructionService( - ICoreScopeProvider provider, - ILoggerFactory loggerFactory, - IEventMessagesFactory eventMessagesFactory, - ICacheInstructionRepository cacheInstructionRepository, - IProfilingLogger profilingLogger, - ILogger logger, - IOptions globalSettings) - : base(provider, loggerFactory, eventMessagesFactory) - { - _cacheInstructionRepository = cacheInstructionRepository; - _profilingLogger = profilingLogger; - _logger = logger; - _globalSettings = globalSettings.Value; - } - - /// - public bool IsColdBootRequired(int lastId) - { - using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) - { - if (lastId <= 0) - { - var count = _cacheInstructionRepository.CountAll(); - - // If there are instructions but we haven't synced, then a cold boot is necessary. - if (count > 0) - { - return true; - } - } - else - { - // If the last synced instruction is not found in the db, then a cold boot is necessary. - if (!_cacheInstructionRepository.Exists(lastId)) - { - return true; - } - } - - return false; - } - } - /// - public bool IsInstructionCountOverLimit(int lastId, int limit, out int count) - { - using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) - { - // Check for how many instructions there are to process, each row contains a count of the number of instructions contained in each - // row so we will sum these numbers to get the actual count. - count = _cacheInstructionRepository.CountPendingInstructions(lastId); - return count > limit; - } - } - - /// - public int GetMaxInstructionId() - { - using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) - { - return _cacheInstructionRepository.GetMaxId(); - } - } - - /// - public void DeliverInstructions(IEnumerable instructions, string localIdentity) - { - CacheInstruction entity = CreateCacheInstruction(instructions, localIdentity); - - using (ICoreScope scope = ScopeProvider.CreateCoreScope()) - { - _cacheInstructionRepository.Add(entity); - scope.Complete(); - } - } - - /// - public void DeliverInstructionsInBatches(IEnumerable instructions, string localIdentity) - { - // Write the instructions but only create JSON blobs with a max instruction count equal to MaxProcessingInstructionCount. - using (ICoreScope scope = ScopeProvider.CreateCoreScope()) - { - foreach (IEnumerable instructionsBatch in instructions.InGroupsOf(_globalSettings.DatabaseServerMessenger.MaxProcessingInstructionCount)) - { - CacheInstruction entity = CreateCacheInstruction(instructionsBatch, localIdentity); - _cacheInstructionRepository.Add(entity); - } - - scope.Complete(); - } - } - - private CacheInstruction CreateCacheInstruction(IEnumerable instructions, string localIdentity) => - new CacheInstruction(0, DateTime.UtcNow, JsonConvert.SerializeObject(instructions, Formatting.None), localIdentity, instructions.Sum(x => x.JsonIdCount)); - - /// - public ProcessInstructionsResult ProcessInstructions( - CacheRefresherCollection cacheRefreshers, - ServerRole serverRole, - CancellationToken cancellationToken, - string localIdentity, - DateTime lastPruned, - int lastId) - { - using (_profilingLogger.DebugDuration("Syncing from database...")) - using (ICoreScope scope = ScopeProvider.CreateCoreScope()) - { - var numberOfInstructionsProcessed = ProcessDatabaseInstructions(cacheRefreshers, cancellationToken, localIdentity, ref lastId); - - // Check for pruning throttling. - if (cancellationToken.IsCancellationRequested || (DateTime.UtcNow - lastPruned) <= _globalSettings.DatabaseServerMessenger.TimeBetweenPruneOperations) - { - scope.Complete(); - return ProcessInstructionsResult.AsCompleted(numberOfInstructionsProcessed, lastId); - } - - var instructionsWerePruned = false; - switch (serverRole) - { - case ServerRole.Single: - case ServerRole.SchedulingPublisher: - PruneOldInstructions(); - instructionsWerePruned = true; - break; - } - - scope.Complete(); - - return instructionsWerePruned - ? ProcessInstructionsResult.AsCompletedAndPruned(numberOfInstructionsProcessed, lastId) - : ProcessInstructionsResult.AsCompleted(numberOfInstructionsProcessed, lastId); - } - } - - /// - /// Process instructions from the database. - /// - /// - /// Thread safety: this is NOT thread safe. Because it is NOT meant to run multi-threaded. - /// - /// Number of instructions processed. - private int ProcessDatabaseInstructions(CacheRefresherCollection cacheRefreshers, CancellationToken cancellationToken, string localIdentity, ref int lastId) - { - // NOTE: - // We 'could' recurse to ensure that no remaining instructions are pending in the table before proceeding but I don't think that - // would be a good idea since instructions could keep getting added and then all other threads will probably get stuck from serving requests - // (depending on what the cache refreshers are doing). I think it's best we do the one time check, process them and continue, if there are - // pending requests after being processed, they'll just be processed on the next poll. - // - // TODO: not true if we're running on a background thread, assuming we can? - - // Only retrieve the top 100 (just in case there are tons). - // Even though MaxProcessingInstructionCount is by default 1000 we still don't want to process that many - // rows in one request thread since each row can contain a ton of instructions (until 7.5.5 in which case - // a row can only contain MaxProcessingInstructionCount). - const int MaxInstructionsToRetrieve = 100; - - // Only process instructions coming from a remote server, and ignore instructions coming from - // the local server as they've already been processed. We should NOT assume that the sequence of - // instructions in the database makes any sense whatsoever, because it's all async. - - // Tracks which ones have already been processed to avoid duplicates - var processed = new HashSet(); - var numberOfInstructionsProcessed = 0; - - // It would have been nice to do this in a Query instead of Fetch using a data reader to save - // some memory however we cannot do that because inside of this loop the cache refreshers are also - // performing some lookups which cannot be done with an active reader open. - IEnumerable pendingInstructions = _cacheInstructionRepository.GetPendingInstructions(lastId, MaxInstructionsToRetrieve); - lastId = 0; - foreach (CacheInstruction instruction in pendingInstructions) - { - // If this flag gets set it means we're shutting down! In this case, we need to exit asap and cannot - // continue processing anything otherwise we'll hold up the app domain shutdown. - if (cancellationToken.IsCancellationRequested) - { - break; - } - - if (instruction.OriginIdentity == localIdentity) - { - // Just skip that local one but update lastId nevertheless. - lastId = instruction.Id; - continue; - } - - // Deserialize remote instructions & skip if it fails. - if (!TryDeserializeInstructions(instruction, out JArray? jsonInstructions)) - { - lastId = instruction.Id; // skip - continue; - } - - List instructionBatch = GetAllInstructions(jsonInstructions); - - // Process as per-normal. - var success = ProcessDatabaseInstructions(cacheRefreshers, instructionBatch, instruction, processed, cancellationToken, ref lastId); - - // If they couldn't be all processed (i.e. we're shutting down) then exit. - if (success == false) - { - _logger.LogInformation("The current batch of instructions was not processed, app is shutting down"); - break; - } - - numberOfInstructionsProcessed++; - } - - return numberOfInstructionsProcessed; - } - - /// - /// Attempts to deserialize the instructions to a JArray. - /// - private bool TryDeserializeInstructions(CacheInstruction instruction, out JArray? jsonInstructions) - { - if (instruction.Instructions is null) - { - _logger.LogError("Failed to deserialize instructions ({DtoId}: 'null').", instruction.Id); - jsonInstructions = null; - return false; - } - - try - { - jsonInstructions = JsonConvert.DeserializeObject(instruction.Instructions); - return true; - } - catch (JsonException ex) - { - _logger.LogError(ex, "Failed to deserialize instructions ({DtoId}: '{DtoInstructions}').", - instruction.Id, - instruction.Instructions); - jsonInstructions = null; - return false; - } - } - - /// - /// Parses out the individual instructions to be processed. - /// - private static List GetAllInstructions(IEnumerable? jsonInstructions) - { - var result = new List(); - if (jsonInstructions is not null) - { - return result; - } - - foreach (JToken jsonItem in jsonInstructions!) - { - // Could be a JObject in which case we can convert to a RefreshInstruction. - // Otherwise it could be another JArray - in which case we'll iterate that. - if (jsonItem is JObject jsonObj) - { - RefreshInstruction? instruction = jsonObj.ToObject(); - if (instruction is not null) - { - result.Add(instruction); - } - } - else - { - var jsonInnerArray = (JArray)jsonItem; - result.AddRange(GetAllInstructions(jsonInnerArray)); // recurse - } - } - - return result; - } - - /// - /// Processes the instruction batch and checks for errors. - /// - /// - /// Tracks which instructions have already been processed to avoid duplicates - /// - /// Returns true if all instructions in the batch were processed, otherwise false if they could not be due to the app being shut down - /// - private bool ProcessDatabaseInstructions( - CacheRefresherCollection cacheRefreshers, - IReadOnlyCollection instructionBatch, - CacheInstruction instruction, - HashSet processed, - CancellationToken cancellationToken, - ref int lastId) - { - // Execute remote instructions & update lastId. - try - { - var result = NotifyRefreshers(cacheRefreshers, instructionBatch, processed, cancellationToken); - if (result) - { - // If all instructions were processed, set the last id. - lastId = instruction.Id; - } - - return result; - } - catch (Exception ex) - { - _logger.LogError( - ex, - "DISTRIBUTED CACHE IS NOT UPDATED. Failed to execute instructions ({DtoId}: '{DtoInstructions}'). Instruction is being skipped/ignored", - instruction.Id, - instruction.Instructions); - - // We cannot throw here because this invalid instruction will just keep getting processed over and over and errors - // will be thrown over and over. The only thing we can do is ignore and move on. - lastId = instruction.Id; - return false; - } - } - - /// - /// Executes the instructions against the cache refresher instances. - /// - /// - /// Returns true if all instructions were processed, otherwise false if the processing was interrupted (i.e. by app shutdown). - /// - private bool NotifyRefreshers( - CacheRefresherCollection cacheRefreshers, - IEnumerable instructions, - HashSet processed, - CancellationToken cancellationToken) - { - foreach (RefreshInstruction instruction in instructions) - { - // Check if the app is shutting down, we need to exit if this happens. - if (cancellationToken.IsCancellationRequested) - { - return false; - } - - // This has already been processed. - if (processed.Contains(instruction)) - { - continue; - } - - switch (instruction.RefreshType) - { - case RefreshMethodType.RefreshAll: - RefreshAll(cacheRefreshers, instruction.RefresherId); - break; - case RefreshMethodType.RefreshByGuid: - RefreshByGuid(cacheRefreshers, instruction.RefresherId, instruction.GuidId); - break; - case RefreshMethodType.RefreshById: - RefreshById(cacheRefreshers, instruction.RefresherId, instruction.IntId); - break; - case RefreshMethodType.RefreshByIds: - RefreshByIds(cacheRefreshers, instruction.RefresherId, instruction.JsonIds); - break; - case RefreshMethodType.RefreshByJson: - RefreshByJson(cacheRefreshers, instruction.RefresherId, instruction.JsonPayload); - break; - case RefreshMethodType.RemoveById: - RemoveById(cacheRefreshers, instruction.RefresherId, instruction.IntId); - break; - } - - processed.Add(instruction); - } - - return true; - } - - private void RefreshAll(CacheRefresherCollection cacheRefreshers, Guid uniqueIdentifier) - { - ICacheRefresher refresher = GetRefresher(cacheRefreshers, uniqueIdentifier); - refresher.RefreshAll(); - } - - private void RefreshByGuid(CacheRefresherCollection cacheRefreshers, Guid uniqueIdentifier, Guid id) - { - ICacheRefresher refresher = GetRefresher(cacheRefreshers, uniqueIdentifier); - refresher.Refresh(id); - } - - private void RefreshById(CacheRefresherCollection cacheRefreshers, Guid uniqueIdentifier, int id) - { - ICacheRefresher refresher = GetRefresher(cacheRefreshers, uniqueIdentifier); - refresher.Refresh(id); - } - - private void RefreshByIds(CacheRefresherCollection cacheRefreshers, Guid uniqueIdentifier, string? jsonIds) - { - ICacheRefresher refresher = GetRefresher(cacheRefreshers, uniqueIdentifier); - if (jsonIds is null) - { - return; - } - - var ids = JsonConvert.DeserializeObject(jsonIds); - if (ids is not null) - { - foreach (var id in ids) - { - refresher.Refresh(id); - } - } - } - - private void RefreshByJson(CacheRefresherCollection cacheRefreshers, Guid uniqueIdentifier, string? jsonPayload) - { - IJsonCacheRefresher refresher = GetJsonRefresher(cacheRefreshers, uniqueIdentifier); - if (jsonPayload is not null) - { - refresher.Refresh(jsonPayload); - } - - } - - private void RemoveById(CacheRefresherCollection cacheRefreshers, Guid uniqueIdentifier, int id) - { - ICacheRefresher refresher = GetRefresher(cacheRefreshers, uniqueIdentifier); - refresher.Remove(id); - } - - private ICacheRefresher GetRefresher(CacheRefresherCollection cacheRefreshers, Guid id) - { - ICacheRefresher? refresher = cacheRefreshers[id]; - if (refresher == null) - { - throw new InvalidOperationException("Cache refresher with ID \"" + id + "\" does not exist."); - } - - return refresher; - } - - private IJsonCacheRefresher GetJsonRefresher(CacheRefresherCollection cacheRefreshers, Guid id) => GetJsonRefresher(GetRefresher(cacheRefreshers, id)); - - private static IJsonCacheRefresher GetJsonRefresher(ICacheRefresher refresher) - { - if (refresher is not IJsonCacheRefresher jsonRefresher) - { - throw new InvalidOperationException("Cache refresher with ID \"" + refresher.RefresherUniqueId + "\" does not implement " + typeof(IJsonCacheRefresher) + "."); - } - - return jsonRefresher; - } - - /// - /// Remove old instructions from the database - /// - /// - /// Always leave the last (most recent) record in the db table, this is so that not all instructions are removed which would cause - /// the site to cold boot if there's been no instruction activity for more than TimeToRetainInstructions. - /// See: http://issues.umbraco.org/issue/U4-7643#comment=67-25085 - /// - private void PruneOldInstructions() - { - DateTime pruneDate = DateTime.UtcNow - _globalSettings.DatabaseServerMessenger.TimeToRetainInstructions; - _cacheInstructionRepository.DeleteInstructionsOlderThan(pruneDate); - } - } -} diff --git a/src/Umbraco.PublishedCache.NuCache/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.PublishedCache.NuCache/DependencyInjection/UmbracoBuilderExtensions.cs index 13b79fb1a1..e7fad750df 100644 --- a/src/Umbraco.PublishedCache.NuCache/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.PublishedCache.NuCache/DependencyInjection/UmbracoBuilderExtensions.cs @@ -6,6 +6,7 @@ using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Notifications; +using Umbraco.Cms.Core.Persistence.Repositories; using Umbraco.Cms.Core.PropertyEditors; using Umbraco.Cms.Core.PublishedCache; using Umbraco.Cms.Core.Scoping; @@ -13,7 +14,6 @@ using Umbraco.Cms.Core.Services; using Umbraco.Cms.Infrastructure.PublishedCache; using Umbraco.Cms.Infrastructure.PublishedCache.DataSource; using Umbraco.Cms.Infrastructure.PublishedCache.Persistence; -using Umbraco.Cms.Infrastructure.Scoping; namespace Umbraco.Extensions { @@ -43,7 +43,7 @@ namespace Umbraco.Extensions // TODO: Gotta wonder how much this does actually improve perf? It's a lot of weird code to make this happen so hope it's worth it builder.Services.AddUnique(factory => { - var idkSvc = new IdKeyMap(factory.GetRequiredService(), factory.GetRequiredService()); + var idkSvc = new IdKeyMap(factory.GetRequiredService(), factory.GetRequiredService()); if (factory.GetRequiredService() is PublishedSnapshotService publishedSnapshotService) { idkSvc.SetMapper(UmbracoObjectTypes.Document, id => publishedSnapshotService.GetDocumentUid(id), uid => publishedSnapshotService.GetDocumentId(uid)); diff --git a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs index 4bc2a49525..868942653b 100644 --- a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs @@ -161,6 +161,7 @@ namespace Umbraco.Extensions // aspnet app lifetime mgmt builder.Services.AddUnique(); builder.Services.AddUnique(); + builder.Services.AddTransient(); return builder; } diff --git a/src/Umbraco.Web.Common/Mvc/IpAddressUtilities.cs b/src/Umbraco.Web.Common/Mvc/IpAddressUtilities.cs new file mode 100644 index 0000000000..ab9ef5d0b9 --- /dev/null +++ b/src/Umbraco.Web.Common/Mvc/IpAddressUtilities.cs @@ -0,0 +1,17 @@ +using System.Net; +using Umbraco.Cms.Core.Services; + +namespace Umbraco.Cms.Web.Common.Mvc; + +public class IpAddressUtilities : IIpAddressUtilities +{ + public bool IsAllowListed(IPAddress clientIpAddress, string allowedIpString) + { + if (IPNetwork.TryParse(allowedIpString, out IPNetwork allowedIp) && allowedIp.Contains(clientIpAddress)) + { + return true; + } + + return false; + } +} diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs index 5ef60b9ecb..5fc3917b35 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs @@ -273,8 +273,9 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Web.BackOffice.Filters { public ComplexTestEditor( IDataValueEditorFactory dataValueEditorFactory, - IIOHelper ioHelper) - : base(dataValueEditorFactory, ioHelper) + IIOHelper ioHelper, + IEditorConfigurationParser editorConfigurationParser) + : base(dataValueEditorFactory, ioHelper, editorConfigurationParser) { } diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Models/VariationTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Models/VariationTests.cs index c2d5b785c9..026b0bfe16 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Models/VariationTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Models/VariationTests.cs @@ -584,6 +584,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Models IIOHelper ioHelper = Mock.Of(); IDataTypeService dataTypeService = Mock.Of(); ILocalizedTextService localizedTextService = Mock.Of(); + IEditorConfigurationParser editorConfigurationParser = Mock.Of(); var attribute = new DataEditorAttribute("a", "a", "a"); IDataValueEditorFactory dataValueEditorFactory = Mock.Of(x @@ -592,7 +593,8 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Models var textBoxEditor = new TextboxPropertyEditor( dataValueEditorFactory, - ioHelper); + ioHelper, + editorConfigurationParser); var serializer = new ConfigurationEditorJsonSerializer(); diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/ColorListValidatorTest.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/ColorListValidatorTest.cs index 6f93386208..da7f22716a 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/ColorListValidatorTest.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/ColorListValidatorTest.cs @@ -25,7 +25,8 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors private ColorPickerPropertyEditor ColorPickerPropertyEditor => new ColorPickerPropertyEditor( Mock.Of(), Mock.Of(), - new JsonNetSerializer()); + new JsonNetSerializer(), + Mock.Of()); [Test] public void Only_Tests_On_JArray() diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollectionTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollectionTests.cs index 944b35023f..7ccfa14e81 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollectionTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollectionTests.cs @@ -34,6 +34,8 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors private IShortStringHelper ShortStringHelper { get; } = Mock.Of(); + private IEditorConfigurationParser EditorConfigurationParser { get; } = Mock.Of(); + [Test] public void GetAllReferences_All_Variants_With_IDataValueReferenceFactory() { @@ -42,7 +44,8 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors // label does not implement IDataValueReference var labelEditor = new LabelPropertyEditor( DataValueEditorFactory, - IOHelper); + IOHelper, + EditorConfigurationParser); var propertyEditors = new PropertyEditorCollection(new DataEditorCollection(() => labelEditor.Yield())); var trackedUdi1 = Udi.Create(Constants.UdiEntityType.Media, Guid.NewGuid()).ToString(); var trackedUdi2 = Udi.Create(Constants.UdiEntityType.Media, Guid.NewGuid()).ToString(); @@ -108,7 +111,8 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors // mediaPicker does implement IDataValueReference var mediaPicker = new MediaPickerPropertyEditor( DataValueEditorFactory, - IOHelper); + IOHelper, + EditorConfigurationParser); var propertyEditors = new PropertyEditorCollection(new DataEditorCollection(() => mediaPicker.Yield())); var trackedUdi1 = Udi.Create(Constants.UdiEntityType.Media, Guid.NewGuid()).ToString(); var trackedUdi2 = Udi.Create(Constants.UdiEntityType.Media, Guid.NewGuid()).ToString(); @@ -174,7 +178,8 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors // mediaPicker does implement IDataValueReference var mediaPicker = new MediaPickerPropertyEditor( DataValueEditorFactory, - IOHelper); + IOHelper, + EditorConfigurationParser); var propertyEditors = new PropertyEditorCollection(new DataEditorCollection(() => mediaPicker.Yield())); var trackedUdi1 = Udi.Create(Constants.UdiEntityType.Media, Guid.NewGuid()).ToString(); var trackedUdi2 = Udi.Create(Constants.UdiEntityType.Media, Guid.NewGuid()).ToString(); diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/EnsureUniqueValuesValidatorTest.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/EnsureUniqueValuesValidatorTest.cs index 5f60ad3e54..da264a216a 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/EnsureUniqueValuesValidatorTest.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/EnsureUniqueValuesValidatorTest.cs @@ -26,7 +26,8 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors private ColorPickerPropertyEditor ColorPickerPropertyEditor => new ColorPickerPropertyEditor( Mock.Of(), Mock.Of(), - new JsonNetSerializer()); + new JsonNetSerializer(), + Mock.Of()); [Test] public void Only_Tests_On_JArray() { @@ -38,7 +39,8 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors new ColorPickerPropertyEditor( Mock.Of(), Mock.Of(), - new JsonNetSerializer())); + new JsonNetSerializer(), + Mock.Of())); Assert.AreEqual(0, result.Count()); } diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/MultiValuePropertyEditorTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/MultiValuePropertyEditorTests.cs index 316de73efb..a38d23eb0e 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/MultiValuePropertyEditorTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/MultiValuePropertyEditorTests.cs @@ -35,7 +35,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors { var dataValueEditorFactoryMock = new Mock(); var serializer = new ConfigurationEditorJsonSerializer(); - var checkBoxListPropertyEditor = new CheckBoxListPropertyEditor(dataValueEditorFactoryMock.Object, Mock.Of(),Mock.Of()); + var checkBoxListPropertyEditor = new CheckBoxListPropertyEditor(dataValueEditorFactoryMock.Object, Mock.Of(),Mock.Of(), Mock.Of()); var dataType = new DataType(checkBoxListPropertyEditor, serializer) { Configuration = new ValueListConfiguration @@ -77,7 +77,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors var dataValueEditorFactoryMock = new Mock(); var serializer = new ConfigurationEditorJsonSerializer(); - var checkBoxListPropertyEditor = new CheckBoxListPropertyEditor(dataValueEditorFactoryMock.Object, Mock.Of(),Mock.Of()); + var checkBoxListPropertyEditor = new CheckBoxListPropertyEditor(dataValueEditorFactoryMock.Object, Mock.Of(),Mock.Of(), Mock.Of()); var dataType = new DataType(checkBoxListPropertyEditor, serializer) { Configuration = new ValueListConfiguration @@ -141,7 +141,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors } }; - var editor = new ValueListConfigurationEditor(Mock.Of(), Mock.Of()); + var editor = new ValueListConfigurationEditor(Mock.Of(), Mock.Of(), Mock.Of()); Dictionary result = editor.ToConfigurationEditor(configuration); diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Published/NestedContentTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Published/NestedContentTests.cs index 742e1b9c76..4f2f018bfc 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Published/NestedContentTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Published/NestedContentTests.cs @@ -37,7 +37,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Published ILocalizationService localizationService = Mock.Of(); PropertyEditorCollection editors = null; - var editor = new NestedContentPropertyEditor(Mock.Of(),Mock.Of()); + var editor = new NestedContentPropertyEditor(Mock.Of(),Mock.Of(), Mock.Of()); editors = new PropertyEditorCollection(new DataEditorCollection(() => new DataEditor[] { editor })); var serializer = new ConfigurationEditorJsonSerializer(); @@ -70,7 +70,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Published } }; - var dataType3 = new DataType(new TextboxPropertyEditor(Mock.Of(),Mock.Of()), serializer) + var dataType3 = new DataType(new TextboxPropertyEditor(Mock.Of(),Mock.Of(), Mock.Of()), serializer) { Id = 3 }; diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Services/BasicAuthServiceTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Services/BasicAuthServiceTests.cs index 6322debaab..c59dd16f10 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Services/BasicAuthServiceTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Services/BasicAuthServiceTests.cs @@ -3,8 +3,11 @@ using System.Net; using Microsoft.Extensions.Options; using Moq; using NUnit.Framework; +using Umbraco.Cms.Core.Configuration; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Services.Implement; +using Umbraco.Cms.Web.Common.Mvc; +using IpAddressUtilities = Umbraco.Cms.Web.Common.Mvc.IpAddressUtilities; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Services { @@ -15,7 +18,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Services [TestCase(false, ExpectedResult = false)] public bool IsBasicAuthEnabled(bool enabled) { - var sut = new BasicAuthService(Mock.Of>(_ => _.CurrentValue == new BasicAuthSettings() {Enabled = enabled})); + var sut = new BasicAuthService(Mock.Of>(_ => _.CurrentValue == new BasicAuthSettings() {Enabled = enabled}), new IpAddressUtilities()); return sut.IsBasicAuthEnabled(); } @@ -29,7 +32,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Services public bool IsIpAllowListed(string clientIpAddress, string commaSeperatedAllowlist) { var allowedIPs = commaSeperatedAllowlist.Split(",").Select(x=>x.Trim()).ToArray(); - var sut = new BasicAuthService(Mock.Of>(_ => _.CurrentValue == new BasicAuthSettings() {AllowedIPs = allowedIPs})); + var sut = new BasicAuthService(Mock.Of>(_ => _.CurrentValue == new BasicAuthSettings() {AllowedIPs = allowedIPs}), new IpAddressUtilities()); return sut.IsIpAllowListed(IPAddress.Parse(clientIpAddress)); }