From 718a7a47cddfefc4e04b7b10afaec5b2cb87c957 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20Knippers?= Date: Wed, 27 Sep 2023 11:00:00 +0200 Subject: [PATCH] Enable nullability and fix all warnings --- .gitignore | 66 +--- Nuget.Config | 10 - .editorconfig => src/.editorconfig | 0 src/{Perplex.ContentBlocks => }/.prettierrc | 0 src/Directory.Build.props | 13 +- .../Categories/Constants.Categories.cs | 13 +- .../Categories/ContentBlockCategory.cs | 19 +- .../ContentBlockCategoryComposer.cs | 29 +- .../Categories/IContentBlockCategory.cs | 37 +- .../IContentBlockCategoryRepository.cs | 16 +- .../InMemoryContentBlockCategoryRepository.cs | 76 ++-- .../Definitions/ContentBlockDefinition.cs | 37 +- .../ContentBlockDefinitionComposer.cs | 32 +- .../ContentBlockDefinitionFilterer.cs | 76 ++-- .../Definitions/ContentBlockLayout.cs | 17 +- .../ContentBlocksDefinitionApiController.cs | 104 +++--- .../Definitions/IContentBlockDefinition.cs | 43 ++- .../IContentBlockDefinitionFilterer.cs | 19 +- .../IContentBlockDefinitionRepository.cs | 20 +- .../Definitions/IContentBlockLayout.cs | 25 +- ...nMemoryContentBlockDefinitionRepository.cs | 50 ++- .../Perplex.ContentBlocks.Core.csproj | 8 +- .../Presets/ContentBlockPreset.cs | 23 +- .../Presets/ContentBlockPresetsComposer.cs | 29 +- .../Presets/ContentBlockVariantPreset.cs | 22 +- .../Presets/ContentBlocksPreset.cs | 27 +- .../ContentBlocksPresetApiController.cs | 39 +- .../Presets/IContentBlockPreset.cs | 55 ++- .../Presets/IContentBlockVariantPreset.cs | 31 +- .../Presets/IContentBlocksPreset.cs | 20 +- .../Presets/IContentBlocksPresetRepository.cs | 18 +- .../InMemoryContentBlocksPresetRepository.cs | 80 ++-- .../Preview/Constants.Preview.cs | 17 +- .../ContentBlocksPreviewApiController.cs | 237 ++++++------ .../Preview/ContentBlocksPreviewComposer.cs | 36 +- .../Preview/CookieBasedPreviewModeProvider.cs | 23 +- .../DefaultPreviewScrollScriptProvider.cs | 19 +- .../Preview/IPreviewModeProvider.cs | 9 +- .../Preview/IPreviewScrollScriptProvider.cs | 19 +- .../Constants.PropertyEditor.Configuration.cs | 33 +- .../ContentBlocksConfiguration.cs | 101 +++-- .../ContentBlocksConfigurationEditor.cs | 350 ++++++++---------- .../Constants.PropertyEditor.cs | 17 +- .../ContentBlocksManifestFilter.cs | 132 ++++--- .../ContentBlocksPropertyEditor.cs | 163 +++----- .../PropertyEditor/ContentBlocksValidator.cs | 126 +++---- .../ContentBlocksValueConverter.cs | 254 ++++++------- .../ContentBlocksValueEditor.cs | 301 +++++++-------- .../ModelValue/ContentBlockInterValue.cs | 16 +- .../ModelValue/ContentBlockModelValue.cs | 63 ++-- .../ContentBlockVariantModelValue.cs | 26 +- .../ModelValue/ContentBlocksInterValue.cs | 13 +- .../ModelValue/ContentBlocksModelValue.cs | 20 +- .../ContentBlocksModelValueComposer.cs | 32 +- .../ContentBlocksModelValueCopyingHandler.cs | 179 ++++----- .../ContentBlocksModelValueDeserializer.cs | 74 ++-- .../ContentBlockProvidersComposer.cs | 29 +- .../Providers/DocumentTypeAliasProvider.cs | 35 +- .../Providers/IDocumentTypeAliasProvider.cs | 9 +- .../Rendering/ContentBlockRenderer.cs | 229 ++++-------- .../Rendering/ContentBlockViewModel.cs | 29 +- .../ContentBlockViewModelFactory{T}.cs | 22 +- .../Rendering/ContentBlockViewModel{T}.cs | 33 +- .../Rendering/ContentBlocks.cs | 14 +- .../ContentBlocksRenderingComposer.cs | 43 +-- .../HtmlHelperExtensions.Rendering.cs | 126 ++----- .../Rendering/IContentBlockRenderer.cs | 48 +-- .../Rendering/IContentBlockViewModel.cs | 19 +- .../IContentBlockViewModelFactory.cs | 15 +- .../IContentBlockViewModelFactory{T}.cs | 15 +- .../Rendering/IContentBlockViewModel{T}.cs | 15 +- .../Rendering/IContentBlocks.cs | 11 +- .../Utils/ContentBlockUtils.cs | 112 +++--- .../Utils/ContentBlockUtilsComposer.cs | 29 +- .../Utils/Cookies/CookiesComposer.cs | 29 +- .../Utils/Cookies/HttpCookiesAccessor.cs | 39 +- .../Utils/Cookies/IHttpCookiesAccessor.cs | 9 +- .../ContentBlockDefaultVariantSelector.cs | 19 +- .../Variants/ContentBlocksVariantsComposer.cs | 29 +- .../Variants/IContentBlockVariantSelector.cs | 28 +- .../Perplex.ContentBlocks.csproj | 6 +- version | 9 +- 82 files changed, 1779 insertions(+), 2536 deletions(-) delete mode 100644 Nuget.Config rename .editorconfig => src/.editorconfig (100%) rename src/{Perplex.ContentBlocks => }/.prettierrc (100%) diff --git a/.gitignore b/.gitignore index b5b6074..8853625 100644 --- a/.gitignore +++ b/.gitignore @@ -1,62 +1,10 @@ -# Inspired by, but heavily reduced version of this: -# https://github.com/github/gitignore/blob/master/VisualStudio.gitignore - -# User-specific files -*.suo -*.user - -# Build results -[Dd]ebug/ -[Rr]elease/ -x64/ -x86/ -[Oo]bj/ -[Bb]in/ -packages/ - -# Logs -[Ll]og/ - -# Visual Studio 2015 cache/options directory .vs/ - -# Node.js Tools for Visual Studio +.vscode/ +.config/ +.github/ +bin/ +obj/ node_modules/ -# Typescript v1 declaration files -typings/ - -## Ignore Umbraco files/folders generated for each instance -## -## Get latest from https://github.com/github/gitignore/blob/master/Umbraco.gitignore - -# Umbraco -# Ignore unimportant folders generated by Umbraco -**/App_Data/Logs/ -**/App_Data/[Pp]review/ -**/App_Data/TEMP/ -**/App_Data/NuGetBackup/ -**/App_Data/NuCache* -**/[Mm]edia -**/App_Data/umbraco.config -**/App_Data/cache/ -# ModelsBuilder out of date flag -ood.flag - -# Don't ignore Umbraco packages (VisualStudio.gitignore mistakes this for a NuGet packages folder) -# Make sure to include details from VisualStudio.gitignore BEFORE this -!**/App_Data/[Pp]ackages/ -!**/[Uu]mbraco/[Dd]eveloper/[Pp]ackages - -# DemoWebsite -src/DemoWebsite*/App_Plugins/Perplex.ContentBlocks -src/DemoWebsite*/App_Data/Models -src/DemoWebsite*/App_Data/Umbraco.sdf -src/DemoWebsite*/[Uu]mbraco/* -!src/DemoWebsite.v9/[Uu]mbraco/models -*.css - -# NuGet / Our Umbraco packages -pkg/**/*.nupkg -pkg/**/*.zip -/src/.vscode/ \ No newline at end of file +**/*.nupkg +**/App_Plugins/**/*.css diff --git a/Nuget.Config b/Nuget.Config deleted file mode 100644 index 2613af4..0000000 --- a/Nuget.Config +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.editorconfig b/src/.editorconfig similarity index 100% rename from .editorconfig rename to src/.editorconfig diff --git a/src/Perplex.ContentBlocks/.prettierrc b/src/.prettierrc similarity index 100% rename from src/Perplex.ContentBlocks/.prettierrc rename to src/.prettierrc diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 16edf36..12dab66 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,14 +1,25 @@  + + net6.0 + enable + enable + True + embedded + + 3.0.0-alpha.1 - Perplex Digital + Perplex Digital + $(Company) + © $(Company) https://github.com/PerplexDigital/Perplex.ContentBlocks icon.png https://github.com/PerplexDigital/Perplex.ContentBlocks git MIT + $(NoWarn);CS1591 diff --git a/src/Perplex.ContentBlocks.Core/Categories/Constants.Categories.cs b/src/Perplex.ContentBlocks.Core/Categories/Constants.Categories.cs index 9e25af5..f98fd25 100644 --- a/src/Perplex.ContentBlocks.Core/Categories/Constants.Categories.cs +++ b/src/Perplex.ContentBlocks.Core/Categories/Constants.Categories.cs @@ -1,13 +1,12 @@ using System; -namespace Perplex.ContentBlocks +namespace Perplex.ContentBlocks; + +public static partial class Constants { - public static partial class Constants + public static partial class Categories { - public static partial class Categories - { - public static readonly Guid Headers = new Guid("0a893d02-9166-437d-90e8-264524f410c0"); - public static readonly Guid Content = new Guid("337cdd43-b90f-4aee-82f4-3c991b3cb8eb"); - } + public static readonly Guid Headers = new Guid("0a893d02-9166-437d-90e8-264524f410c0"); + public static readonly Guid Content = new Guid("337cdd43-b90f-4aee-82f4-3c991b3cb8eb"); } } diff --git a/src/Perplex.ContentBlocks.Core/Categories/ContentBlockCategory.cs b/src/Perplex.ContentBlocks.Core/Categories/ContentBlockCategory.cs index 6c9d587..7bd59e3 100644 --- a/src/Perplex.ContentBlocks.Core/Categories/ContentBlockCategory.cs +++ b/src/Perplex.ContentBlocks.Core/Categories/ContentBlockCategory.cs @@ -1,14 +1,11 @@ -using System; +namespace Perplex.ContentBlocks.Categories; -namespace Perplex.ContentBlocks.Categories +public class ContentBlockCategory : IContentBlockCategory { - public class ContentBlockCategory : IContentBlockCategory - { - public Guid Id { get; set; } - public string Name { get; set; } - public string Icon { get; set; } - public bool IsHidden { get; set; } - public bool IsEnabledForHeaders { get; set; } - public bool IsDisabledForBlocks { get; set; } - } + public Guid Id { get; set; } + public string Name { get; set; } = ""; + public string Icon { get; set; } = ""; + public bool IsHidden { get; set; } + public bool IsEnabledForHeaders { get; set; } + public bool IsDisabledForBlocks { get; set; } } diff --git a/src/Perplex.ContentBlocks.Core/Categories/ContentBlockCategoryComposer.cs b/src/Perplex.ContentBlocks.Core/Categories/ContentBlockCategoryComposer.cs index ce4e213..c42d495 100644 --- a/src/Perplex.ContentBlocks.Core/Categories/ContentBlockCategoryComposer.cs +++ b/src/Perplex.ContentBlocks.Core/Categories/ContentBlockCategoryComposer.cs @@ -1,30 +1,13 @@ -#if NET5_0 -using Umbraco.Cms.Core.Composing; +using Umbraco.Cms.Core.Composing; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Extensions; -#elif NET472 -using Umbraco.Core; -using Umbraco.Core.Composing; -#endif -namespace Perplex.ContentBlocks.Categories +namespace Perplex.ContentBlocks.Categories; + +public class ContentBlockCategoriesComposer : IComposer { -#if NET5_0 - public class ContentBlockCategoriesComposer : IComposer - { - public void Compose(IUmbracoBuilder builder) - { - builder.Services.AddUnique(); - } - } -#elif NET472 - [RuntimeLevel(MinLevel = RuntimeLevel.Run)] - public class ContentBlockCategoriesComposer : IUserComposer + public void Compose(IUmbracoBuilder builder) { - public void Compose(Composition composition) - { - composition.RegisterUnique(); - } + builder.Services.AddUnique(); } -#endif } diff --git a/src/Perplex.ContentBlocks.Core/Categories/IContentBlockCategory.cs b/src/Perplex.ContentBlocks.Core/Categories/IContentBlockCategory.cs index a4db9b1..e38dd17 100644 --- a/src/Perplex.ContentBlocks.Core/Categories/IContentBlockCategory.cs +++ b/src/Perplex.ContentBlocks.Core/Categories/IContentBlockCategory.cs @@ -1,26 +1,25 @@ using System; -namespace Perplex.ContentBlocks.Categories +namespace Perplex.ContentBlocks.Categories; + +public interface IContentBlockCategory { - public interface IContentBlockCategory - { - Guid Id { get; } - string Name { get; } - string Icon { get; } + Guid Id { get; } + string Name { get; } + string Icon { get; } - /// - /// Hidden categories do not show up in the UI - /// - bool IsHidden { get; } + /// + /// Hidden categories do not show up in the UI + /// + bool IsHidden { get; } - /// - /// Enables this category when selecting a header - /// - bool IsEnabledForHeaders { get; } + /// + /// Enables this category when selecting a header + /// + bool IsEnabledForHeaders { get; } - /// - /// Disables this category when selecting a block - /// - bool IsDisabledForBlocks { get; } - } + /// + /// Disables this category when selecting a block + /// + bool IsDisabledForBlocks { get; } } diff --git a/src/Perplex.ContentBlocks.Core/Categories/IContentBlockCategoryRepository.cs b/src/Perplex.ContentBlocks.Core/Categories/IContentBlockCategoryRepository.cs index 7d30bcd..dede791 100644 --- a/src/Perplex.ContentBlocks.Core/Categories/IContentBlockCategoryRepository.cs +++ b/src/Perplex.ContentBlocks.Core/Categories/IContentBlockCategoryRepository.cs @@ -1,16 +1,12 @@ -using System; -using System.Collections.Generic; +namespace Perplex.ContentBlocks.Categories; -namespace Perplex.ContentBlocks.Categories +public interface IContentBlockCategoryRepository { - public interface IContentBlockCategoryRepository - { - void Add(IContentBlockCategory category); + void Add(IContentBlockCategory category); - void Remove(Guid id); + void Remove(Guid id); - IContentBlockCategory GetById(Guid id); + IContentBlockCategory? GetById(Guid id); - IEnumerable GetAll(bool includeHidden); - } + IEnumerable GetAll(bool includeHidden); } diff --git a/src/Perplex.ContentBlocks.Core/Categories/InMemoryContentBlockCategoryRepository.cs b/src/Perplex.ContentBlocks.Core/Categories/InMemoryContentBlockCategoryRepository.cs index 55d84fc..2bf39cb 100644 --- a/src/Perplex.ContentBlocks.Core/Categories/InMemoryContentBlockCategoryRepository.cs +++ b/src/Perplex.ContentBlocks.Core/Categories/InMemoryContentBlockCategoryRepository.cs @@ -1,54 +1,50 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using static Perplex.ContentBlocks.Constants.PropertyEditor; +using static Perplex.ContentBlocks.Constants.PropertyEditor; using categories = Perplex.ContentBlocks.Constants.Categories; -namespace Perplex.ContentBlocks.Categories +namespace Perplex.ContentBlocks.Categories; + +public class InMemoryContentBlockCategoryRepository : IContentBlockCategoryRepository { - public class InMemoryContentBlockCategoryRepository : IContentBlockCategoryRepository + private readonly IDictionary _categories = new IContentBlockCategory[] { - private readonly IDictionary _categories = new IContentBlockCategory[] + new ContentBlockCategory + { + Id = categories.Headers, + Name = "Headers", + Icon = $"{AssetsFolder}/icons.svg#icon-cat-header", + IsEnabledForHeaders = true, + IsDisabledForBlocks = true, + }, + + new ContentBlockCategory { - new ContentBlockCategory - { - Id = categories.Headers, - Name = "Headers", - Icon = $"{AssetsFolder}/icons.svg#icon-cat-header", - IsEnabledForHeaders = true, - IsDisabledForBlocks = true, - }, + Id = categories.Content, + Name = "Content", + Icon = $"{AssetsFolder}/icons.svg#icon-cat-content", + }, + }.ToDictionary(d => d.Id); - new ContentBlockCategory - { - Id = categories.Content, - Name = "Content", - Icon = $"{AssetsFolder}/icons.svg#icon-cat-content", - }, - }.ToDictionary(d => d.Id); + public IContentBlockCategory? GetById(Guid id) + { + return _categories.TryGetValue(id, out var definition) ? definition : null; + } - public IContentBlockCategory GetById(Guid id) + public IEnumerable GetAll(bool includeHidden) + { + var categories = _categories.Values; + if (includeHidden) { - return _categories.TryGetValue(id, out var definition) ? definition : null; + return categories; } - - public IEnumerable GetAll(bool includeHidden) + else { - var categories = _categories.Values; - if (includeHidden) - { - return categories; - } - else - { - return categories.Where(category => !category.IsHidden); - } + return categories.Where(category => !category.IsHidden); } + } - public void Add(IContentBlockCategory category) - => _categories[category.Id] = category; + public void Add(IContentBlockCategory category) + => _categories[category.Id] = category; - public void Remove(Guid id) - => _categories.Remove(id); - } + public void Remove(Guid id) + => _categories.Remove(id); } diff --git a/src/Perplex.ContentBlocks.Core/Definitions/ContentBlockDefinition.cs b/src/Perplex.ContentBlocks.Core/Definitions/ContentBlockDefinition.cs index fe4543d..8da3386 100644 --- a/src/Perplex.ContentBlocks.Core/Definitions/ContentBlockDefinition.cs +++ b/src/Perplex.ContentBlocks.Core/Definitions/ContentBlockDefinition.cs @@ -1,24 +1,23 @@ -using System; -using System.Collections.Generic; -using System.Linq; +namespace Perplex.ContentBlocks.Definitions; -namespace Perplex.ContentBlocks.Definitions +public class ContentBlockDefinition : IContentBlockDefinition { - public class ContentBlockDefinition : IContentBlockDefinition - { - public Guid Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public string PreviewImage { get; set; } - public int? DataTypeId { get; set; } - public Guid? DataTypeKey { get; set; } - public IEnumerable CategoryIds { get; set; } - public IEnumerable Layouts { get; set; } + public Guid Id { get; set; } + public string Name { get; set; } = ""; + public string Description { get; set; } = ""; + public string PreviewImage { get; set; } = ""; + public int? DataTypeId { get; set; } + public Guid? DataTypeKey { get; set; } - public virtual IEnumerable LimitToDocumentTypes { get; set; } - = Enumerable.Empty(); + public IEnumerable CategoryIds { get; set; } + = Array.Empty(); - public virtual IEnumerable LimitToCultures { get; set; } - = Enumerable.Empty(); - } + public IEnumerable Layouts { get; set; } + = Array.Empty(); + + public virtual IEnumerable LimitToDocumentTypes { get; set; } + = Array.Empty(); + + public virtual IEnumerable LimitToCultures { get; set; } + = Array.Empty(); } diff --git a/src/Perplex.ContentBlocks.Core/Definitions/ContentBlockDefinitionComposer.cs b/src/Perplex.ContentBlocks.Core/Definitions/ContentBlockDefinitionComposer.cs index 9f793e1..c6da287 100644 --- a/src/Perplex.ContentBlocks.Core/Definitions/ContentBlockDefinitionComposer.cs +++ b/src/Perplex.ContentBlocks.Core/Definitions/ContentBlockDefinitionComposer.cs @@ -1,33 +1,15 @@ -#if NET5_0 -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.Composing; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Extensions; -#elif NET472 -using Umbraco.Core; -using Umbraco.Core.Composing; -#endif -namespace Perplex.ContentBlocks.Definitions +namespace Perplex.ContentBlocks.Definitions; + +public class ContentBlockDefinitionComposer : IComposer { -#if NET5_0 - public class ContentBlockDefinitionComposer : IComposer - { - public void Compose(IUmbracoBuilder builder) - { - builder.Services.AddUnique(); - builder.Services.AddSingleton(); - } - } -#elif NET472 - [RuntimeLevel(MinLevel = RuntimeLevel.Run)] - public class ContentBlockDefinitionComposer : IUserComposer + public void Compose(IUmbracoBuilder builder) { - public void Compose(Composition composition) - { - composition.RegisterUnique(); - composition.Register(Lifetime.Singleton); - } + builder.Services.AddUnique(); + builder.Services.AddSingleton(); } -#endif } diff --git a/src/Perplex.ContentBlocks.Core/Definitions/ContentBlockDefinitionFilterer.cs b/src/Perplex.ContentBlocks.Core/Definitions/ContentBlockDefinitionFilterer.cs index 2c81ff4..7484df5 100644 --- a/src/Perplex.ContentBlocks.Core/Definitions/ContentBlockDefinitionFilterer.cs +++ b/src/Perplex.ContentBlocks.Core/Definitions/ContentBlockDefinitionFilterer.cs @@ -1,55 +1,51 @@ using Perplex.ContentBlocks.Providers; -using System; -using System.Collections.Generic; -using System.Linq; -namespace Perplex.ContentBlocks.Definitions +namespace Perplex.ContentBlocks.Definitions; + +public class ContentBlockDefinitionFilterer : IContentBlockDefinitionFilterer { - public class ContentBlockDefinitionFilterer : IContentBlockDefinitionFilterer - { - private readonly IDocumentTypeAliasProvider _documentTypeAliasProvider; + private readonly IDocumentTypeAliasProvider _documentTypeAliasProvider; - public ContentBlockDefinitionFilterer(IDocumentTypeAliasProvider documentTypeAliasProvider) - { - _documentTypeAliasProvider = documentTypeAliasProvider; - } + public ContentBlockDefinitionFilterer(IDocumentTypeAliasProvider documentTypeAliasProvider) + { + _documentTypeAliasProvider = documentTypeAliasProvider; + } - public IEnumerable FilterForCulture(IEnumerable definitions, string culture) - => definitions.Where(definition => - definition.LimitToCultures?.Any() != true || - definition.LimitToCultures.Any(definitionCulture => string.Equals(definitionCulture, culture, StringComparison.InvariantCultureIgnoreCase))); + public IEnumerable FilterForCulture(IEnumerable definitions, string culture) + => definitions.Where(definition => + definition.LimitToCultures?.Any() != true || + definition.LimitToCultures.Any(definitionCulture => string.Equals(definitionCulture, culture, StringComparison.InvariantCultureIgnoreCase))); - public IEnumerable FilterForDocumentType(IEnumerable definitions, string documentType) - => definitions.Where(definition => - definition.LimitToDocumentTypes?.Any() != true || - definition.LimitToDocumentTypes.Any(definitionDocumentType => string.Equals(definitionDocumentType, documentType, StringComparison.InvariantCultureIgnoreCase))); + public IEnumerable FilterForDocumentType(IEnumerable definitions, string documentType) + => definitions.Where(definition => + definition.LimitToDocumentTypes?.Any() != true || + definition.LimitToDocumentTypes.Any(definitionDocumentType => string.Equals(definitionDocumentType, documentType, StringComparison.InvariantCultureIgnoreCase))); - public IEnumerable FilterForCultureAndDocumentType(IEnumerable definitions, string culture, string documentType) - => FilterForCulture(FilterForDocumentType(definitions, documentType), culture); + public IEnumerable FilterForCultureAndDocumentType(IEnumerable definitions, string culture, string documentType) + => FilterForCulture(FilterForDocumentType(definitions, documentType), culture); - public IEnumerable FilterForPage(IEnumerable definitions, int pageId, string culture) + public IEnumerable FilterForPage(IEnumerable definitions, int pageId, string culture) + { + if (string.IsNullOrEmpty(culture)) { - if (string.IsNullOrEmpty(culture)) - { - // A document type can be culture invariant, in that case nothing is filtered. - return definitions; - } - - string documentType = _documentTypeAliasProvider.GetDocumentTypeAlias(pageId); - return FilterForPage(definitions, documentType, culture); + // A document type can be culture invariant, in that case nothing is filtered. + return definitions; } - public IEnumerable FilterForPage(IEnumerable definitions, string documentType, string culture) + var documentType = _documentTypeAliasProvider.GetDocumentTypeAlias(pageId); + return FilterForPage(definitions, documentType, culture); + } + + public IEnumerable FilterForPage(IEnumerable definitions, string? documentType, string culture) + { + if (string.IsNullOrEmpty(documentType)) { - if (string.IsNullOrEmpty(documentType)) - { - return definitions; - } - - return FilterForCultureAndDocumentType( - definitions, - culture, - documentType); + return definitions; } + + return FilterForCultureAndDocumentType( + definitions, + culture, + documentType); } } diff --git a/src/Perplex.ContentBlocks.Core/Definitions/ContentBlockLayout.cs b/src/Perplex.ContentBlocks.Core/Definitions/ContentBlockLayout.cs index 3020fc7..2029167 100644 --- a/src/Perplex.ContentBlocks.Core/Definitions/ContentBlockLayout.cs +++ b/src/Perplex.ContentBlocks.Core/Definitions/ContentBlockLayout.cs @@ -1,13 +1,10 @@ -using System; +namespace Perplex.ContentBlocks.Definitions; -namespace Perplex.ContentBlocks.Definitions +public class ContentBlockLayout : IContentBlockLayout { - public class ContentBlockLayout : IContentBlockLayout - { - public Guid Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public string PreviewImage { get; set; } - public string ViewPath { get; set; } - } + public Guid Id { get; set; } + public string Name { get; set; } = ""; + public string Description { get; set; } = ""; + public string PreviewImage { get; set; } = ""; + public string ViewPath { get; set; } = ""; } diff --git a/src/Perplex.ContentBlocks.Core/Definitions/ContentBlocksDefinitionApiController.cs b/src/Perplex.ContentBlocks.Core/Definitions/ContentBlocksDefinitionApiController.cs index 67dca58..75b7596 100644 --- a/src/Perplex.ContentBlocks.Core/Definitions/ContentBlocksDefinitionApiController.cs +++ b/src/Perplex.ContentBlocks.Core/Definitions/ContentBlocksDefinitionApiController.cs @@ -2,78 +2,58 @@ using System.Collections.Generic; -#if NET5_0 using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using System.Net.Mime; using Umbraco.Cms.Web.BackOffice.Controllers; -#elif NET472 -using System.Web.Http; -using Umbraco.Web.WebApi; -#endif -namespace Perplex.ContentBlocks.Definitions -{ - public class ContentBlocksDefinitionApiController : UmbracoAuthorizedApiController - { - private readonly IContentBlockDefinitionRepository _definitionRepository; - private readonly IContentBlockCategoryRepository _categoryRepository; +namespace Perplex.ContentBlocks.Definitions; - public ContentBlocksDefinitionApiController(IContentBlockDefinitionRepository definitionRepository, IContentBlockCategoryRepository categoryRepository) - { - _definitionRepository = definitionRepository; - _categoryRepository = categoryRepository; - } - -#if NET5_0 - [HttpGet] - public IActionResult GetAllDefinitions() - { - var definitions = _definitionRepository.GetAll(); - return JsonContent(definitions); - } +public class ContentBlocksDefinitionApiController : UmbracoAuthorizedApiController +{ + private readonly IContentBlockDefinitionRepository _definitionRepository; + private readonly IContentBlockCategoryRepository _categoryRepository; - [HttpGet] - public IActionResult GetAllCategories() - { - var categories = _categoryRepository.GetAll(true); - return JsonContent(categories); - } + public ContentBlocksDefinitionApiController(IContentBlockDefinitionRepository definitionRepository, IContentBlockCategoryRepository categoryRepository) + { + _definitionRepository = definitionRepository; + _categoryRepository = categoryRepository; + } - [HttpGet] - public IActionResult GetDefinitionsForPage(string documentType, string culture) - { - var definitions = _definitionRepository.GetAllForPage(documentType, culture); - return JsonContent(definitions); - } + [HttpGet] + public IActionResult GetAllDefinitions() + { + var definitions = _definitionRepository.GetAll(); + return JsonContent(definitions); + } - /// - /// Returns obj serialized to JSON using Newtonsoft.Json. - /// The Json serializer + deserializer in .NET Core has been switched - /// to the System.Text.Json namespace which handles casing differently. - /// It will transform properties to camelCase by default instead of using the original casing. - /// We used PascalCasing in v8 and want to continue to do so to prevent having to rewrite the front-end code, - /// so we explicitly use Newtonsoft here to create the JSON response by hand. - /// - /// Object to serialize to JSON - /// - private IActionResult JsonContent(object obj) - { - var serialized = JsonConvert.SerializeObject(obj); - return Content(serialized, MediaTypeNames.Application.Json); - } -#elif NET472 - [HttpGet] - public IEnumerable GetAllDefinitions() - => _definitionRepository.GetAll(); + [HttpGet] + public IActionResult GetAllCategories() + { + var categories = _categoryRepository.GetAll(true); + return JsonContent(categories); + } - [HttpGet] - public IEnumerable GetAllCategories() - => _categoryRepository.GetAll(true); + [HttpGet] + public IActionResult GetDefinitionsForPage(string documentType, string culture) + { + var definitions = _definitionRepository.GetAllForPage(documentType, culture); + return JsonContent(definitions); + } - [HttpGet] - public IEnumerable GetDefinitionsForPage(string documentType, string culture) - => _definitionRepository.GetAllForPage(documentType, culture); -#endif + /// + /// Returns obj serialized to JSON using Newtonsoft.Json. + /// The Json serializer + deserializer in .NET Core has been switched + /// to the System.Text.Json namespace which handles casing differently. + /// It will transform properties to camelCase by default instead of using the original casing. + /// We used PascalCasing in v8 and want to continue to do so to prevent having to rewrite the front-end code, + /// so we explicitly use Newtonsoft here to create the JSON response by hand. + /// + /// Object to serialize to JSON + /// + private IActionResult JsonContent(object obj) + { + var serialized = JsonConvert.SerializeObject(obj); + return Content(serialized, MediaTypeNames.Application.Json); } } diff --git a/src/Perplex.ContentBlocks.Core/Definitions/IContentBlockDefinition.cs b/src/Perplex.ContentBlocks.Core/Definitions/IContentBlockDefinition.cs index dcce984..857998d 100644 --- a/src/Perplex.ContentBlocks.Core/Definitions/IContentBlockDefinition.cs +++ b/src/Perplex.ContentBlocks.Core/Definitions/IContentBlockDefinition.cs @@ -1,30 +1,29 @@ using System; using System.Collections.Generic; -namespace Perplex.ContentBlocks.Definitions +namespace Perplex.ContentBlocks.Definitions; + +public interface IContentBlockDefinition { - public interface IContentBlockDefinition - { - Guid Id { get; } - string Name { get; } - string Description { get; } - string PreviewImage { get; } + Guid Id { get; } + string Name { get; } + string Description { get; } + string PreviewImage { get; } - /// - /// Data type id of the Nested Content data type used for this Content Block definition. - /// Provide either DataTypeId OR DataTypeKey, not both. Leave one of them NULL. - /// - int? DataTypeId { get; } + /// + /// Data type id of the Nested Content data type used for this Content Block definition. + /// Provide either DataTypeId OR DataTypeKey, not both. Leave one of them NULL. + /// + int? DataTypeId { get; } - /// - /// Data type key of the Nested Content data type used for this Content Block definition. - /// Provide either DataTypeId OR DataTypeKey, not both. Leave one of them NULL. - /// - Guid? DataTypeKey { get; } + /// + /// Data type key of the Nested Content data type used for this Content Block definition. + /// Provide either DataTypeId OR DataTypeKey, not both. Leave one of them NULL. + /// + Guid? DataTypeKey { get; } - IEnumerable CategoryIds { get; } - IEnumerable Layouts { get; } - IEnumerable LimitToDocumentTypes { get; } - IEnumerable LimitToCultures { get; } - } + IEnumerable CategoryIds { get; } + IEnumerable Layouts { get; } + IEnumerable LimitToDocumentTypes { get; } + IEnumerable LimitToCultures { get; } } diff --git a/src/Perplex.ContentBlocks.Core/Definitions/IContentBlockDefinitionFilterer.cs b/src/Perplex.ContentBlocks.Core/Definitions/IContentBlockDefinitionFilterer.cs index 8725bbb..ef1f961 100644 --- a/src/Perplex.ContentBlocks.Core/Definitions/IContentBlockDefinitionFilterer.cs +++ b/src/Perplex.ContentBlocks.Core/Definitions/IContentBlockDefinitionFilterer.cs @@ -1,18 +1,17 @@ using System.Collections.Generic; -namespace Perplex.ContentBlocks.Definitions +namespace Perplex.ContentBlocks.Definitions; + +public interface IContentBlockDefinitionFilterer { - public interface IContentBlockDefinitionFilterer - { - IEnumerable FilterForCulture(IEnumerable definitions, string culture); + IEnumerable FilterForCulture(IEnumerable definitions, string culture); - IEnumerable FilterForDocumentType(IEnumerable definitions, string documentType); + IEnumerable FilterForDocumentType(IEnumerable definitions, string documentType); - IEnumerable FilterForCultureAndDocumentType(IEnumerable definitions, - string culture, string documentType); + IEnumerable FilterForCultureAndDocumentType(IEnumerable definitions, + string culture, string documentType); - IEnumerable FilterForPage(IEnumerable definitions, int pageId, string culture); + IEnumerable FilterForPage(IEnumerable definitions, int pageId, string culture); - IEnumerable FilterForPage(IEnumerable definitions, string documentType, string culture); - } + IEnumerable FilterForPage(IEnumerable definitions, string documentType, string culture); } diff --git a/src/Perplex.ContentBlocks.Core/Definitions/IContentBlockDefinitionRepository.cs b/src/Perplex.ContentBlocks.Core/Definitions/IContentBlockDefinitionRepository.cs index b4be550..2cc6fc5 100644 --- a/src/Perplex.ContentBlocks.Core/Definitions/IContentBlockDefinitionRepository.cs +++ b/src/Perplex.ContentBlocks.Core/Definitions/IContentBlockDefinitionRepository.cs @@ -1,20 +1,16 @@ -using System; -using System.Collections.Generic; +namespace Perplex.ContentBlocks.Definitions; -namespace Perplex.ContentBlocks.Definitions +public interface IContentBlockDefinitionRepository { - public interface IContentBlockDefinitionRepository - { - void Add(IContentBlockDefinition definition); + void Add(IContentBlockDefinition definition); - void Remove(Guid id); + void Remove(Guid id); - IContentBlockDefinition GetById(Guid id); + IContentBlockDefinition? GetById(Guid id); - IEnumerable GetAll(); + IEnumerable GetAll(); - IEnumerable GetAllForPage(int pageId, string culture); + IEnumerable GetAllForPage(int pageId, string culture); - IEnumerable GetAllForPage(string documentType, string culture); - } + IEnumerable GetAllForPage(string documentType, string culture); } diff --git a/src/Perplex.ContentBlocks.Core/Definitions/IContentBlockLayout.cs b/src/Perplex.ContentBlocks.Core/Definitions/IContentBlockLayout.cs index a3548c3..0eae0a1 100644 --- a/src/Perplex.ContentBlocks.Core/Definitions/IContentBlockLayout.cs +++ b/src/Perplex.ContentBlocks.Core/Definitions/IContentBlockLayout.cs @@ -1,18 +1,17 @@ using System; -namespace Perplex.ContentBlocks.Definitions +namespace Perplex.ContentBlocks.Definitions; + +public interface IContentBlockLayout { - public interface IContentBlockLayout - { - Guid Id { get; } - string Name { get; } - string Description { get; } - string PreviewImage { get; } + Guid Id { get; } + string Name { get; } + string Description { get; } + string PreviewImage { get; } - /// - /// Full path to the View file of this ContentBlockLayout, - /// e.g. "~/Views/Partials/ContentBlocks/ExampleBlock.cshtml" - /// - string ViewPath { get; } - } + /// + /// Full path to the View file of this ContentBlockLayout, + /// e.g. "~/Views/Partials/ContentBlocks/ExampleBlock.cshtml" + /// + string ViewPath { get; } } diff --git a/src/Perplex.ContentBlocks.Core/Definitions/InMemoryContentBlockDefinitionRepository.cs b/src/Perplex.ContentBlocks.Core/Definitions/InMemoryContentBlockDefinitionRepository.cs index 2af10de..4597596 100644 --- a/src/Perplex.ContentBlocks.Core/Definitions/InMemoryContentBlockDefinitionRepository.cs +++ b/src/Perplex.ContentBlocks.Core/Definitions/InMemoryContentBlockDefinitionRepository.cs @@ -1,40 +1,34 @@ -using System; -using System.Collections.Generic; +namespace Perplex.ContentBlocks.Definitions; -namespace Perplex.ContentBlocks.Definitions +public class InMemoryContentBlockDefinitionRepository : IContentBlockDefinitionRepository { - public class InMemoryContentBlockDefinitionRepository : IContentBlockDefinitionRepository + public InMemoryContentBlockDefinitionRepository(IContentBlockDefinitionFilterer definitionFilterer) { - public InMemoryContentBlockDefinitionRepository(IContentBlockDefinitionFilterer definitionFilterer) - { - _definitionFilterer = definitionFilterer; - _definitions = new Dictionary(); - } + _definitionFilterer = definitionFilterer; + _definitions = new Dictionary(); + } - private readonly IDictionary _definitions; + private readonly IDictionary _definitions; - private readonly IContentBlockDefinitionFilterer _definitionFilterer; + private readonly IContentBlockDefinitionFilterer _definitionFilterer; - public IContentBlockDefinition GetById(Guid id) - { - return _definitions.TryGetValue(id, out var definition) ? definition : null; - } + public IContentBlockDefinition? GetById(Guid id) + => _definitions.TryGetValue(id, out var definition) ? definition : null; - public IEnumerable GetAll() - { - return _definitions.Values; - } + public IEnumerable GetAll() + { + return _definitions.Values; + } - public IEnumerable GetAllForPage(int pageId, string culture) - => _definitionFilterer.FilterForPage(GetAll(), pageId, culture); + public IEnumerable GetAllForPage(int pageId, string culture) + => _definitionFilterer.FilterForPage(GetAll(), pageId, culture); - public IEnumerable GetAllForPage(string documentType, string culture) - => _definitionFilterer.FilterForPage(GetAll(), documentType, culture); + public IEnumerable GetAllForPage(string documentType, string culture) + => _definitionFilterer.FilterForPage(GetAll(), documentType, culture); - public void Add(IContentBlockDefinition definition) - => _definitions[definition.Id] = definition; + public void Add(IContentBlockDefinition definition) + => _definitions[definition.Id] = definition; - public void Remove(Guid id) - => _definitions.Remove(id); - } + public void Remove(Guid id) + => _definitions.Remove(id); } diff --git a/src/Perplex.ContentBlocks.Core/Perplex.ContentBlocks.Core.csproj b/src/Perplex.ContentBlocks.Core/Perplex.ContentBlocks.Core.csproj index ff5df34..c161b3d 100644 --- a/src/Perplex.ContentBlocks.Core/Perplex.ContentBlocks.Core.csproj +++ b/src/Perplex.ContentBlocks.Core/Perplex.ContentBlocks.Core.csproj @@ -1,12 +1,6 @@ - + - net6.0 - enable - enable - Nullable - / - embedded True False diff --git a/src/Perplex.ContentBlocks.Core/Presets/ContentBlockPreset.cs b/src/Perplex.ContentBlocks.Core/Presets/ContentBlockPreset.cs index 3f6bcff..eb4a973 100644 --- a/src/Perplex.ContentBlocks.Core/Presets/ContentBlockPreset.cs +++ b/src/Perplex.ContentBlocks.Core/Presets/ContentBlockPreset.cs @@ -2,18 +2,17 @@ using System.Collections.Generic; using System.Linq; -namespace Perplex.ContentBlocks.Presets +namespace Perplex.ContentBlocks.Presets; + +public class ContentBlockPreset : IContentBlockPreset { - public class ContentBlockPreset : IContentBlockPreset - { - public Guid Id { get; set; } - public Guid DefinitionId { get; set; } - public Guid LayoutId { get; set; } - public bool IsMandatory { get; set; } - public IDictionary Values { get; set; } - = new Dictionary(); + public Guid Id { get; set; } + public Guid DefinitionId { get; set; } + public Guid LayoutId { get; set; } + public bool IsMandatory { get; set; } + public IDictionary Values { get; set; } + = new Dictionary(); - public IEnumerable Variants { get; set; } - = Enumerable.Empty(); - } + public IEnumerable Variants { get; set; } + = Enumerable.Empty(); } diff --git a/src/Perplex.ContentBlocks.Core/Presets/ContentBlockPresetsComposer.cs b/src/Perplex.ContentBlocks.Core/Presets/ContentBlockPresetsComposer.cs index 02604f7..388ff90 100644 --- a/src/Perplex.ContentBlocks.Core/Presets/ContentBlockPresetsComposer.cs +++ b/src/Perplex.ContentBlocks.Core/Presets/ContentBlockPresetsComposer.cs @@ -1,30 +1,13 @@ -#if NET5_0 -using Umbraco.Cms.Core.Composing; +using Umbraco.Cms.Core.Composing; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Extensions; -#elif NET472 -using Umbraco.Core; -using Umbraco.Core.Composing; -#endif -namespace Perplex.ContentBlocks.Presets +namespace Perplex.ContentBlocks.Presets; + +public class ContentBlockPresetsComposer : IComposer { -#if NET5_0 - public class ContentBlockPresetsComposer : IComposer - { - public void Compose(IUmbracoBuilder builder) - { - builder.Services.AddUnique(); - } - } -#elif NET472 - [RuntimeLevel(MinLevel = RuntimeLevel.Run)] - public class ContentBlockPresetsComposer : IUserComposer + public void Compose(IUmbracoBuilder builder) { - public void Compose(Composition composition) - { - composition.RegisterUnique(); - } + builder.Services.AddUnique(); } -#endif } diff --git a/src/Perplex.ContentBlocks.Core/Presets/ContentBlockVariantPreset.cs b/src/Perplex.ContentBlocks.Core/Presets/ContentBlockVariantPreset.cs index d253f00..1b9c8fe 100644 --- a/src/Perplex.ContentBlocks.Core/Presets/ContentBlockVariantPreset.cs +++ b/src/Perplex.ContentBlocks.Core/Presets/ContentBlockVariantPreset.cs @@ -1,18 +1,14 @@ -using System; -using System.Collections.Generic; +namespace Perplex.ContentBlocks.Presets; -namespace Perplex.ContentBlocks.Presets +public class ContentBlockVariantPreset : IContentBlockVariantPreset { - public class ContentBlockVariantPreset : IContentBlockVariantPreset - { - public Guid Id { get; set; } + public Guid Id { get; set; } - public string Alias { get; set; } + public string Alias { get; set; } = ""; - /// - /// The initial values of the generated Content Block variant per property alias of the IPublishedElement - /// - public IDictionary Values { get; set; } - = new Dictionary(); - } + /// + /// The initial values of the generated Content Block variant per property alias of the IPublishedElement + /// + public IDictionary Values { get; set; } + = new Dictionary(); } diff --git a/src/Perplex.ContentBlocks.Core/Presets/ContentBlocksPreset.cs b/src/Perplex.ContentBlocks.Core/Presets/ContentBlocksPreset.cs index 1046933..2800c7a 100644 --- a/src/Perplex.ContentBlocks.Core/Presets/ContentBlocksPreset.cs +++ b/src/Perplex.ContentBlocks.Core/Presets/ContentBlocksPreset.cs @@ -1,23 +1,18 @@ -using System; -using System.Collections.Generic; -using System.Linq; +namespace Perplex.ContentBlocks.Presets; -namespace Perplex.ContentBlocks.Presets +public class ContentBlocksPreset : IContentBlocksPreset { - public class ContentBlocksPreset : IContentBlocksPreset - { - public Guid Id { get; set; } - public string Name { get; set; } + public Guid Id { get; set; } + public string Name { get; set; } = ""; - public IEnumerable ApplyToCultures { get; set; } - = Enumerable.Empty(); + public IEnumerable ApplyToCultures { get; set; } + = Enumerable.Empty(); - public IEnumerable ApplyToDocumentTypes { get; set; } - = Enumerable.Empty(); + public IEnumerable ApplyToDocumentTypes { get; set; } + = Enumerable.Empty(); - public IContentBlockPreset Header { get; set; } + public IContentBlockPreset? Header { get; set; } - public IEnumerable Blocks { get; set; } - = Enumerable.Empty(); - } + public IEnumerable Blocks { get; set; } + = Enumerable.Empty(); } diff --git a/src/Perplex.ContentBlocks.Core/Presets/ContentBlocksPresetApiController.cs b/src/Perplex.ContentBlocks.Core/Presets/ContentBlocksPresetApiController.cs index a53d01c..86007c6 100644 --- a/src/Perplex.ContentBlocks.Core/Presets/ContentBlocksPresetApiController.cs +++ b/src/Perplex.ContentBlocks.Core/Presets/ContentBlocksPresetApiController.cs @@ -1,30 +1,23 @@ -using Perplex.ContentBlocks.Presets; -using System.Collections.Generic; -#if NET5_0 -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc; +using Perplex.ContentBlocks.Presets; using Umbraco.Cms.Web.BackOffice.Controllers; -#elif NET472 -using System.Web.Http; -using Umbraco.Web.WebApi; -#endif -namespace Perplex.ContentBlocks.Definitions +namespace Perplex.ContentBlocks.Definitions; + +public class ContentBlocksPresetApiController : UmbracoAuthorizedApiController { - public class ContentBlocksPresetApiController : UmbracoAuthorizedApiController - { - private readonly IContentBlocksPresetRepository _presetRepository; + private readonly IContentBlocksPresetRepository _presetRepository; - public ContentBlocksPresetApiController(IContentBlocksPresetRepository presetRepository) - { - _presetRepository = presetRepository; - } + public ContentBlocksPresetApiController(IContentBlocksPresetRepository presetRepository) + { + _presetRepository = presetRepository; + } - [HttpGet] - public IEnumerable GetAllPresets() - => _presetRepository.GetAll(); + [HttpGet] + public IEnumerable GetAllPresets() + => _presetRepository.GetAll(); - [HttpGet] - public IContentBlocksPreset GetPresetForPage(string documentType, string culture) - => _presetRepository.GetPresetForPage(documentType, culture); - } + [HttpGet] + public IContentBlocksPreset? GetPresetForPage(string documentType, string culture) + => _presetRepository.GetPresetForPage(documentType, culture); } diff --git a/src/Perplex.ContentBlocks.Core/Presets/IContentBlockPreset.cs b/src/Perplex.ContentBlocks.Core/Presets/IContentBlockPreset.cs index 7bcd7bd..68b9dfa 100644 --- a/src/Perplex.ContentBlocks.Core/Presets/IContentBlockPreset.cs +++ b/src/Perplex.ContentBlocks.Core/Presets/IContentBlockPreset.cs @@ -1,38 +1,37 @@ using System; using System.Collections.Generic; -namespace Perplex.ContentBlocks.Presets +namespace Perplex.ContentBlocks.Presets; + +public interface IContentBlockPreset { - public interface IContentBlockPreset - { - /// - /// Unique id of this preset. - /// - Guid Id { get; } + /// + /// Unique id of this preset. + /// + Guid Id { get; } - /// - /// Definition to use for this preset. - /// - Guid DefinitionId { get; } + /// + /// Definition to use for this preset. + /// + Guid DefinitionId { get; } - /// - /// Layout to use for this preset. - /// - Guid LayoutId { get; } + /// + /// Layout to use for this preset. + /// + Guid LayoutId { get; } - /// - /// When set to true, the block specified by this preset cannot be hidden or removed. - /// - bool IsMandatory { get; } + /// + /// When set to true, the block specified by this preset cannot be hidden or removed. + /// + bool IsMandatory { get; } - /// - /// The initial values of the generated Content Block per property alias of the IPublishedElement. - /// - IDictionary Values { get; } + /// + /// The initial values of the generated Content Block per property alias of the IPublishedElement. + /// + IDictionary Values { get; } - /// - /// The variants of this preset. - /// - IEnumerable Variants { get; set; } - } + /// + /// The variants of this preset. + /// + IEnumerable Variants { get; set; } } diff --git a/src/Perplex.ContentBlocks.Core/Presets/IContentBlockVariantPreset.cs b/src/Perplex.ContentBlocks.Core/Presets/IContentBlockVariantPreset.cs index 2087956..37be0a6 100644 --- a/src/Perplex.ContentBlocks.Core/Presets/IContentBlockVariantPreset.cs +++ b/src/Perplex.ContentBlocks.Core/Presets/IContentBlockVariantPreset.cs @@ -1,23 +1,22 @@ using System; using System.Collections.Generic; -namespace Perplex.ContentBlocks.Presets +namespace Perplex.ContentBlocks.Presets; + +public interface IContentBlockVariantPreset { - public interface IContentBlockVariantPreset - { - /// - /// Unique id of this variant preset - /// - Guid Id { get; } + /// + /// Unique id of this variant preset + /// + Guid Id { get; } - /// - /// The variant alias - /// - string Alias { get; } + /// + /// The variant alias + /// + string Alias { get; } - /// - /// The initial values of the generated Content Block variant per property alias of the IPublishedElement - /// - IDictionary Values { get; } - } + /// + /// The initial values of the generated Content Block variant per property alias of the IPublishedElement + /// + IDictionary Values { get; } } diff --git a/src/Perplex.ContentBlocks.Core/Presets/IContentBlocksPreset.cs b/src/Perplex.ContentBlocks.Core/Presets/IContentBlocksPreset.cs index 25ba806..b8cd639 100644 --- a/src/Perplex.ContentBlocks.Core/Presets/IContentBlocksPreset.cs +++ b/src/Perplex.ContentBlocks.Core/Presets/IContentBlocksPreset.cs @@ -1,17 +1,13 @@ -using System; -using System.Collections.Generic; +namespace Perplex.ContentBlocks.Presets; -namespace Perplex.ContentBlocks.Presets +public interface IContentBlocksPreset { - public interface IContentBlocksPreset - { - Guid Id { get; } - string Name { get; } + Guid Id { get; } + string Name { get; } - IEnumerable ApplyToCultures { get; } - IEnumerable ApplyToDocumentTypes { get; } + IEnumerable ApplyToCultures { get; } + IEnumerable ApplyToDocumentTypes { get; } - IContentBlockPreset Header { get; } - IEnumerable Blocks { get; } - } + IContentBlockPreset? Header { get; } + IEnumerable Blocks { get; } } diff --git a/src/Perplex.ContentBlocks.Core/Presets/IContentBlocksPresetRepository.cs b/src/Perplex.ContentBlocks.Core/Presets/IContentBlocksPresetRepository.cs index 1bbac51..70ddd58 100644 --- a/src/Perplex.ContentBlocks.Core/Presets/IContentBlocksPresetRepository.cs +++ b/src/Perplex.ContentBlocks.Core/Presets/IContentBlocksPresetRepository.cs @@ -1,18 +1,14 @@ -using System; -using System.Collections.Generic; +namespace Perplex.ContentBlocks.Presets; -namespace Perplex.ContentBlocks.Presets +public interface IContentBlocksPresetRepository { - public interface IContentBlocksPresetRepository - { - void Add(IContentBlocksPreset preset); + void Add(IContentBlocksPreset preset); - void Remove(Guid id); + void Remove(Guid id); - IEnumerable GetAll(); + IEnumerable GetAll(); - IContentBlocksPreset GetPresetForPage(int pageId, string culture); + IContentBlocksPreset? GetPresetForPage(int pageId, string culture); - IContentBlocksPreset GetPresetForPage(string documentType, string culture); - } + IContentBlocksPreset? GetPresetForPage(string documentType, string culture); } diff --git a/src/Perplex.ContentBlocks.Core/Presets/InMemoryContentBlocksPresetRepository.cs b/src/Perplex.ContentBlocks.Core/Presets/InMemoryContentBlocksPresetRepository.cs index 2da0b15..f9322c7 100644 --- a/src/Perplex.ContentBlocks.Core/Presets/InMemoryContentBlocksPresetRepository.cs +++ b/src/Perplex.ContentBlocks.Core/Presets/InMemoryContentBlocksPresetRepository.cs @@ -1,61 +1,59 @@ using Perplex.ContentBlocks.Providers; -using System; -using System.Collections.Generic; -using System.Linq; -namespace Perplex.ContentBlocks.Presets +namespace Perplex.ContentBlocks.Presets; + +public class InMemoryContentBlocksPresetRepository : IContentBlocksPresetRepository { - public class InMemoryContentBlocksPresetRepository : IContentBlocksPresetRepository + private readonly IDocumentTypeAliasProvider _documentTypeAliasProvider; + + public InMemoryContentBlocksPresetRepository(IDocumentTypeAliasProvider documentTypeAliasProvider) { - private readonly IDocumentTypeAliasProvider _documentTypeAliasProvider; + _documentTypeAliasProvider = documentTypeAliasProvider; + } - public InMemoryContentBlocksPresetRepository(IDocumentTypeAliasProvider documentTypeAliasProvider) - { - _documentTypeAliasProvider = documentTypeAliasProvider; - } + private readonly IDictionary _presets = new Dictionary(); - private readonly IDictionary _presets = new Dictionary(); + public void Add(IContentBlocksPreset preset) + => _presets[preset.Id] = preset; - public void Add(IContentBlocksPreset preset) - => _presets[preset.Id] = preset; + public void Remove(Guid id) + => _presets.Remove(id); - public void Remove(Guid id) - => _presets.Remove(id); + public IContentBlocksPreset? GetById(Guid id) + { + return _presets.TryGetValue(id, out var preset) ? preset : null; + } - public IContentBlocksPreset GetById(Guid id) - { - return _presets.TryGetValue(id, out var preset) ? preset : null; - } + public IEnumerable GetAll() + { + return _presets.Values; + } - public IEnumerable GetAll() + public IContentBlocksPreset? GetPresetForPage(int pageId, string culture) + { + if (string.IsNullOrEmpty(culture)) { - return _presets.Values; + return null; } - public IContentBlocksPreset GetPresetForPage(int pageId, string culture) - { - if (string.IsNullOrEmpty(culture)) - { - return null; - } + var documentType = _documentTypeAliasProvider.GetDocumentTypeAlias(pageId); + if (documentType is null) return null; - string documentType = _documentTypeAliasProvider.GetDocumentTypeAlias(pageId); - return GetPresetForPage(documentType, culture); - } + return GetPresetForPage(documentType, culture); + } - public IContentBlocksPreset GetPresetForPage(string documentType, string culture) + public IContentBlocksPreset? GetPresetForPage(string documentType, string culture) + { + if (string.IsNullOrEmpty(documentType)) { - if (string.IsNullOrEmpty(documentType)) - { - return null; - } + return null; + } - bool isEmptyOrContains(IEnumerable input, string toMatch) - => input?.Any() != true || input.Any(i => string.Equals(i, toMatch, StringComparison.InvariantCultureIgnoreCase)); + bool isEmptyOrContains(IEnumerable input, string toMatch) + => input?.Any() != true || input.Any(i => string.Equals(i, toMatch, StringComparison.InvariantCultureIgnoreCase)); - return GetAll()?.FirstOrDefault(p => - isEmptyOrContains(p.ApplyToCultures, culture) && - isEmptyOrContains(p.ApplyToDocumentTypes, documentType)); - } + return GetAll()?.FirstOrDefault(p => + isEmptyOrContains(p.ApplyToCultures, culture) && + isEmptyOrContains(p.ApplyToDocumentTypes, documentType)); } } diff --git a/src/Perplex.ContentBlocks.Core/Preview/Constants.Preview.cs b/src/Perplex.ContentBlocks.Core/Preview/Constants.Preview.cs index 1262a51..18be670 100644 --- a/src/Perplex.ContentBlocks.Core/Preview/Constants.Preview.cs +++ b/src/Perplex.ContentBlocks.Core/Preview/Constants.Preview.cs @@ -1,13 +1,12 @@ -namespace Perplex.ContentBlocks +namespace Perplex.ContentBlocks; + +public static partial class Constants { - public static partial class Constants + public static partial class Preview { - public static partial class Preview - { - public const string UmbracoCookieName = "UMB_UCONTEXT"; - public const string UmbracoPreviewCookieName = "UMB_PREVIEW"; - public const string UmbracoPreviewCookieValue = "preview"; - public const string UmbracoPreviewPath = "umbraco/preview/frame"; - } + public const string UmbracoCookieName = "UMB_UCONTEXT"; + public const string UmbracoPreviewCookieName = "UMB_PREVIEW"; + public const string UmbracoPreviewCookieValue = "preview"; + public const string UmbracoPreviewPath = "umbraco/preview/frame"; } } diff --git a/src/Perplex.ContentBlocks.Core/Preview/ContentBlocksPreviewApiController.cs b/src/Perplex.ContentBlocks.Core/Preview/ContentBlocksPreviewApiController.cs index f3b3c7e..9ab6a48 100644 --- a/src/Perplex.ContentBlocks.Core/Preview/ContentBlocksPreviewApiController.cs +++ b/src/Perplex.ContentBlocks.Core/Preview/ContentBlocksPreviewApiController.cs @@ -1,149 +1,121 @@ using HtmlAgilityPack; +using Microsoft.AspNetCore.Mvc; using Perplex.ContentBlocks.Utils.Cookies; -using System; -using System.Collections.Generic; -using System.Net.Http; using System.Net.Mime; using System.Text; -using System.Threading.Tasks; +using Umbraco.Cms.Web.BackOffice.Controllers; using static Perplex.ContentBlocks.Constants.Preview; -#if NET5_0 -using Microsoft.AspNetCore.Mvc; -using Umbraco.Cms.Web.BackOffice.Controllers; -#elif NET472 -using System.Net.Http.Headers; -using System.Web.Http; -using Umbraco.Web.WebApi; -#endif +namespace Perplex.ContentBlocks.Preview; -namespace Perplex.ContentBlocks.Preview +public class ContentBlocksPreviewApiController : UmbracoAuthorizedApiController { - public class ContentBlocksPreviewApiController : UmbracoAuthorizedApiController + private static readonly HttpClient _httpClient; + private readonly IPreviewScrollScriptProvider _scrollScriptProvider; + private readonly IHttpCookiesAccessor _httpCookiesAccessor; + + static ContentBlocksPreviewApiController() + { + var handler = new HttpClientHandler + { + UseCookies = false, + // Do not validate any certificates, which fails on self signed certificates and causes the preview to fail. + ServerCertificateCustomValidationCallback = (_, __, ___, ____) => true + }; + + _httpClient = new HttpClient(handler); + } + + public ContentBlocksPreviewApiController(IPreviewScrollScriptProvider scrollScriptProvider, IHttpCookiesAccessor httpCookiesAccessor) + { + _scrollScriptProvider = scrollScriptProvider; + _httpCookiesAccessor = httpCookiesAccessor; + } + + [HttpGet] + public async Task GetPreviewForIframe(int? pageId, string culture) + { + string html = string.Empty; + + if (pageId != null) + { + html = await GetPreviewHtml(pageId.Value, culture); + } + + return Content(html, MediaTypeNames.Text.Html, Encoding.UTF8); + } + + private async Task GetPreviewHtml(int pageId, string culture) { - private static readonly HttpClient _httpClient; - private readonly IPreviewScrollScriptProvider _scrollScriptProvider; - private readonly IHttpCookiesAccessor _httpCookiesAccessor; + string host = Request.Scheme + "://" + Request.Host; + string path = GetPreviewPath(pageId, culture); - static ContentBlocksPreviewApiController() + if (!Uri.TryCreate($"{host}/{path}", UriKind.Absolute, out Uri? previewUri)) { - var handler = new HttpClientHandler - { - UseCookies = false, - // Do not validate any certificates, which fails on self signed certificates and causes the preview to fail. - ServerCertificateCustomValidationCallback = (_, __, ___, ____) => true - }; - - _httpClient = new HttpClient(handler); + return string.Empty; } - public ContentBlocksPreviewApiController(IPreviewScrollScriptProvider scrollScriptProvider, IHttpCookiesAccessor httpCookiesAccessor) + var message = new HttpRequestMessage(HttpMethod.Get, previewUri); + + IList cookies = new List(); + if (_httpCookiesAccessor.Cookies.TryGetValue(UmbracoCookieName, out string? umbracoCookieValue)) { - _scrollScriptProvider = scrollScriptProvider; - _httpCookiesAccessor = httpCookiesAccessor; + cookies.Add($"{UmbracoCookieName}={umbracoCookieValue}"); } - [HttpGet] -#if NET5_0 - public async Task GetPreviewForIframe(int? pageId, string culture) -#elif NET472 - public async Task GetPreviewForIframe(int? pageId, string culture) -#endif + // Preview cookie to enable preview mode + cookies.Add($"{UmbracoPreviewCookieName}={UmbracoPreviewCookieValue}"); + + string cookieHeader = string.Join("; ", cookies); + message.Headers.Add("Cookie", cookieHeader); + + var result = await _httpClient.SendAsync(message); + string html = await result.Content.ReadAsStringAsync(); + + if (!result.IsSuccessStatusCode) { - string html = string.Empty; - - if (pageId != null) - { - html = await GetPreviewHtml(pageId.Value, culture); - } - -#if NET5_0 - return Content(html, MediaTypeNames.Text.Html, Encoding.UTF8); -#elif NET472 - var response = new HttpResponseMessage - { - Content = new StringContent(html) - }; - response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html"); - return response; -#endif + // Do not modify the HTML when it was not successful + return html; } + else + { + return TransformOriginalHtmlToPreviewHtml(html); + } + } - private async Task GetPreviewHtml(int pageId, string culture) + /// + /// Transforms the original HTML we receive from Umbraco's preview mode to the format we want. + /// + /// Original HTML of this page based on Umbraco's preview mode + /// + private string TransformOriginalHtmlToPreviewHtml(string originalHtml) + { + if (string.IsNullOrEmpty(originalHtml)) { -#if NET5_0 - string host = Request.Scheme + "://" + Request.Host; -#elif NET472 - string host = Request.RequestUri.GetLeftPart(UriPartial.Authority); -#endif - string path = GetPreviewPath(pageId, culture); - - if (!Uri.TryCreate($"{host}/{path}", UriKind.Absolute, out Uri previewUri)) - { - return string.Empty; - } - - var message = new HttpRequestMessage(HttpMethod.Get, previewUri); - - IList cookies = new List(); - if (_httpCookiesAccessor.Cookies.TryGetValue(UmbracoCookieName, out string umbracoCookieValue)) - { - cookies.Add($"{UmbracoCookieName}={umbracoCookieValue}"); - } - - // Preview cookie to enable preview mode - cookies.Add($"{UmbracoPreviewCookieName}={UmbracoPreviewCookieValue}"); - - string cookieHeader = string.Join("; ", cookies); - message.Headers.Add("Cookie", cookieHeader); - - var result = await _httpClient.SendAsync(message); - string html = await result.Content.ReadAsStringAsync(); - - if (!result.IsSuccessStatusCode) - { - // Do not modify the HTML when it was not successful - return html; - } - else - { - return TransformOriginalHtmlToPreviewHtml(html); - } + return originalHtml; } - /// - /// Transforms the original HTML we receive from Umbraco's preview mode to the format we want. - /// - /// Original HTML of this page based on Umbraco's preview mode - /// - private string TransformOriginalHtmlToPreviewHtml(string originalHtml) + HtmlDocument doc = new HtmlDocument(); + doc.LoadHtml(originalHtml); + + if (doc.DocumentNode.SelectSingleNode("//*[@id='umbracoPreviewBadge']") is HtmlNode previewLabel) { - if (string.IsNullOrEmpty(originalHtml)) - { - return originalHtml; - } - - HtmlDocument doc = new HtmlDocument(); - doc.LoadHtml(originalHtml); - - if (doc.DocumentNode.SelectSingleNode("//*[@id='umbracoPreviewBadge']") is HtmlNode previewLabel) - { - // Remove Umbraco Preview Badge - previewLabel.Remove(); - } - - if (doc.DocumentNode.SelectSingleNode("//body") is HtmlNode body) - { - AppendScrollScript(body); - } - - // .OuterHtml does not contain a DOCTYPE declaration so we add this manually - return "" + doc.DocumentNode.OuterHtml; + // Remove Umbraco Preview Badge + previewLabel.Remove(); } - private void AppendScrollScript(HtmlNode parent) + if (doc.DocumentNode.SelectSingleNode("//body") is HtmlNode body) { - string script = @" + AppendScrollScript(body); + } + + // .OuterHtml does not contain a DOCTYPE declaration so we add this manually + return "" + doc.DocumentNode.OuterHtml; + } + + private void AppendScrollScript(HtmlNode parent) + { + string script = @" "; - var scriptNode = HtmlNode.CreateNode(script); - parent.AppendChild(scriptNode); - } + var scriptNode = HtmlNode.CreateNode(script); + parent.AppendChild(scriptNode); + } - private string GetPreviewPath(int pageId, string culture) + private string GetPreviewPath(int pageId, string culture) + { + string path = UmbracoPreviewPath + "?id=" + pageId; + if (!string.IsNullOrEmpty(culture)) { - string path = UmbracoPreviewPath + "?id=" + pageId; - if (!string.IsNullOrEmpty(culture)) - { - // If a content type is not set to "allow varying by culture" - // the culture will be null. - path += "&culture=" + culture; - } - - return path; + // If a content type is not set to "allow varying by culture" + // the culture will be null. + path += "&culture=" + culture; } + + return path; } } diff --git a/src/Perplex.ContentBlocks.Core/Preview/ContentBlocksPreviewComposer.cs b/src/Perplex.ContentBlocks.Core/Preview/ContentBlocksPreviewComposer.cs index fbefd4d..87cd4f6 100644 --- a/src/Perplex.ContentBlocks.Core/Preview/ContentBlocksPreviewComposer.cs +++ b/src/Perplex.ContentBlocks.Core/Preview/ContentBlocksPreviewComposer.cs @@ -1,38 +1,18 @@ -#if NET5_0 -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.Composing; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Extensions; -#elif NET472 -using Umbraco.Core; -using Umbraco.Core.Composing; -#endif -namespace Perplex.ContentBlocks.Preview -{ -#if NET5_0 - public class ContentBlocksPreviewComposer : IComposer - { - public void Compose(IUmbracoBuilder builder) - { - builder.Services.AddScoped(); +namespace Perplex.ContentBlocks.Preview; - // Can be replaced by clients - builder.Services.AddUnique(); - } - } -#elif NET472 - [RuntimeLevel(MinLevel = RuntimeLevel.Run)] - public class ContentBlocksPreviewComposer : IUserComposer +public class ContentBlocksPreviewComposer : IComposer +{ + public void Compose(IUmbracoBuilder builder) { - public void Compose(Composition composition) - { - composition.Register(Lifetime.Scope); + builder.Services.AddScoped(); - // Can be replaced by clients - composition.RegisterUnique(); - } + // Can be replaced by clients + builder.Services.AddUnique(); } -#endif } diff --git a/src/Perplex.ContentBlocks.Core/Preview/CookieBasedPreviewModeProvider.cs b/src/Perplex.ContentBlocks.Core/Preview/CookieBasedPreviewModeProvider.cs index 865878d..2476184 100644 --- a/src/Perplex.ContentBlocks.Core/Preview/CookieBasedPreviewModeProvider.cs +++ b/src/Perplex.ContentBlocks.Core/Preview/CookieBasedPreviewModeProvider.cs @@ -1,18 +1,17 @@ using Perplex.ContentBlocks.Utils.Cookies; -namespace Perplex.ContentBlocks.Preview -{ - public class CookieBasedPreviewModeProvider : IPreviewModeProvider - { - private readonly IHttpCookiesAccessor _cookiesAccessor; +namespace Perplex.ContentBlocks.Preview; - public CookieBasedPreviewModeProvider(IHttpCookiesAccessor cookiesAccessor) - { - _cookiesAccessor = cookiesAccessor; - } +public class CookieBasedPreviewModeProvider : IPreviewModeProvider +{ + private readonly IHttpCookiesAccessor _cookiesAccessor; - public bool IsPreviewMode => - _cookiesAccessor.Cookies.TryGetValue(Constants.Preview.UmbracoPreviewCookieName, out string value) && - value == Constants.Preview.UmbracoPreviewCookieValue; + public CookieBasedPreviewModeProvider(IHttpCookiesAccessor cookiesAccessor) + { + _cookiesAccessor = cookiesAccessor; } + + public bool IsPreviewMode => + _cookiesAccessor.Cookies.TryGetValue(Constants.Preview.UmbracoPreviewCookieName, out string? value) && + value == Constants.Preview.UmbracoPreviewCookieValue; } diff --git a/src/Perplex.ContentBlocks.Core/Preview/DefaultPreviewScrollScriptProvider.cs b/src/Perplex.ContentBlocks.Core/Preview/DefaultPreviewScrollScriptProvider.cs index 9f3e121..1b8a505 100644 --- a/src/Perplex.ContentBlocks.Core/Preview/DefaultPreviewScrollScriptProvider.cs +++ b/src/Perplex.ContentBlocks.Core/Preview/DefaultPreviewScrollScriptProvider.cs @@ -1,15 +1,14 @@ -namespace Perplex.ContentBlocks.Preview +namespace Perplex.ContentBlocks.Preview; + +/// +/// Default preview scroll script. +/// Scrolls exactly to the anchor generated for a Content Block. +/// Does not take into account a fixed header bar or other elements like that. +/// +public class DefaultPreviewScrollScriptProvider : IPreviewScrollScriptProvider { - /// - /// Default preview scroll script. - /// Scrolls exactly to the anchor generated for a Content Block. - /// Does not take into account a fixed header bar or other elements like that. - /// - public class DefaultPreviewScrollScriptProvider : IPreviewScrollScriptProvider - { - public string ScrollScript { get; } = @" + public string ScrollScript { get; } = @" if (element != null && typeof window.jump === ""function"") { window.jump(element, { duration: 500 }); }"; - } } diff --git a/src/Perplex.ContentBlocks.Core/Preview/IPreviewModeProvider.cs b/src/Perplex.ContentBlocks.Core/Preview/IPreviewModeProvider.cs index 7639c49..7db5d4f 100644 --- a/src/Perplex.ContentBlocks.Core/Preview/IPreviewModeProvider.cs +++ b/src/Perplex.ContentBlocks.Core/Preview/IPreviewModeProvider.cs @@ -1,7 +1,6 @@ -namespace Perplex.ContentBlocks.Preview +namespace Perplex.ContentBlocks.Preview; + +public interface IPreviewModeProvider { - public interface IPreviewModeProvider - { - bool IsPreviewMode { get; } - } + bool IsPreviewMode { get; } } diff --git a/src/Perplex.ContentBlocks.Core/Preview/IPreviewScrollScriptProvider.cs b/src/Perplex.ContentBlocks.Core/Preview/IPreviewScrollScriptProvider.cs index af5d167..47d2712 100644 --- a/src/Perplex.ContentBlocks.Core/Preview/IPreviewScrollScriptProvider.cs +++ b/src/Perplex.ContentBlocks.Core/Preview/IPreviewScrollScriptProvider.cs @@ -1,12 +1,11 @@ -namespace Perplex.ContentBlocks.Preview +namespace Perplex.ContentBlocks.Preview; + +public interface IPreviewScrollScriptProvider { - public interface IPreviewScrollScriptProvider - { - /// - /// JavaScript function to execute when scrolling to a specific Content Block. - /// The JavaScript provided will be executed within a function scope that - /// has already set an "element" variable to the DOM element of the scroll anchor. - /// - string ScrollScript { get; } - } + /// + /// JavaScript function to execute when scrolling to a specific Content Block. + /// The JavaScript provided will be executed within a function scope that + /// has already set an "element" variable to the DOM element of the scroll anchor. + /// + string ScrollScript { get; } } diff --git a/src/Perplex.ContentBlocks.Core/PropertyEditor/Configuration/Constants.PropertyEditor.Configuration.cs b/src/Perplex.ContentBlocks.Core/PropertyEditor/Configuration/Constants.PropertyEditor.Configuration.cs index 4dc46d1..6e52748 100644 --- a/src/Perplex.ContentBlocks.Core/PropertyEditor/Configuration/Constants.PropertyEditor.Configuration.cs +++ b/src/Perplex.ContentBlocks.Core/PropertyEditor/Configuration/Constants.PropertyEditor.Configuration.cs @@ -1,28 +1,27 @@ -namespace Perplex.ContentBlocks +namespace Perplex.ContentBlocks; + +public static partial class Constants { - public static partial class Constants + public static partial class PropertyEditor { - public static partial class PropertyEditor + public static partial class Configuration { - public static partial class Configuration - { - public const string VersionKey = "_version"; + public const string VersionKey = "_version"; - public const string StructureKey = "structure"; - public const string StructureViewName = "/App_Plugins/Perplex.ContentBlocks/configuration/perplex.content-blocks.configuration.structure.html"; + public const string StructureKey = "structure"; + public const string StructureViewName = "/App_Plugins/Perplex.ContentBlocks/configuration/perplex.content-blocks.configuration.structure.html"; - public const string DisablePreviewKey = "disablePreview"; - public const string DisablePreviewViewName = "boolean"; + public const string DisablePreviewKey = "disablePreview"; + public const string DisablePreviewViewName = "boolean"; - public const string HideLabelKey = "hideLabel"; - public const string HideLabelViewName = "boolean"; + public const string HideLabelKey = "hideLabel"; + public const string HideLabelViewName = "boolean"; - public const string HidePropertyGroupContainerKey = "hidePropertyGroupContainer"; - public const string HidePropertyGroupContainerViewName = "boolean"; + public const string HidePropertyGroupContainerKey = "hidePropertyGroupContainer"; + public const string HidePropertyGroupContainerViewName = "boolean"; - public const string AllowBlocksWithoutHeaderKey = "allowBlocksWithoutHeader"; - public const string AllowBlocksWithoutHeaderViewName = "boolean"; - } + public const string AllowBlocksWithoutHeaderKey = "allowBlocksWithoutHeader"; + public const string AllowBlocksWithoutHeaderViewName = "boolean"; } } } diff --git a/src/Perplex.ContentBlocks.Core/PropertyEditor/Configuration/ContentBlocksConfiguration.cs b/src/Perplex.ContentBlocks.Core/PropertyEditor/Configuration/ContentBlocksConfiguration.cs index 96331fb..2d4fbd3 100644 --- a/src/Perplex.ContentBlocks.Core/PropertyEditor/Configuration/ContentBlocksConfiguration.cs +++ b/src/Perplex.ContentBlocks.Core/PropertyEditor/Configuration/ContentBlocksConfiguration.cs @@ -1,29 +1,86 @@ -using System; +namespace Perplex.ContentBlocks.PropertyEditor.Configuration; -namespace Perplex.ContentBlocks.PropertyEditor.Configuration +/// +/// The structure of the editor in the backoffice +/// +[Flags] +public enum Structure { - [Flags] - public enum Structure - { - None = 0, + /// + /// Default value - nothing + /// + None = 0, + + /// + /// Blocks only + /// + Blocks = 1, + + /// + /// Header only + /// + Header = 2, + + /// + /// Blocks and Header + /// + All = Blocks | Header, +} + +/// +/// ContentBlocks configuration +/// +public class ContentBlocksConfiguration +{ + /// + /// Added for detecting out of date configuration objects in the future. + /// + public int Version { get; set; } - Blocks = 1, - Header = 2, + /// + /// The structure of the editor in the backoffice + /// + public Structure Structure { get; set; } - All = Blocks | Header, - } + /// + /// Indicates if the preview component should be hidden + /// + public bool DisablePreview { get; set; } - public class ContentBlocksConfiguration + /// + /// Indicates if the label of the editor should be hidden + /// + public bool HideLabel { get; set; } + + /// + /// Indicates if the property group container should be hidden + /// + public bool HidePropertyGroupContainer { get; set; } + + /// + /// Indicates if it is allowed to add blocks without first setting a header + /// + public bool AllowBlocksWithoutHeader { get; set; } + + /// + /// Current configuration version. + /// + public const int VERSION = 3; + + public static readonly ContentBlocksConfiguration DefaultConfiguration = new() { - /// - /// Added for detecting out of date configuration objects in the future. - /// - public int Version { get; set; } - - public Structure Structure { get; set; } - public bool DisablePreview { get; set; } - public bool HideLabel { get; set; } - public bool HidePropertyGroupContainer { get; set; } - public bool AllowBlocksWithoutHeader { get; set; } - } + Version = VERSION, + + HideLabel = true, + Structure = Structure.Blocks | Structure.Header, + DisablePreview = false, + + // It is quite likely this will default to "false" in the future + // considering hiding the property group container is messing with + // the default Umbraco UI and also causes some flickering upon page load + // when the group is being hidden after our editor is initialized. + HidePropertyGroupContainer = true, + + AllowBlocksWithoutHeader = false, + }; } diff --git a/src/Perplex.ContentBlocks.Core/PropertyEditor/Configuration/ContentBlocksConfigurationEditor.cs b/src/Perplex.ContentBlocks.Core/PropertyEditor/Configuration/ContentBlocksConfigurationEditor.cs index 7c22ccc..edb2546 100644 --- a/src/Perplex.ContentBlocks.Core/PropertyEditor/Configuration/ContentBlocksConfigurationEditor.cs +++ b/src/Perplex.ContentBlocks.Core/PropertyEditor/Configuration/ContentBlocksConfigurationEditor.cs @@ -1,245 +1,213 @@ using Newtonsoft.Json.Linq; -using System.Collections.Generic; -using static Perplex.ContentBlocks.Constants.PropertyEditor.Configuration; - -#if NET5_0 using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.PropertyEditors; using Umbraco.Cms.Core.Serialization; -#elif NET472 -using Umbraco.Core.PropertyEditors; -#endif +using Umbraco.Cms.Core.Services; +using static Perplex.ContentBlocks.Constants.PropertyEditor.Configuration; + +namespace Perplex.ContentBlocks.PropertyEditor.Configuration; -namespace Perplex.ContentBlocks.PropertyEditor.Configuration +public class ContentBlocksConfigurationEditor : ConfigurationEditor { - public class ContentBlocksConfigurationEditor : ConfigurationEditor + public ContentBlocksConfigurationEditor(IIOHelper ioHelper, IEditorConfigurationParser editorConfigurationParser) + : base(ioHelper, editorConfigurationParser) { -#if NET5_0 -public ContentBlocksConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) -#elif NET472 - public ContentBlocksConfigurationEditor() -#endif + Fields.AddRange(new[] { - Fields.AddRange(new[] + new ConfigurationField { - new ConfigurationField - { - Name = "Structure", - Description = "Sets the structure", - Key = StructureKey, - View = StructureViewName, - }, - - new ConfigurationField - { - Name = "Disable preview", - Description = "Disables the preview feature", - Key = DisablePreviewKey, - View = DisablePreviewViewName, - }, - - new ConfigurationField - { - Name = "Hide label", - Description = "Hides the data type label", - Key = HideLabelKey, - View = HideLabelViewName, - }, - - new ConfigurationField - { - Name = "Hide property group container", - Description = "Hides the property group container that holds this editor", - Key = HidePropertyGroupContainerKey, - View = HidePropertyGroupContainerViewName, - }, - - new ConfigurationField - { - Name = "Allow adding blocks without header", - Description = "Blocks can be added without having to set a header first", - Key = AllowBlocksWithoutHeaderKey, - View = AllowBlocksWithoutHeaderViewName, - }, - }); - } + Name = "Structure", + Description = "Sets the structure", + Key = StructureKey, + View = StructureViewName, + }, - /// - /// Current configuration version. - /// - public const int Version = 3; + new ConfigurationField + { + Name = "Disable preview", + Description = "Disables the preview feature", + Key = DisablePreviewKey, + View = DisablePreviewViewName, + }, - internal static readonly ContentBlocksConfiguration _defaultConfiguration = new ContentBlocksConfiguration - { - Version = Version, + new ConfigurationField + { + Name = "Hide label", + Description = "Hides the data type label", + Key = HideLabelKey, + View = HideLabelViewName, + }, - HideLabel = true, - Structure = Structure.Blocks | Structure.Header, - DisablePreview = false, + new ConfigurationField + { + Name = "Hide property group container", + Description = "Hides the property group container that holds this editor", + Key = HidePropertyGroupContainerKey, + View = HidePropertyGroupContainerViewName, + }, - // It is quite likely this will default to "false" in the future - // considering hiding the property group container is messing with - // the default Umbraco UI and also causes some flickering upon page load - // when the group is being hidden after our editor is initialized. - HidePropertyGroupContainer = true, + new ConfigurationField + { + Name = "Allow adding blocks without header", + Description = "Blocks can be added without having to set a header first", + Key = AllowBlocksWithoutHeaderKey, + View = AllowBlocksWithoutHeaderViewName, + }, + }); + } - AllowBlocksWithoutHeader = false, - }; + public override object DefaultConfigurationObject { get; } + = ContentBlocksConfiguration.DefaultConfiguration; - public override object DefaultConfigurationObject { get; } - = _defaultConfiguration; + public override IDictionary DefaultConfiguration + => ToConfigurationEditor(DefaultConfigurationObject); - public override IDictionary DefaultConfiguration - => ToConfigurationEditor(_defaultConfiguration); + public override ContentBlocksConfiguration FromConfigurationEditor(IDictionary? editorValues, ContentBlocksConfiguration? configuration) + { + var hideLabel = GetBool(editorValues, HideLabelKey); + var structure = GetStructure(editorValues); + var disablePreview = GetBool(editorValues, DisablePreviewKey); + var hidePropertyGroupContainer = GetBool(editorValues, HidePropertyGroupContainerKey); + var requireHeaderForBlocks = GetBool(editorValues, AllowBlocksWithoutHeaderKey); + + var defaultConfig = ContentBlocksConfiguration.DefaultConfiguration; - public override ContentBlocksConfiguration FromConfigurationEditor(IDictionary editorValues, ContentBlocksConfiguration configuration) + return new ContentBlocksConfiguration { - var hideLabel = GetBool(editorValues, HideLabelKey); - var structure = GetStructure(editorValues); - var disablePreview = GetBool(editorValues, DisablePreviewKey); - var hidePropertyGroupContainer = GetBool(editorValues, HidePropertyGroupContainerKey); - var requireHeaderForBlocks = GetBool(editorValues, AllowBlocksWithoutHeaderKey); + // When saved we store the current version, + // Any transformations should have been applied before + // and the user has now actively saved the configuration again. + Version = ContentBlocksConfiguration.VERSION, + + Structure = structure ?? defaultConfig.Structure, + DisablePreview = disablePreview ?? defaultConfig.DisablePreview, + HideLabel = hideLabel ?? defaultConfig.HideLabel, + HidePropertyGroupContainer = hidePropertyGroupContainer ?? defaultConfig.HidePropertyGroupContainer, + AllowBlocksWithoutHeader = requireHeaderForBlocks ?? defaultConfig.AllowBlocksWithoutHeader, + }; + } - return new ContentBlocksConfiguration - { - // When saved we store the current version, - // Any transformations should have been applied before - // and the user has now actively saved the configuration again. - Version = Version, - - Structure = structure ?? _defaultConfiguration.Structure, - DisablePreview = disablePreview ?? _defaultConfiguration.DisablePreview, - HideLabel = hideLabel ?? _defaultConfiguration.HideLabel, - HidePropertyGroupContainer = hidePropertyGroupContainer ?? _defaultConfiguration.HidePropertyGroupContainer, - AllowBlocksWithoutHeader = requireHeaderForBlocks ?? _defaultConfiguration.AllowBlocksWithoutHeader, - }; + public override Dictionary ToConfigurationEditor(ContentBlocksConfiguration? configuration) + { + if (configuration is null) + { + return new Dictionary(); } - public override Dictionary ToConfigurationEditor(ContentBlocksConfiguration configuration) + return new Dictionary { - return new Dictionary + [VersionKey] = configuration.Version, + + [StructureKey] = new { - [VersionKey] = configuration.Version, + blocks = configuration.Structure.HasFlag(Structure.Blocks), + header = configuration.Structure.HasFlag(Structure.Header), + }, - [StructureKey] = new - { - blocks = configuration.Structure.HasFlag(Structure.Blocks), - header = configuration.Structure.HasFlag(Structure.Header), - }, + [DisablePreviewKey] = configuration.DisablePreview, - [DisablePreviewKey] = configuration.DisablePreview, + [HideLabelKey] = configuration.HideLabel, - [HideLabelKey] = configuration.HideLabel, + [HidePropertyGroupContainerKey] = configuration.HidePropertyGroupContainer, - [HidePropertyGroupContainerKey] = configuration.HidePropertyGroupContainer, + [AllowBlocksWithoutHeaderKey] = configuration.AllowBlocksWithoutHeader, + }; + } - [AllowBlocksWithoutHeaderKey] = configuration.AllowBlocksWithoutHeader, - }; + public override object FromDatabase(string? configuration, IConfigurationEditorJsonSerializer configurationEditorJsonSerializer) + { + if (configuration == null || configuration.Trim() == "{}") + { + // Special case: empty configuration object. + // That is not allowed, return the default. + return ContentBlocksConfiguration.DefaultConfiguration; } -#if NET5_0 - public override object FromDatabase(string configuration, IConfigurationEditorJsonSerializer configurationEditorJsonSerializer) -#elif NET472 - public override object FromDatabase(string configuration) -#endif + try { - if (configuration == null || configuration.Trim() == "{}") + if (base.FromDatabase(configuration, configurationEditorJsonSerializer) is ContentBlocksConfiguration contentBlocksConfiguration) { - // Special case: empty configuration object. - // That is not allowed, return the default. - return _defaultConfiguration; + return ApplyMigrations(contentBlocksConfiguration); } - - try + else { -#if NET5_0 - if (base.FromDatabase(configuration, configurationEditorJsonSerializer) is ContentBlocksConfiguration contentBlocksConfiguration) -#elif NET472 - if (base.FromDatabase(configuration) is ContentBlocksConfiguration contentBlocksConfiguration) -#endif - { - return ApplyMigrations(contentBlocksConfiguration); - } - else - { - return _defaultConfiguration; - }; - } - catch - { - return _defaultConfiguration; - } + return ContentBlocksConfiguration.DefaultConfiguration; + }; } - - private ContentBlocksConfiguration ApplyMigrations(ContentBlocksConfiguration source) + catch { - if (source.Version == Version) - { - // Already the latest version. - return source; - } - - switch (source.Version) - { - case 1: - // HidePropertyGroupContainer will be read as "false" when this option - // did not exist before, whereas our default is "true" at the moment. - // To not suddenly change existing editors upon update we should set - // this setting to "true" for existing editors. - source.HidePropertyGroupContainer = true; - break; - - default: - break; - } + return ContentBlocksConfiguration.DefaultConfiguration; + } + } + private static ContentBlocksConfiguration ApplyMigrations(ContentBlocksConfiguration source) + { + if (source.Version == ContentBlocksConfiguration.VERSION) + { + // Already the latest version. return source; } - private bool? GetBool(IDictionary config, string key) + switch (source.Version) { - if (config != null && config.TryGetValue(key, out object value) && - ParseBoolean(value?.ToString()) is bool boolValue) - { - return boolValue; - }; - - return null; + case 1: + // HidePropertyGroupContainer will be read as "false" when this option + // did not exist before, whereas our default is "true" at the moment. + // To not suddenly change existing editors upon update we should set + // this setting to "true" for existing editors. + source.HidePropertyGroupContainer = true; + break; + + default: + break; } - private bool? ParseBoolean(string input) + return source; + } + + private static bool? GetBool(IDictionary? config, string key) + { + if (config != null && config.TryGetValue(key, out object? value) && + ParseBoolean(value?.ToString()) is bool boolValue) { - if (bool.TryParse(input, out bool value)) - return value; + return boolValue; + }; - // Parse manually - if (input == "0") - return false; + return null; + } - if (input == "1") - return true; + private static bool? ParseBoolean(string? input) + { + if (bool.TryParse(input, out bool value)) + return value; - return null; - } + // Parse manually + if (input == "0") + return false; - private Structure? GetStructure(IDictionary config) - { - Structure structure = Structure.None; + if (input == "1") + return true; - if (config != null && - config.TryGetValue(StructureKey, out object obj) && - obj is JObject structureObj) - { - if (structureObj.Value("blocks")) - structure |= Structure.Blocks; + return null; + } - if (structureObj.Value("header")) - structure |= Structure.Header; + private static Structure? GetStructure(IDictionary? config) + { + Structure structure = Structure.None; - return structure; - }; + if (config != null && + config.TryGetValue(StructureKey, out object? obj) && + obj is JObject structureObj) + { + if (structureObj.Value("blocks")) + structure |= Structure.Blocks; - return null; - } + if (structureObj.Value("header")) + structure |= Structure.Header; + + return structure; + }; + + return null; } } diff --git a/src/Perplex.ContentBlocks.Core/PropertyEditor/Constants.PropertyEditor.cs b/src/Perplex.ContentBlocks.Core/PropertyEditor/Constants.PropertyEditor.cs index 196da6a..b4a203d 100644 --- a/src/Perplex.ContentBlocks.Core/PropertyEditor/Constants.PropertyEditor.cs +++ b/src/Perplex.ContentBlocks.Core/PropertyEditor/Constants.PropertyEditor.cs @@ -1,13 +1,12 @@ -namespace Perplex.ContentBlocks +namespace Perplex.ContentBlocks; + +public static partial class Constants { - public static partial class Constants + public static partial class PropertyEditor { - public static partial class PropertyEditor - { - public const string Alias = "Perplex.ContentBlocks"; - public const string Name = "Perplex.ContentBlocks"; - public const string ViewPath = "/App_Plugins/Perplex.ContentBlocks/perplex.content-blocks.html"; - public const string AssetsFolder = "/App_Plugins/Perplex.ContentBlocks/assets"; - } + public const string Alias = "Perplex.ContentBlocks"; + public const string Name = "Perplex.ContentBlocks"; + public const string ViewPath = "/App_Plugins/Perplex.ContentBlocks/perplex.content-blocks.html"; + public const string AssetsFolder = "/App_Plugins/Perplex.ContentBlocks/assets"; } } diff --git a/src/Perplex.ContentBlocks.Core/PropertyEditor/ContentBlocksManifestFilter.cs b/src/Perplex.ContentBlocks.Core/PropertyEditor/ContentBlocksManifestFilter.cs index 07d98ab..d9d7132 100644 --- a/src/Perplex.ContentBlocks.Core/PropertyEditor/ContentBlocksManifestFilter.cs +++ b/src/Perplex.ContentBlocks.Core/PropertyEditor/ContentBlocksManifestFilter.cs @@ -1,6 +1,4 @@ -#if NET5_0_OR_GREATER - -using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting; using System; using System.Collections.Generic; using System.IO; @@ -10,89 +8,87 @@ using Umbraco.Cms.Core.Manifest; using Umbraco.Extensions; -namespace Perplex.ContentBlocks.PropertyEditor +namespace Perplex.ContentBlocks.PropertyEditor; + +/// +/// Manifest Filter to ensure the main ContentBlocks JavaScript file that creates the AngularJS module "perplexContentBlocks" always runs first. +/// In addition it ensures all package.manifest files are loaded. +/// Starting with Umbraco v11 the load order of package.manifest files has changed and the file is no longer loaded first like it +/// was in v8, v9 and v10. +/// This filter is applied to v9 and v10 as well to pre-empt Umbraco backporting the v11 change to v9 and v10, breaking them too. +/// +public class ContentBlocksManifestFilter : IManifestFilter { - /// - /// Manifest Filter to ensure the main ContentBlocks JavaScript file that creates the AngularJS module "perplexContentBlocks" always runs first. - /// In addition it ensures all package.manifest files are loaded. - /// Starting with Umbraco v11 the load order of package.manifest files has changed and the file is no longer loaded first like it - /// was in v8, v9 and v10. - /// This filter is applied to v9 and v10 as well to pre-empt Umbraco backporting the v11 change to v9 and v10, breaking them too. - /// - public class ContentBlocksManifestFilter : IManifestFilter - { - private const string MANIFEST_FILE = "perplex.content-blocks.requires.js"; - private readonly IWebHostEnvironment _webHostEnv; - private readonly IManifestParser _manifestParser; + private const string MANIFEST_FILE = "perplex.content-blocks.requires.js"; + private readonly IWebHostEnvironment _webHostEnv; + private readonly IManifestParser _manifestParser; - public ContentBlocksManifestFilter(IWebHostEnvironment webHostEnv, IManifestParser manifestParser) - { - _webHostEnv = webHostEnv; - _manifestParser = manifestParser; - } + public ContentBlocksManifestFilter(IWebHostEnvironment webHostEnv, IManifestParser manifestParser) + { + _webHostEnv = webHostEnv; + _manifestParser = manifestParser; + } - public void Filter(List manifests) - { - EnsureManifestFilesAreLoaded(manifests); - FixManifestLoadOrder(manifests); - } + public void Filter(List manifests) + { + EnsureManifestFilesAreLoaded(manifests); + FixManifestLoadOrder(manifests); + } - /// - /// Ensure our manifest files from App_Plugins\Perplex.ContentBlocks\ are loaded. - /// When Umbraco fixes https://github.com/umbraco/Umbraco-CMS/issues/13565 this method will no longer be needed but - /// at the same time shouldn't be harmful to keep around as it only does something when no Perplex.ContentBlocks manifests are found. - /// - /// Currently loaded manifests - private void EnsureManifestFilesAreLoaded(List manifests) + /// + /// Ensure our manifest files from App_Plugins\Perplex.ContentBlocks\ are loaded. + /// When Umbraco fixes https://github.com/umbraco/Umbraco-CMS/issues/13565 this method will no longer be needed but + /// at the same time shouldn't be harmful to keep around as it only does something when no Perplex.ContentBlocks manifests are found. + /// + /// Currently loaded manifests + private void EnsureManifestFilesAreLoaded(List manifests) + { + if (manifests is not null && !manifests.Any(IsContentBlocksManifest)) { - if (manifests is not null && !manifests.Any(IsContentBlocksManifest)) + // Perplex.ContentBlocks manifest files are not loaded due to v11 bug, so if there not a single "Perplex.ContentBlocks" + // entry in the current manifests we add them all. + // We will manually read them from disk here ourselves. + var contentBlocksPath = Path.Combine(_webHostEnv.ContentRootPath, "App_Plugins", "Perplex.ContentBlocks"); + if (Directory.Exists(contentBlocksPath)) { - // Perplex.ContentBlocks manifest files are not loaded due to v11 bug, so if there not a single "Perplex.ContentBlocks" - // entry in the current manifests we add them all. - // We will manually read them from disk here ourselves. - var contentBlocksPath = Path.Combine(_webHostEnv.ContentRootPath, "App_Plugins", "Perplex.ContentBlocks"); - if (Directory.Exists(contentBlocksPath)) + var contentBlocksManifests = Directory.GetFiles(contentBlocksPath, "package.manifest", SearchOption.AllDirectories); + foreach (var manifestPath in contentBlocksManifests) { - var contentBlocksManifests = Directory.GetFiles(contentBlocksPath, "package.manifest", SearchOption.AllDirectories); - foreach (var manifestPath in contentBlocksManifests) - { - if (!File.Exists(manifestPath)) continue; + if (!File.Exists(manifestPath)) continue; - var packageManifestJson = File.ReadAllText(manifestPath); - if (string.IsNullOrWhiteSpace(packageManifestJson)) continue; + var packageManifestJson = File.ReadAllText(manifestPath); + if (string.IsNullOrWhiteSpace(packageManifestJson)) continue; - var packageManifest = _manifestParser.ParseManifest(packageManifestJson); + var packageManifest = _manifestParser.ParseManifest(packageManifestJson); - // Umbraco throws when PackageName is null so ensure it is not. - packageManifest.PackageName ??= ""; + // Umbraco throws when PackageName is null so ensure it is not. + packageManifest.PackageName ??= ""; - manifests.Add(packageManifest); - } + manifests.Add(packageManifest); } } - - static bool IsContentBlocksManifest(PackageManifest manifest) - => manifest?.Scripts?.Any(script => script?.Contains("/App_Plugins/Perplex.ContentBlocks/", StringComparison.OrdinalIgnoreCase) == true) == true; } - private static void FixManifestLoadOrder(List manifests) - { - var requiresManifest = manifests.FirstOrDefault(m => m.Scripts.Any(script => script.InvariantEndsWith(MANIFEST_FILE))); - - if (requiresManifest is not null) - { - // Ensure the requires file is loaded first - manifests.Remove(requiresManifest); - manifests.Insert(0, requiresManifest); - } - } + static bool IsContentBlocksManifest(PackageManifest manifest) + => manifest?.Scripts?.Any(script => script?.Contains("/App_Plugins/Perplex.ContentBlocks/", StringComparison.OrdinalIgnoreCase) == true) == true; } - public class ContentBlocksManifestFilterComposer : IComposer + private static void FixManifestLoadOrder(List manifests) { - public void Compose(IUmbracoBuilder builder) - => builder.ManifestFilters().Append(); + var requiresManifest = manifests.FirstOrDefault(m => m.Scripts.Any(script => script.InvariantEndsWith(MANIFEST_FILE))); + + if (requiresManifest is not null) + { + // Ensure the requires file is loaded first + manifests.Remove(requiresManifest); + manifests.Insert(0, requiresManifest); + } } } -#endif +public class ContentBlocksManifestFilterComposer : IComposer +{ + public void Compose(IUmbracoBuilder builder) + => builder.ManifestFilters().Append(); +} + diff --git a/src/Perplex.ContentBlocks.Core/PropertyEditor/ContentBlocksPropertyEditor.cs b/src/Perplex.ContentBlocks.Core/PropertyEditor/ContentBlocksPropertyEditor.cs index d3e8485..0d78506 100644 --- a/src/Perplex.ContentBlocks.Core/PropertyEditor/ContentBlocksPropertyEditor.cs +++ b/src/Perplex.ContentBlocks.Core/PropertyEditor/ContentBlocksPropertyEditor.cs @@ -1,131 +1,84 @@ using Perplex.ContentBlocks.PropertyEditor.Configuration; using Perplex.ContentBlocks.PropertyEditor.ModelValue; using Perplex.ContentBlocks.Utils; -using System; -using System.Collections.Generic; - -#if NET5_0 -using Microsoft.AspNetCore.Http; 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.Core.Strings; -#elif NET472 -using Umbraco.Core; -using Umbraco.Core.IO; -using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Services; -using Umbraco.Web; -#endif -namespace Perplex.ContentBlocks.PropertyEditor +namespace Perplex.ContentBlocks.PropertyEditor; + +public class ContentBlocksPropertyEditor : IDataEditor { - public class ContentBlocksPropertyEditor : IDataEditor + private readonly ContentBlocksModelValueDeserializer _deserializer; + private readonly ContentBlockUtils _utils; + + private readonly IIOHelper _iOHelper; + private readonly ILocalizedTextService _localizedTextService; + private readonly IShortStringHelper _shortStringHelper; + private readonly IJsonSerializer _jsonSerializer; + private readonly IPropertyValidationService _validationService; + private readonly IEditorConfigurationParser _editorConfigurationParser; + + public ContentBlocksPropertyEditor( + ContentBlocksModelValueDeserializer deserializer, + ContentBlockUtils utils, + IIOHelper iOHelper, + ILocalizedTextService localizedTextService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer, + IPropertyValidationService validationService, + IEditorConfigurationParser editorConfigurationParser) { - private readonly ContentBlocksModelValueDeserializer _deserializer; - private readonly ContentBlockUtils _utils; + _deserializer = deserializer; + _utils = utils; + _iOHelper = iOHelper; + _localizedTextService = localizedTextService; + _shortStringHelper = shortStringHelper; + _jsonSerializer = jsonSerializer; + _validationService = validationService; + _editorConfigurationParser = editorConfigurationParser; + } -#if NET5_0 - private readonly IIOHelper _iOHelper; - private readonly ILocalizedTextService _localizedTextService; - private readonly IShortStringHelper _shortStringHelper; - private readonly IJsonSerializer _jsonSerializer; - private readonly IPropertyValidationService _validationService; + public string Alias { get; } = Constants.PropertyEditor.Alias; + public EditorType Type { get; } = EditorType.PropertyValue; + public string Name { get; } = Constants.PropertyEditor.Name; - public ContentBlocksPropertyEditor( - ContentBlocksModelValueDeserializer deserializer, - ContentBlockUtils utils, - IIOHelper iOHelper, - ILocalizedTextService localizedTextService, - IShortStringHelper shortStringHelper, - IJsonSerializer jsonSerializer, - IPropertyValidationService validationService) - { - _deserializer = deserializer; - _utils = utils; - _iOHelper = iOHelper; - _localizedTextService = localizedTextService; - _shortStringHelper = shortStringHelper; - _jsonSerializer = jsonSerializer; - _validationService = validationService; - } -#elif NET472 - private readonly Lazy _propertyEditorCollection; - private readonly IDataTypeService _dataTypeService; - private readonly ILocalizedTextService _textService; + // Icon cannot be NULL for Umbraco 8.6+, + // it will actually crash the UI. + public string Icon { get; } = "icon-list"; - public ContentBlocksPropertyEditor( - ContentBlocksModelValueDeserializer deserializer, - ContentBlockUtils utils, - Lazy propertyEditorCollection, - IDataTypeService dataTypeService, - ILocalizedTextService textService) - { - _deserializer = deserializer; - _utils = utils; - _propertyEditorCollection = propertyEditorCollection; - _dataTypeService = dataTypeService; - _textService = textService; - } -#endif + public string Group { get; } = "Lists"; - public string Alias { get; } = Constants.PropertyEditor.Alias; - public EditorType Type { get; } = EditorType.PropertyValue; - public string Name { get; } = Constants.PropertyEditor.Name; + public bool IsDeprecated { get; } = false; - // Icon cannot be NULL for Umbraco 8.6+, - // it will actually crash the UI. - public string Icon { get; } = "icon-list"; + public IDictionary DefaultConfiguration => GetConfigurationEditor().DefaultConfiguration; - public string Group { get; } = "Lists"; + public IPropertyIndexValueFactory PropertyIndexValueFactory + => new DefaultPropertyIndexValueFactory(); - public bool IsDeprecated { get; } = false; - public IDictionary DefaultConfiguration { get; } + public IConfigurationEditor GetConfigurationEditor() + => new ContentBlocksConfigurationEditor(_iOHelper, _editorConfigurationParser); - public IPropertyIndexValueFactory PropertyIndexValueFactory - => new DefaultPropertyIndexValueFactory(); + public IDataValueEditor GetValueEditor() + => GetValueEditor(null); - public IConfigurationEditor GetConfigurationEditor() -#if NET5_0 - => new ContentBlocksConfigurationEditor(_iOHelper); -#elif NET472 - => new ContentBlocksConfigurationEditor(); -#endif + public IDataValueEditor GetValueEditor(object? configuration) + { + var validator = new ContentBlocksValidator(_deserializer, _utils, _validationService, _shortStringHelper); - public IDataValueEditor GetValueEditor() - => GetValueEditor(null); + bool hideLabel = (configuration as ContentBlocksConfiguration)?.HideLabel + ?? ContentBlocksConfiguration.DefaultConfiguration.HideLabel; - public IDataValueEditor GetValueEditor(object configuration) + return new ContentBlocksValueEditor(_deserializer, _utils, _localizedTextService, _shortStringHelper, _jsonSerializer) { -#if NET5_0 - var validator = new ContentBlocksValidator(_deserializer, _utils, _validationService, _shortStringHelper); - - bool hideLabel = (configuration as ContentBlocksConfiguration)?.HideLabel - ?? ContentBlocksConfigurationEditor._defaultConfiguration.HideLabel; - - return new ContentBlocksValueEditor(_deserializer, _utils, _localizedTextService, _shortStringHelper, _jsonSerializer) - { - View = Constants.PropertyEditor.ViewPath, - Configuration = configuration, - HideLabel = hideLabel, - ValueType = ValueTypes.Json, - Validators = { validator } - }; -#elif NET472 - var validator = new ContentBlocksValidator(_deserializer, _utils, _propertyEditorCollection.Value, _dataTypeService, _textService); - - bool hideLabel = (configuration as ContentBlocksConfiguration)?.HideLabel - ?? ContentBlocksConfigurationEditor._defaultConfiguration.HideLabel; - - return new ContentBlocksValueEditor(Constants.PropertyEditor.ViewPath, _deserializer, _utils, validator) - { - Configuration = configuration, - HideLabel = hideLabel, - ValueType = ValueTypes.Json, - }; -#endif - } + View = Constants.PropertyEditor.ViewPath, + Configuration = configuration, + HideLabel = hideLabel, + ValueType = ValueTypes.Json, + Validators = { validator } + }; } } diff --git a/src/Perplex.ContentBlocks.Core/PropertyEditor/ContentBlocksValidator.cs b/src/Perplex.ContentBlocks.Core/PropertyEditor/ContentBlocksValidator.cs index 13679b0..b37c197 100644 --- a/src/Perplex.ContentBlocks.Core/PropertyEditor/ContentBlocksValidator.cs +++ b/src/Perplex.ContentBlocks.Core/PropertyEditor/ContentBlocksValidator.cs @@ -1,109 +1,79 @@ using Perplex.ContentBlocks.PropertyEditor.ModelValue; using Perplex.ContentBlocks.Utils; -using System.Collections.Generic; -using System.Linq; -#if NET5_0 using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.PropertyEditors; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; -#elif NET472 -using System.Collections.Specialized; -using System.Web; -using Umbraco.Core; -using Umbraco.Core.Models; -using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Services; -using Umbraco.Web; -using Umbraco.Web.PropertyEditors; -using Umbraco.Web.PropertyEditors.Validation; -#endif -namespace Perplex.ContentBlocks.PropertyEditor +namespace Perplex.ContentBlocks.PropertyEditor; + +public class ContentBlocksValidator : ComplexEditorValidator { - public class ContentBlocksValidator : ComplexEditorValidator - { - private readonly ContentBlockUtils _utils; - private readonly ContentBlocksModelValueDeserializer _deserializer; + private readonly ContentBlockUtils _utils; + private readonly ContentBlocksModelValueDeserializer _deserializer; + + private readonly IShortStringHelper _shortStringHelper; -#if NET5_0 - private readonly IShortStringHelper _shortStringHelper; -#endif + public ContentBlocksValidator( + ContentBlocksModelValueDeserializer deserializer, + ContentBlockUtils utils, + IPropertyValidationService validationService, + IShortStringHelper shortStringHelper) : base(validationService) + { + _deserializer = deserializer; + _utils = utils; + _shortStringHelper = shortStringHelper; + } - public ContentBlocksValidator( - ContentBlocksModelValueDeserializer deserializer, - ContentBlockUtils utils, -#if NET5_0 - IPropertyValidationService validationService, - IShortStringHelper shortStringHelper) : base(validationService) -#elif NET472 - PropertyEditorCollection propertyEditorCollection, - IDataTypeService dataTypeService, - ILocalizedTextService textService) : base(propertyEditorCollection, dataTypeService, textService) -#endif + protected override IEnumerable GetElementTypeValidation(object? value) + { + var modelValue = _deserializer.Deserialize(value?.ToString()); + if (modelValue == null) { - _deserializer = deserializer; - _utils = utils; -#if NET5_0 - _shortStringHelper = shortStringHelper; -#endif + yield break; } - protected override IEnumerable GetElementTypeValidation(object value) + if (modelValue.Header != null && GetValidationModel(modelValue.Header) is ElementTypeValidationModel headerValidationModel) { - var modelValue = _deserializer.Deserialize(value?.ToString()); - if (modelValue == null) - { - yield break; - } - - if (modelValue.Header != null) - { - yield return GetValidationModel(modelValue.Header); - } + yield return headerValidationModel; + } - if (modelValue.Blocks?.Any() == true) + if (modelValue.Blocks?.Any() == true) + { + foreach (var block in modelValue.Blocks) { - foreach (var block in modelValue.Blocks) + if (GetValidationModel(block) is ElementTypeValidationModel blockValidationModel) { - yield return GetValidationModel(block); + yield return blockValidationModel; } } + } - ElementTypeValidationModel GetValidationModel(ContentBlockModelValue blockValue) - { - IDataType dataType = _utils.GetDataType(blockValue.DefinitionId); + ElementTypeValidationModel? GetValidationModel(ContentBlockModelValue blockValue) + { + IDataType? dataType = _utils.GetDataType(blockValue.DefinitionId); - if (dataType == null) - { - return null; - } + if (dataType is null) + { + return null; + } - var validationModel = new ElementTypeValidationModel("", blockValue.Id); + var validationModel = new ElementTypeValidationModel("", blockValue.Id); -#if NET5_0 - var propType = new PropertyType(_shortStringHelper, dataType) { Alias = "content" }; -#elif NET472 - var propType = new PropertyType(dataType) { Alias = "content" }; -#endif - validationModel.AddPropertyTypeValidation(new PropertyTypeValidationModel(propType, blockValue.Content?.ToString())); + var propType = new PropertyType(_shortStringHelper, dataType) { Alias = "content" }; + validationModel.AddPropertyTypeValidation(new PropertyTypeValidationModel(propType, blockValue.Content?.ToString())); - if (blockValue.Variants?.Any() == true) + if (blockValue.Variants?.Any() == true) + { + foreach (var variant in blockValue.Variants) { - foreach (var variant in blockValue.Variants) - { -#if NET5_0 - var variantPropType = new PropertyType(_shortStringHelper, dataType) { Alias = "content_variant_" + variant.Id.ToString("N") }; -#elif NET472 - var variantPropType = new PropertyType(dataType) { Alias = "content_variant_" + variant.Id.ToString("N") }; -#endif - validationModel.AddPropertyTypeValidation(new PropertyTypeValidationModel(variantPropType, variant.Content?.ToString())); - } + var variantPropType = new PropertyType(_shortStringHelper, dataType) { Alias = "content_variant_" + variant.Id.ToString("N") }; + validationModel.AddPropertyTypeValidation(new PropertyTypeValidationModel(variantPropType, variant.Content?.ToString())); } - - return validationModel; } + + return validationModel; } } } diff --git a/src/Perplex.ContentBlocks.Core/PropertyEditor/ContentBlocksValueConverter.cs b/src/Perplex.ContentBlocks.Core/PropertyEditor/ContentBlocksValueConverter.cs index 3c4da38..817ede2 100644 --- a/src/Perplex.ContentBlocks.Core/PropertyEditor/ContentBlocksValueConverter.cs +++ b/src/Perplex.ContentBlocks.Core/PropertyEditor/ContentBlocksValueConverter.cs @@ -1,176 +1,148 @@ -using Perplex.ContentBlocks.Definitions; +using Microsoft.Extensions.DependencyInjection; +using Perplex.ContentBlocks.Definitions; using Perplex.ContentBlocks.PropertyEditor.Configuration; using Perplex.ContentBlocks.PropertyEditor.ModelValue; using Perplex.ContentBlocks.Rendering; using Perplex.ContentBlocks.Variants; -using System; -using System.Collections.Generic; -using System.Linq; - -#if NET5_0 -using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.PropertyEditors; using Umbraco.Cms.Core.PropertyEditors.ValueConverters; -#elif NET472 -using Umbraco.Core; -using Umbraco.Core.Composing; -using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.PropertyEditors; -using Umbraco.Web.PropertyEditors.ValueConverters; -#endif - -namespace Perplex.ContentBlocks.PropertyEditor + +namespace Perplex.ContentBlocks.PropertyEditor; + +public class ContentBlocksValueConverter : PropertyValueConverterBase { - public class ContentBlocksValueConverter : PropertyValueConverterBase + private readonly NestedContentSingleValueConverter _nestedContentSingleValueConverter; + private readonly ContentBlocksModelValueDeserializer _deserializer; + private readonly IContentBlockVariantSelector _variantSelector; + private readonly IServiceProvider _serviceProvider; + + public ContentBlocksValueConverter( + NestedContentSingleValueConverter nestedContentSingleValueConverter, + ContentBlocksModelValueDeserializer deserializer, + IContentBlockVariantSelector variantSelector + , IServiceProvider serviceProvider + ) { - private readonly NestedContentSingleValueConverter _nestedContentSingleValueConverter; - private readonly ContentBlocksModelValueDeserializer _deserializer; - private readonly IContentBlockVariantSelector _variantSelector; -#if NET5_0 - private readonly IServiceProvider _serviceProvider; -#endif - - public ContentBlocksValueConverter( - NestedContentSingleValueConverter nestedContentSingleValueConverter, - ContentBlocksModelValueDeserializer deserializer, - IContentBlockVariantSelector variantSelector -#if NET5_0 - , IServiceProvider serviceProvider -#endif - ) + _nestedContentSingleValueConverter = nestedContentSingleValueConverter; + _deserializer = deserializer; + _variantSelector = variantSelector; + _serviceProvider = serviceProvider; + } + + public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) + { + // We might be able to set this to .Elements. This ensures the cache will be refreshed + // even after publishing any other content, which ensures no issues arise when the block + // contains editors that reference other content (e.g. a ContentPicker). + // However, this requires proper testing first with a wide range of editors. + // Until that time, .Snapshot is the safest option: per request caching. + return PropertyCacheLevel.Snapshot; + } + + public override bool IsConverter(IPublishedPropertyType propertyType) + => propertyType.EditorAlias == Constants.PropertyEditor.Alias; + + public override object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview) + { + ContentBlocksModelValue? modelValue = _deserializer.Deserialize(inter?.ToString()); + if (modelValue is null) { - _nestedContentSingleValueConverter = nestedContentSingleValueConverter; - _deserializer = deserializer; - _variantSelector = variantSelector; -#if NET5_0 - _serviceProvider = serviceProvider; -#endif + return Rendering.ContentBlocks.Empty; } - public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) + var interValue = new ContentBlocksInterValue { - // We might be able to set this to .Elements. This ensures the cache will be refreshed - // even after publishing any other content, which ensures no issues arise when the block - // contains editors that reference other content (e.g. a ContentPicker). - // However, this requires proper testing first with a wide range of editors. - // Until that time, .Snapshot is the safest option: per request caching. - return PropertyCacheLevel.Snapshot; - } + Header = selectBlock(modelValue.Header), + Blocks = modelValue.Blocks?.Select(selectBlock).OfType().ToArray() ?? Array.Empty(), + }; + + var config = propertyType.DataType.ConfigurationAs() ?? ContentBlocksConfiguration.DefaultConfiguration; + + var header = config.Structure.HasFlag(Structure.Header) + ? createViewModel(interValue.Header) + : null; - public override bool IsConverter(IPublishedPropertyType propertyType) - => propertyType.EditorAlias == Constants.PropertyEditor.Alias; + var blocks = config.Structure.HasFlag(Structure.Blocks) + ? interValue.Blocks.Select(createViewModel).OfType().ToArray() + : Enumerable.Empty(); - public override object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview) + return new Rendering.ContentBlocks { - ContentBlocksModelValue modelValue = _deserializer.Deserialize(inter?.ToString()); - if (modelValue == null) + Header = header, + Blocks = blocks + }; + + ContentBlockInterValue? selectBlock(ContentBlockModelValue? original) + { + if (original is null || original.IsDisabled) { - return Rendering.ContentBlocks.Empty; + return null; } - var interValue = new ContentBlocksInterValue + // Start with default content + var block = new ContentBlockInterValue { - Header = selectBlock(modelValue.Header), - Blocks = modelValue.Blocks?.Select(selectBlock).ToList() ?? new List(), + Id = original.Id, + DefinitionId = original.DefinitionId, + LayoutId = original.LayoutId, + Content = original.Content, }; - var config = propertyType.DataType.ConfigurationAs(); + if (_variantSelector.SelectVariant(original, owner, preview) is ContentBlockVariantModelValue variant) + { + // Use variant instead, note we always use the definition + layout specified by the block + block.Id = variant.Id; + block.Content = variant.Content; + }; - var header = config.Structure.HasFlag(Structure.Header) - ? createViewModel(interValue.Header) - : null; + return block; + } - var blocks = config.Structure.HasFlag(Structure.Blocks) - ? interValue.Blocks.Select(createViewModel).Where(vm => vm != null).ToList() - : Enumerable.Empty(); + IContentBlockViewModel? createViewModel(ContentBlockInterValue? block) + { + if (block is null) + { + return null; + } - return new Rendering.ContentBlocks + var definitionRepository = _serviceProvider.GetService(); + if (definitionRepository is null) { - Header = header, - Blocks = blocks - }; + return null; + } - ContentBlockInterValue selectBlock(ContentBlockModelValue original) + IContentBlockDefinition? definition = definitionRepository.GetById(block.DefinitionId); + if (definition is null || definition.Layouts is null || definition.Layouts.Any() == false) { - if (original == null || original.IsDisabled) - { - return null; - } - - // Start with default content - var block = new ContentBlockInterValue - { - Id = original.Id, - DefinitionId = original.DefinitionId, - LayoutId = original.LayoutId, - Content = original.Content, - }; - - if (_variantSelector.SelectVariant(original, owner, preview) is ContentBlockVariantModelValue variant) - { - // Use variant instead, note we always use the definition + layout specified by the block - block.Id = variant.Id; - block.Content = variant.Content; - }; - - return block; + return null; } - IContentBlockViewModel createViewModel(ContentBlockInterValue block) + var layout = definition.Layouts.FirstOrDefault(l => l.Id == block.LayoutId); + if (layout is null) { - if (block == null) - { - return null; - } - -#if NET5_0 - IContentBlockDefinitionRepository definitionRepository = _serviceProvider.GetService(); -#elif NET472 - IContentBlockDefinitionRepository definitionRepository = Current.Factory.GetInstance(); -#endif - if (definitionRepository == null) - { - return null; - } - - IContentBlockDefinition definition = definitionRepository.GetById(block.DefinitionId); - if (definition == null || definition.Layouts == null || definition.Layouts.Any() == false) - { - return null; - } - - IContentBlockLayout layout = definition.Layouts.FirstOrDefault(l => l.Id == block.LayoutId); - if (layout == null) - { - return null; - } - - IPublishedElement content = _nestedContentSingleValueConverter.ConvertIntermediateToObject(owner, propertyType, referenceCacheLevel, block?.Content?.ToString(), preview) as IPublishedElement; - if (content == null) - { - return null; - } - - var contentType = content.GetType(); - var genericViewModelFactoryType = typeof(IContentBlockViewModelFactory<>).MakeGenericType(new[] { contentType }); - -#if NET5_0 - var viewModelFactory = _serviceProvider.GetService(genericViewModelFactoryType) as IContentBlockViewModelFactory; -#elif NET472 - var viewModelFactory = Current.Factory.GetInstance(genericViewModelFactoryType) as IContentBlockViewModelFactory; -#endif - - if (viewModelFactory == null) - { - return null; - } - - return viewModelFactory.Create(content, block.Id, block.DefinitionId, block.LayoutId); + return null; + } + + var content = _nestedContentSingleValueConverter.ConvertIntermediateToObject(owner, propertyType, referenceCacheLevel, block.Content?.ToString(), preview) as IPublishedElement; + if (content is null) + { + return null; + } + + var contentType = content.GetType(); + var genericViewModelFactoryType = typeof(IContentBlockViewModelFactory<>).MakeGenericType(new[] { contentType }); + + var viewModelFactory = _serviceProvider.GetService(genericViewModelFactoryType) as IContentBlockViewModelFactory; + if (viewModelFactory is null) + { + return null; } - } - public override Type GetPropertyValueType(IPublishedPropertyType propertyType) - => typeof(IContentBlocks); + return viewModelFactory.Create(content, block.Id, block.DefinitionId, block.LayoutId); + } } + + public override Type GetPropertyValueType(IPublishedPropertyType propertyType) + => typeof(IContentBlocks); } diff --git a/src/Perplex.ContentBlocks.Core/PropertyEditor/ContentBlocksValueEditor.cs b/src/Perplex.ContentBlocks.Core/PropertyEditor/ContentBlocksValueEditor.cs index bd7157d..9f14e56 100644 --- a/src/Perplex.ContentBlocks.Core/PropertyEditor/ContentBlocksValueEditor.cs +++ b/src/Perplex.ContentBlocks.Core/PropertyEditor/ContentBlocksValueEditor.cs @@ -2,231 +2,194 @@ using Newtonsoft.Json.Linq; using Perplex.ContentBlocks.PropertyEditor.ModelValue; using Perplex.ContentBlocks.Utils; -using System; -using System.Collections.Generic; -using System.Linq; - -#if NET5_0 using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Editors; using Umbraco.Cms.Core.PropertyEditors; using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; -#elif NET472 -using Umbraco.Core.Models; -using Umbraco.Core.Models.Editors; -using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Services; -#endif +namespace Perplex.ContentBlocks.PropertyEditor; -namespace Perplex.ContentBlocks.PropertyEditor +public class ContentBlocksValueEditor : DataValueEditor, IDataValueReference { - public class ContentBlocksValueEditor : DataValueEditor, IDataValueReference + private readonly ContentBlocksModelValueDeserializer _deserializer; + private readonly ContentBlockUtils _utils; + + private readonly IShortStringHelper _shortStringHelper; + + public ContentBlocksValueEditor( + ContentBlocksModelValueDeserializer deserializer, + ContentBlockUtils utils, + ILocalizedTextService localizedTextService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer) : base(localizedTextService, shortStringHelper, jsonSerializer) { - private readonly ContentBlocksModelValueDeserializer _deserializer; - private readonly ContentBlockUtils _utils; - -#if NET5_0 - private readonly IShortStringHelper _shortStringHelper; - - public ContentBlocksValueEditor( - ContentBlocksModelValueDeserializer deserializer, - ContentBlockUtils utils, - ILocalizedTextService localizedTextService, - IShortStringHelper shortStringHelper, - IJsonSerializer jsonSerializer) : base(localizedTextService, shortStringHelper, jsonSerializer) - { - _deserializer = deserializer; - _utils = utils; - _shortStringHelper = shortStringHelper; - } -#elif NET472 - public ContentBlocksValueEditor(string view, ContentBlocksModelValueDeserializer deserializer, ContentBlockUtils utils, params IValueValidator[] validators) : base(view, validators) + _deserializer = deserializer; + _utils = utils; + _shortStringHelper = shortStringHelper; + } + + public override object? FromEditor(ContentPropertyData editorValue, object? currentValue) + { + var json = editorValue.Value?.ToString(); + var modelValue = _deserializer.Deserialize(json); + if (modelValue == null) { - _deserializer = deserializer; - _utils = utils; + return base.FromEditor(editorValue, currentValue); } -#endif - public override object FromEditor(ContentPropertyData editorValue, object currentValue) + if (modelValue.Header is ContentBlockModelValue header) { - string json = editorValue.Value?.ToString(); - var modelValue = _deserializer.Deserialize(json); - if (modelValue == null) - { - return base.FromEditor(editorValue, currentValue); - } + header.Content = FromEditor(header.Content, header.DefinitionId); - if (modelValue.Header is ContentBlockModelValue header) + foreach (var variant in header.Variants ?? Enumerable.Empty()) { - header.Content = FromEditor(header.Content, header.DefinitionId); - - foreach (var variant in header.Variants ?? Enumerable.Empty()) - { - variant.Content = FromEditor(variant.Content, header.DefinitionId); - } + variant.Content = FromEditor(variant.Content, header.DefinitionId); } + } - foreach (var block in modelValue.Blocks ?? Enumerable.Empty()) - { - block.Content = FromEditor(block.Content, block.DefinitionId); + foreach (var block in modelValue.Blocks ?? Enumerable.Empty()) + { + block.Content = FromEditor(block.Content, block.DefinitionId); - foreach (var variant in block.Variants ?? Enumerable.Empty()) - { - variant.Content = FromEditor(variant.Content, block.DefinitionId); - } + foreach (var variant in block.Variants ?? Enumerable.Empty()) + { + variant.Content = FromEditor(variant.Content, block.DefinitionId); } + } - return JsonConvert.SerializeObject(modelValue, Formatting.None); + return JsonConvert.SerializeObject(modelValue, Formatting.None); - JArray FromEditor(JArray blockContent, Guid blockDefinitionId) + JArray? FromEditor(JArray? blockContent, Guid blockDefinitionId) + { + if (blockContent?.ToString() is string content && + !string.IsNullOrWhiteSpace(content) && + _utils.GetDataType(blockDefinitionId) is IDataType dataType && + dataType.Editor?.GetValueEditor() is IDataValueEditor valueEditor) { - if (blockContent?.ToString() is string content && - !string.IsNullOrWhiteSpace(content) && - _utils.GetDataType(blockDefinitionId) is IDataType dataType && - dataType.Editor?.GetValueEditor() is IDataValueEditor valueEditor) - { - var propertyData = new ContentPropertyData(content, dataType.Configuration); + var propertyData = new ContentPropertyData(content, dataType.Configuration); - try - { - var ncJson = valueEditor.FromEditor(propertyData, null)?.ToString(); + try + { + var ncJson = valueEditor.FromEditor(propertyData, null)?.ToString(); - if (!string.IsNullOrWhiteSpace(ncJson)) - { - return JArray.Parse(ncJson); - } - } - catch + if (!string.IsNullOrWhiteSpace(ncJson)) { - return blockContent; + return JArray.Parse(ncJson); } } - - // Fallback: return the original value - return blockContent; + catch + { + return blockContent; + } } + + // Fallback: return the original value + return blockContent; } + } -#if NET5_0 - public override object ToEditor(IProperty property, string culture = null, string segment = null) -#elif NET472 - public override object ToEditor(Property property, IDataTypeService dataTypeService, string culture = null, string segment = null) -#endif + public override object? ToEditor(IProperty property, string? culture = null, string? segment = null) + { + var json = property.GetValue(culture, segment)?.ToString(); + var modelValue = _deserializer.Deserialize(json); + if (modelValue == null) { - string json = property.GetValue(culture, segment)?.ToString(); - var modelValue = _deserializer.Deserialize(json); - if (modelValue == null) - { -#if NET5_0 - return base.ToEditor(property, culture, segment); -#elif NET472 - return base.ToEditor(property, dataTypeService, culture, segment); -#endif - } + return base.ToEditor(property, culture, segment); + } - JArray ToEditor(JArray blockContent, Guid blockDefinitionId) + JArray? ToEditor(JArray? blockContent, Guid blockDefinitionId) + { + if (blockContent?.ToString() is string content && + !string.IsNullOrWhiteSpace(content) && + _utils.GetDataType(blockDefinitionId) is IDataType dataType && + dataType.Editor?.GetValueEditor() is IDataValueEditor valueEditor) { - if (blockContent?.ToString() is string content && - !string.IsNullOrWhiteSpace(content) && - _utils.GetDataType(blockDefinitionId) is IDataType dataType && - dataType.Editor?.GetValueEditor() is IDataValueEditor valueEditor) - { -#if NET5_0 - var ncPropType = new PropertyType(_shortStringHelper, dataType); -#elif NET472 - var ncPropType = new PropertyType(dataType); -#endif - if (culture != null) ncPropType.Variations |= ContentVariation.Culture; - if (segment != null) ncPropType.Variations |= ContentVariation.Segment; - - var ncProperty = new Property(ncPropType); - ncProperty.SetValue(content, culture, segment); - - try - { -#if NET5_0 - if (valueEditor.ToEditor(ncProperty, culture, segment) is object ncValue) -#elif NET472 - if (valueEditor.ToEditor(ncProperty, dataTypeService, culture, segment) is object ncValue) -#endif - { - return JArray.FromObject(ncValue); - }; - } - catch - { - return blockContent; - } - } + var ncPropType = new PropertyType(_shortStringHelper, dataType); + if (culture != null) ncPropType.Variations |= ContentVariation.Culture; + if (segment != null) ncPropType.Variations |= ContentVariation.Segment; - // Fallback: return the original value - return blockContent; - } - - if (modelValue.Header is ContentBlockModelValue header) - { - header.Content = ToEditor(header.Content, header.DefinitionId); + var ncProperty = new Property(ncPropType); + ncProperty.SetValue(content, culture, segment); - foreach (var variant in header.Variants ?? Enumerable.Empty()) + try { - variant.Content = ToEditor(variant.Content, header.DefinitionId); + if (valueEditor.ToEditor(ncProperty, culture, segment) is object ncValue) + { + return JArray.FromObject(ncValue); + }; } - } - - foreach (var block in modelValue.Blocks ?? Enumerable.Empty()) - { - block.Content = ToEditor(block.Content, block.DefinitionId); - - foreach (var variant in block.Variants ?? Enumerable.Empty()) + catch { - variant.Content = ToEditor(variant.Content, block.DefinitionId); + return blockContent; } } - return JObject.FromObject(modelValue); + // Fallback: return the original value + return blockContent; } - public IEnumerable GetReferences(object value) + if (modelValue.Header is ContentBlockModelValue header) { - var result = new List(); - var json = value?.ToString(); + header.Content = ToEditor(header.Content, header.DefinitionId); - var modelValue = _deserializer.Deserialize(json); - if (modelValue is null) - return result; - - if (modelValue.Header != null) + foreach (var variant in header.Variants ?? Enumerable.Empty()) { - result.AddRange(GetReferencesByBlock(modelValue.Header)); + variant.Content = ToEditor(variant.Content, header.DefinitionId); } + } - if (modelValue.Blocks?.Any() is true) + foreach (var block in modelValue.Blocks ?? Enumerable.Empty()) + { + block.Content = ToEditor(block.Content, block.DefinitionId); + + foreach (var variant in block.Variants ?? Enumerable.Empty()) { - foreach (var block in modelValue.Blocks) - { - result.AddRange(GetReferencesByBlock(block)); - } + variant.Content = ToEditor(variant.Content, block.DefinitionId); } + } - IEnumerable GetReferencesByBlock(ContentBlockModelValue model) + return JObject.FromObject(modelValue); + } + + public IEnumerable GetReferences(object? value) + { + var result = new List(); + var json = value?.ToString(); + + var modelValue = _deserializer.Deserialize(json); + if (modelValue is null) + return result; + + if (modelValue.Header != null) + { + result.AddRange(GetReferencesByBlock(modelValue.Header)); + } + + if (modelValue.Blocks?.Any() is true) + { + foreach (var block in modelValue.Blocks) { - if (_utils.GetDataType(model.DefinitionId) is IDataType dataType && dataType.Editor?.GetValueEditor() is IDataValueReference valueEditor) - { - var blockReferences = valueEditor.GetReferences(model.Content?.ToString()); - var variantReferences = model.Variants?.SelectMany(v => valueEditor.GetReferences(v.Content?.ToString())) ?? Enumerable.Empty(); - return blockReferences.Concat(variantReferences); - } - else - { - return Enumerable.Empty(); - } + result.AddRange(GetReferencesByBlock(block)); } + } - return result; + IEnumerable GetReferencesByBlock(ContentBlockModelValue model) + { + if (_utils.GetDataType(model.DefinitionId) is IDataType dataType && dataType.Editor?.GetValueEditor() is IDataValueReference valueEditor) + { + var blockReferences = valueEditor.GetReferences(model.Content?.ToString()); + var variantReferences = model.Variants?.SelectMany(v => valueEditor.GetReferences(v.Content?.ToString())) ?? Enumerable.Empty(); + return blockReferences.Concat(variantReferences); + } + else + { + return Enumerable.Empty(); + } } + + return result; } } diff --git a/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlockInterValue.cs b/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlockInterValue.cs index a1f5407..ea65750 100644 --- a/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlockInterValue.cs +++ b/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlockInterValue.cs @@ -1,13 +1,11 @@ using Newtonsoft.Json.Linq; -using System; -namespace Perplex.ContentBlocks.PropertyEditor.ModelValue +namespace Perplex.ContentBlocks.PropertyEditor.ModelValue; + +public class ContentBlockInterValue { - public class ContentBlockInterValue - { - public Guid Id { get; set; } - public Guid DefinitionId { get; set; } - public Guid LayoutId { get; set; } - public JArray Content { get; set; } - } + public Guid Id { get; set; } + public Guid DefinitionId { get; set; } + public Guid LayoutId { get; set; } + public JArray? Content { get; set; } } diff --git a/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlockModelValue.cs b/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlockModelValue.cs index 4623b2b..573c79a 100644 --- a/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlockModelValue.cs +++ b/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlockModelValue.cs @@ -1,38 +1,35 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; -namespace Perplex.ContentBlocks.PropertyEditor.ModelValue +namespace Perplex.ContentBlocks.PropertyEditor.ModelValue; + +public class ContentBlockModelValue { - public class ContentBlockModelValue - { - [JsonProperty("id")] - public Guid Id { get; set; } - - [JsonProperty("definitionId")] - public Guid DefinitionId { get; set; } - - [JsonProperty("layoutId")] - public Guid LayoutId { get; set; } - - /// - /// Indien dit blok uit een preset komt zal dit een waarde hebben - /// en wijzen naar de betreffende IContentBlockPreset - /// - [JsonProperty("presetId")] - public Guid? PresetId { get; set; } - - [JsonProperty("isDisabled")] - public bool IsDisabled { get; set; } - - /// - /// JSON NestedContent - /// - [JsonProperty("content")] - public JArray Content { get; set; } - - [JsonProperty("variants")] - public List Variants { get; set; } - } + [JsonProperty("id")] + public Guid Id { get; set; } + + [JsonProperty("definitionId")] + public Guid DefinitionId { get; set; } + + [JsonProperty("layoutId")] + public Guid LayoutId { get; set; } + + /// + /// Indien dit blok uit een preset komt zal dit een waarde hebben + /// en wijzen naar de betreffende IContentBlockPreset + /// + [JsonProperty("presetId")] + public Guid? PresetId { get; set; } + + [JsonProperty("isDisabled")] + public bool IsDisabled { get; set; } + + /// + /// JSON NestedContent + /// + [JsonProperty("content")] + public JArray? Content { get; set; } + + [JsonProperty("variants")] + public List? Variants { get; set; } } diff --git a/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlockVariantModelValue.cs b/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlockVariantModelValue.cs index bb2508f..48b753e 100644 --- a/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlockVariantModelValue.cs +++ b/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlockVariantModelValue.cs @@ -1,21 +1,19 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using System; -namespace Perplex.ContentBlocks.PropertyEditor.ModelValue +namespace Perplex.ContentBlocks.PropertyEditor.ModelValue; + +public class ContentBlockVariantModelValue { - public class ContentBlockVariantModelValue - { - [JsonProperty("id")] - public Guid Id { get; set; } + [JsonProperty("id")] + public Guid Id { get; set; } - [JsonProperty("alias")] - public string Alias { get; set; } + [JsonProperty("alias")] + public string Alias { get; set; } = ""; - /// - /// JSON NestedContent - /// - [JsonProperty("content")] - public JArray Content { get; set; } - } + /// + /// JSON NestedContent + /// + [JsonProperty("content")] + public JArray? Content { get; set; } } diff --git a/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlocksInterValue.cs b/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlocksInterValue.cs index ed2d596..3ca9617 100644 --- a/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlocksInterValue.cs +++ b/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlocksInterValue.cs @@ -1,10 +1,9 @@ -using System.Collections.Generic; +namespace Perplex.ContentBlocks.PropertyEditor.ModelValue; -namespace Perplex.ContentBlocks.PropertyEditor.ModelValue +public class ContentBlocksInterValue { - public class ContentBlocksInterValue - { - public ContentBlockInterValue Header { get; set; } - public List Blocks { get; set; } - } + public ContentBlockInterValue? Header { get; set; } + + public IEnumerable Blocks { get; set; } + = Array.Empty(); } diff --git a/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlocksModelValue.cs b/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlocksModelValue.cs index a0f711c..1a230e6 100644 --- a/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlocksModelValue.cs +++ b/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlocksModelValue.cs @@ -1,17 +1,15 @@ using Newtonsoft.Json; -using System.Collections.Generic; -namespace Perplex.ContentBlocks.PropertyEditor.ModelValue +namespace Perplex.ContentBlocks.PropertyEditor.ModelValue; + +public class ContentBlocksModelValue { - public class ContentBlocksModelValue - { - [JsonProperty("version")] - public int Version { get; set; } + [JsonProperty("version")] + public int Version { get; set; } - [JsonProperty("header")] - public ContentBlockModelValue Header { get; set; } + [JsonProperty("header")] + public ContentBlockModelValue? Header { get; set; } - [JsonProperty("blocks")] - public List Blocks { get; set; } - } + [JsonProperty("blocks")] + public List? Blocks { get; set; } } diff --git a/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlocksModelValueComposer.cs b/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlocksModelValueComposer.cs index 8a2af8a..a2dc3e5 100644 --- a/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlocksModelValueComposer.cs +++ b/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlocksModelValueComposer.cs @@ -1,34 +1,16 @@ -#if NET5_0 -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.Composing; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Notifications; -#elif NET472 -using Umbraco.Core; -using Umbraco.Core.Composing; -#endif -namespace Perplex.ContentBlocks.PropertyEditor.ModelValue +namespace Perplex.ContentBlocks.PropertyEditor.ModelValue; + +public class ContentBlocksModelValueComposer : IComposer { -#if NET5_0 - public class ContentBlocksModelValueComposer : IComposer - { - public void Compose(IUmbracoBuilder builder) - { - builder.Services.AddSingleton(); - builder.AddNotificationHandler(); - } - } -#elif NET472 - [RuntimeLevel(MinLevel = RuntimeLevel.Boot)] - public class ContentBlocksModelValueComposer : IUserComposer + public void Compose(IUmbracoBuilder builder) { - public void Compose(Composition composition) - { - composition.Register(Lifetime.Singleton); - composition.Components().Append(); - } + builder.Services.AddSingleton(); + builder.AddNotificationHandler(); } -#endif } diff --git a/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlocksModelValueCopyingHandler.cs b/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlocksModelValueCopyingHandler.cs index 11586de..990b48d 100644 --- a/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlocksModelValueCopyingHandler.cs +++ b/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlocksModelValueCopyingHandler.cs @@ -1,140 +1,141 @@ -#if NET5_0 -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using System; -using System.Linq; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Notifications; -namespace Perplex.ContentBlocks.PropertyEditor.ModelValue +namespace Perplex.ContentBlocks.PropertyEditor.ModelValue; + +public class ContentBlocksModelValueCopyingHandler : INotificationHandler { - public class ContentBlocksModelValueCopyingHandler : INotificationHandler - { - private readonly ILogger _logger; + private readonly ILogger _logger; - public ContentBlocksModelValueCopyingHandler(ILogger logger) - { - _logger = logger; - } + public ContentBlocksModelValueCopyingHandler(ILogger logger) + { + _logger = logger; + } - public void Handle(ContentCopyingNotification notification) - => UpdateContentBlocksKeys(notification.Copy); + public void Handle(ContentCopyingNotification notification) + => UpdateContentBlocksKeys(notification.Copy); - private void UpdateContentBlocksKeys(IContent entity) + private void UpdateContentBlocksKeys(IContent entity) + { + try { - try + var properties = entity.Properties.Where(p => p.PropertyType.PropertyEditorAlias == Constants.PropertyEditor.Alias); + foreach (var prop in properties) { - var properties = entity.Properties.Where(p => p.PropertyType.PropertyEditorAlias == Constants.PropertyEditor.Alias); - foreach (var prop in properties) + // Update all property values -- i.e. all variants + foreach (var propValue in prop.Values) { - // Update all property values -- i.e. all variants - foreach (var propValue in prop.Values) - { - string culture = propValue.Culture; - string segment = propValue.Segment; + if (propValue is null) continue; - string value = propValue.EditedValue as string; - if (string.IsNullOrEmpty(value)) - { - continue; - } + string? culture = propValue.Culture; + string? segment = propValue.Segment; - var contentBlocks = JsonConvert.DeserializeObject(value); + string? value = propValue.EditedValue as string; + if (string.IsNullOrEmpty(value)) + { + continue; + } - var header = contentBlocks.Value("header"); - if (header != null) - { - UpdateContentBlockKeys(header); - } + var contentBlocks = JsonConvert.DeserializeObject(value); + + var header = contentBlocks?.Value("header"); + if (header is not null) + { + UpdateContentBlockKeys(header); + } - foreach (JObject block in contentBlocks.Value("blocks")) + if (contentBlocks?.Value("blocks") is JArray blocks) + { + foreach (JObject block in blocks) { UpdateContentBlockKeys(block); } - - prop.SetValue(JsonConvert.SerializeObject(contentBlocks), culture: culture, segment: segment); } + + prop.SetValue(JsonConvert.SerializeObject(contentBlocks), culture: culture, segment: segment); } } - catch (Exception ex) - { - _logger.LogError(ex, "Failed to update ContentBlock keys and IDs while copying a node."); - } } - - private void UpdateContentBlockKeys(JObject block) + catch (Exception ex) { - block["id"] = Guid.NewGuid(); + _logger.LogError(ex, "Failed to update ContentBlock keys and IDs while copying a node."); + } + } - var nestedContentItems = block.Value("content"); + private void UpdateContentBlockKeys(JObject block) + { + block["id"] = Guid.NewGuid(); + if (block.Value("content") is JArray nestedContentItems) + { foreach (var nestedContentItem in nestedContentItems) { UpdateNestedContentKey(nestedContentItem as JObject); } + } - var variants = block.Value("variants"); - if (variants != null) + var variants = block.Value("variants"); + if (variants != null) + { + foreach (JObject variant in variants) { - foreach (JObject variant in variants) - { - UpdateContentBlockKeys(variant); - } + UpdateContentBlockKeys(variant); } } + } - private void UpdateNestedContentKey(JObject nestedContent) + private void UpdateNestedContentKey(JObject? nestedContent) + { + if (nestedContent is null || nestedContent["key"] == null) { - if (nestedContent == null || nestedContent["key"] == null) - { - return; - } + return; + } - nestedContent["key"] = Guid.NewGuid(); + nestedContent["key"] = Guid.NewGuid(); - // Also update any nested Nested Content items inside this nestedContent - foreach (var property in nestedContent.Properties()) + // Also update any nested Nested Content items inside this nestedContent + foreach (var property in nestedContent.Properties()) + { + // NestedContent stores nested NestedContent as strings rather than arrays for some reason, + // i.e. if one of the properties inside this object is also + // a NestedContent its value will be a string that looks like this: + // "[{ \"key\": \" ... \" }]" instead of a real array like [{ "key": "..." }] + // This means we have to actually parse each value to check if it's a JArray or not. + if ( + property.Value is JValue value && + value.Type == JTokenType.String && + value.ToString() is string rawValue && + rawValue.TrimStart().StartsWith("[") + ) { - // NestedContent stores nested NestedContent as strings rather than arrays for some reason, - // i.e. if one of the properties inside this object is also - // a NestedContent its value will be a string that looks like this: - // "[{ \"key\": \" ... \" }]" instead of a real array like [{ "key": "..." }] - // This means we have to actually parse each value to check if it's a JArray or not. - if ( - property.Value is JValue value && - value.Type == JTokenType.String && - value.ToString() is string rawValue && - rawValue.TrimStart().StartsWith("[") - ) + try { - try - { - var array = JArray.Parse(value.ToString()); + var array = JArray.Parse(value.ToString()); - if (IsNestedContentValue(array)) + if (IsNestedContentValue(array)) + { + foreach (var child in array.Children()) { - foreach (var child in array.Children()) - { - UpdateNestedContentKey(child); - } - - nestedContent[property.Name] = JsonConvert.SerializeObject(array); + UpdateNestedContentKey(child); } - } - catch (JsonReaderException) - { - // Not actually an Array -- just ignore + + nestedContent[property.Name] = JsonConvert.SerializeObject(array); } } + catch (JsonReaderException) + { + // Not actually an Array -- just ignore + } } } + } - private bool IsNestedContentValue(JArray value) - { - return value.First is JObject obj && obj["key"] != null && obj["ncContentTypeAlias"] != null; - } + private bool IsNestedContentValue(JArray value) + { + return value.First is JObject obj && obj["key"] != null && obj["ncContentTypeAlias"] != null; } } -#endif diff --git a/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlocksModelValueDeserializer.cs b/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlocksModelValueDeserializer.cs index 244adc8..f21bbac 100644 --- a/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlocksModelValueDeserializer.cs +++ b/src/Perplex.ContentBlocks.Core/PropertyEditor/ModelValue/ContentBlocksModelValueDeserializer.cs @@ -1,57 +1,55 @@ using Newtonsoft.Json; -using System.Collections.Generic; -namespace Perplex.ContentBlocks.PropertyEditor.ModelValue +namespace Perplex.ContentBlocks.PropertyEditor.ModelValue; + +public class ContentBlocksModelValueDeserializer { - public class ContentBlocksModelValueDeserializer + /// + /// Deserializes the given JSON to an instance of ContentBlocksModelValue + /// + /// JSON to deserialize + /// + public ContentBlocksModelValue? Deserialize(string? json) { - /// - /// Deserializes the given JSON to an instance of ContentBlocksModelValue - /// - /// JSON to deserialize - /// - public ContentBlocksModelValue Deserialize(string json) + if (string.IsNullOrWhiteSpace(json)) { - if (string.IsNullOrWhiteSpace(json)) - { - return null; - } - - try - { - var modelValue = JsonConvert.DeserializeObject(json); + return null; + } - return MaybeTransformData(modelValue); - } - catch - { - return null; - } + try + { + var modelValue = JsonConvert.DeserializeObject(json); + if (modelValue is null) return null; + return MaybeTransformData(modelValue); } + catch + { + return null; + } + } - private ContentBlocksModelValue MaybeTransformData(ContentBlocksModelValue modelValue) + private static ContentBlocksModelValue MaybeTransformData(ContentBlocksModelValue modelValue) + { + if (modelValue.Version < 3) { - if (modelValue.Version < 3) + // We added a Variants property in v3, for any older version we will ensure this property becomes an empty Array. + if (modelValue.Header != null && modelValue.Header.Variants == null) { - // We added a Variants property in v3, for any older version we will ensure this property becomes an empty Array. - if (modelValue.Header != null && modelValue.Header.Variants == null) - { - modelValue.Header.Variants = new List(); - } + modelValue.Header.Variants = new List(); + } - if (modelValue.Blocks != null) + if (modelValue.Blocks != null) + { + foreach (var block in modelValue.Blocks) { - foreach (var block in modelValue.Blocks) + if (block.Variants == null) { - if (block.Variants == null) - { - block.Variants = new List(); - } + block.Variants = new List(); } } } - - return modelValue; } + + return modelValue; } } diff --git a/src/Perplex.ContentBlocks.Core/Providers/ContentBlockProvidersComposer.cs b/src/Perplex.ContentBlocks.Core/Providers/ContentBlockProvidersComposer.cs index c33034e..9cf52be 100644 --- a/src/Perplex.ContentBlocks.Core/Providers/ContentBlockProvidersComposer.cs +++ b/src/Perplex.ContentBlocks.Core/Providers/ContentBlockProvidersComposer.cs @@ -1,31 +1,14 @@ -#if NET5_0 -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.Composing; using Umbraco.Cms.Core.DependencyInjection; -#elif NET472 -using Umbraco.Core; -using Umbraco.Core.Composing; -#endif -namespace Perplex.ContentBlocks.Providers +namespace Perplex.ContentBlocks.Providers; + +public class ContentBlockProvidersComposer : IComposer { -#if NET5_0 - public class ContentBlockProvidersComposer : IComposer - { - public void Compose(IUmbracoBuilder builder) - { - builder.Services.AddSingleton(); - } - } -#elif NET472 - [RuntimeLevel(MinLevel = RuntimeLevel.Run)] - public class ContentBlockProvidersComposer : IUserComposer + public void Compose(IUmbracoBuilder builder) { - public void Compose(Composition composition) - { - composition.Register(Lifetime.Singleton); - } + builder.Services.AddSingleton(); } -#endif } diff --git a/src/Perplex.ContentBlocks.Core/Providers/DocumentTypeAliasProvider.cs b/src/Perplex.ContentBlocks.Core/Providers/DocumentTypeAliasProvider.cs index 50e1b6f..7271996 100644 --- a/src/Perplex.ContentBlocks.Core/Providers/DocumentTypeAliasProvider.cs +++ b/src/Perplex.ContentBlocks.Core/Providers/DocumentTypeAliasProvider.cs @@ -1,32 +1,25 @@ -#if NET5_0 -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services; -#elif NET472 -using Umbraco.Core.Models; -using Umbraco.Core.Services; -#endif +namespace Perplex.ContentBlocks.Providers; -namespace Perplex.ContentBlocks.Providers +public class DocumentTypeAliasProvider : IDocumentTypeAliasProvider { - public class DocumentTypeAliasProvider : IDocumentTypeAliasProvider + private readonly IContentService _contentService; + + public DocumentTypeAliasProvider(IContentService contentService) { - private readonly IContentService _contentService; + _contentService = contentService; + } - public DocumentTypeAliasProvider(IContentService contentService) + public string? GetDocumentTypeAlias(int pageId) + { + IContent? content = _contentService.GetById(pageId); + if (content == null) { - _contentService = contentService; + return null; } - public string GetDocumentTypeAlias(int pageId) - { - IContent content = _contentService.GetById(pageId); - if (content == null) - { - return null; - } - - return content.ContentType?.Alias; - } + return content.ContentType?.Alias; } } diff --git a/src/Perplex.ContentBlocks.Core/Providers/IDocumentTypeAliasProvider.cs b/src/Perplex.ContentBlocks.Core/Providers/IDocumentTypeAliasProvider.cs index 1072c7f..de74095 100644 --- a/src/Perplex.ContentBlocks.Core/Providers/IDocumentTypeAliasProvider.cs +++ b/src/Perplex.ContentBlocks.Core/Providers/IDocumentTypeAliasProvider.cs @@ -1,7 +1,6 @@ -namespace Perplex.ContentBlocks.Providers +namespace Perplex.ContentBlocks.Providers; + +public interface IDocumentTypeAliasProvider { - public interface IDocumentTypeAliasProvider - { - string GetDocumentTypeAlias(int pageId); - } + string? GetDocumentTypeAlias(int pageId); } diff --git a/src/Perplex.ContentBlocks.Core/Rendering/ContentBlockRenderer.cs b/src/Perplex.ContentBlocks.Core/Rendering/ContentBlockRenderer.cs index 9748eb3..6ab60d7 100644 --- a/src/Perplex.ContentBlocks.Core/Rendering/ContentBlockRenderer.cs +++ b/src/Perplex.ContentBlocks.Core/Rendering/ContentBlockRenderer.cs @@ -1,196 +1,103 @@ -using Perplex.ContentBlocks.Definitions; +using Microsoft.AspNetCore.Html; +using Perplex.ContentBlocks.Definitions; using Perplex.ContentBlocks.Preview; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -#if NET5_0 -using Microsoft.AspNetCore.Html; -using Microsoft.AspNetCore.Mvc.Rendering; -#elif NET472 -using System.Web; -using System.Web.Mvc; -using System.Web.Mvc.Html; -#endif - -namespace Perplex.ContentBlocks.Rendering + +namespace Perplex.ContentBlocks.Rendering; + +public class ContentBlockRenderer : IContentBlockRenderer { - public class ContentBlockRenderer : IContentBlockRenderer + private readonly IContentBlockDefinitionRepository _definitionRepository; + private readonly bool _isPreview; + + public ContentBlockRenderer( + IContentBlockDefinitionRepository definitionRepository, + IPreviewModeProvider previewModeProvider) { - private readonly IContentBlockDefinitionRepository _definitionRepository; - private readonly bool _isPreview; + _definitionRepository = definitionRepository; + _isPreview = previewModeProvider.IsPreviewMode; + } - public ContentBlockRenderer( - IContentBlockDefinitionRepository definitionRepository, - IPreviewModeProvider previewModeProvider) + public async Task Render(IContentBlocks? contentBlocks, RenderPartialViewAsync renderPartialViewAsync) + { + if (contentBlocks == null) { - _definitionRepository = definitionRepository; - _isPreview = previewModeProvider.IsPreviewMode; + return HtmlString.Empty; } -#if NET5_0 - - public async Task Render(IContentBlocks contentBlocks, RenderPartialViewAsync renderPartialViewAsync) - { - if (contentBlocks == null) - { - return HtmlString.Empty; - } - - var builder = new HtmlContentBuilder(); - - var blocksHtml = await Task.WhenAll( - RenderHeader(contentBlocks, renderPartialViewAsync), - RenderBlocks(contentBlocks, renderPartialViewAsync) - ); - - foreach (var blockHtml in blocksHtml) - { - builder.AppendHtml(blockHtml); - } + var builder = new HtmlContentBuilder(); - return builder; - } - - public async Task RenderBlocks(IContentBlocks contentBlocks, RenderPartialViewAsync renderPartialViewAsync) - => await RenderBlocks(contentBlocks?.Blocks, renderPartialViewAsync); + var blocksHtml = await Task.WhenAll( + RenderHeader(contentBlocks, renderPartialViewAsync), + RenderBlocks(contentBlocks, renderPartialViewAsync) + ); - public async Task RenderBlocks(IEnumerable contentBlocks, RenderPartialViewAsync renderPartialViewAsync) + foreach (var blockHtml in blocksHtml) { - if (contentBlocks?.Any() != true) - { - return HtmlString.Empty; - } - - var builder = new HtmlContentBuilder(); - - var blocksHtml = await Task.WhenAll(contentBlocks.Select(block => RenderBlock(block, renderPartialViewAsync))); - - foreach (var blockHtml in blocksHtml) - { - builder.AppendHtml(blockHtml); - } - - return builder; + builder.AppendHtml(blockHtml); } - public async Task RenderBlock(IContentBlockViewModel contentBlockViewModel, RenderPartialViewAsync renderPartialViewAsync) - { - if (contentBlockViewModel == null) - { - return HtmlString.Empty; - } - - string viewPath = GetViewPath(contentBlockViewModel.DefinitionId, contentBlockViewModel.LayoutId); - if (string.IsNullOrEmpty(viewPath)) - { - return HtmlString.Empty; - } - - IHtmlContent contentBlockHtml = await renderPartialViewAsync(viewPath, contentBlockViewModel); - - var builder = new HtmlContentBuilder(); - - if (_isPreview) - { - // Preview mode: add block id for scroll synchronisation - string blockIdAnchor = $""; - builder.AppendHtml(blockIdAnchor); - } + return builder; + } - builder.AppendHtml(contentBlockHtml); + public async Task RenderBlocks(IContentBlocks? contentBlocks, RenderPartialViewAsync renderPartialViewAsync) + => await RenderBlocks(contentBlocks?.Blocks, renderPartialViewAsync); - return builder; + public async Task RenderBlocks(IEnumerable? contentBlocks, RenderPartialViewAsync renderPartialViewAsync) + { + if (contentBlocks?.Any() != true) + { + return HtmlString.Empty; } - public async Task RenderHeader(IContentBlocks contentBlocks, RenderPartialViewAsync renderPartialViewAsync) - => await RenderBlock(contentBlocks?.Header, renderPartialViewAsync); + var builder = new HtmlContentBuilder(); -#elif NET472 + var blocksHtml = await Task.WhenAll(contentBlocks.Select(block => RenderBlock(block, renderPartialViewAsync))); - public IHtmlString Render(IContentBlocks contentBlocks, HtmlHelper htmlHelper) + foreach (var blockHtml in blocksHtml) { - if (contentBlocks == null) - { - return MvcHtmlString.Empty; - } - - StringBuilder sb = new StringBuilder(); + builder.AppendHtml(blockHtml); + } - sb.Append(RenderHeader(contentBlocks, htmlHelper)); - sb.Append(RenderBlocks(contentBlocks, htmlHelper)); + return builder; + } - return new HtmlString(sb.ToString()); + public async Task RenderBlock(IContentBlockViewModel? contentBlockViewModel, RenderPartialViewAsync renderPartialViewAsync) + { + if (contentBlockViewModel == null) + { + return HtmlString.Empty; } - public IHtmlString RenderHeader(IContentBlocks contentBlocks, HtmlHelper htmlHelper) + var viewPath = GetViewPath(contentBlockViewModel.DefinitionId, contentBlockViewModel.LayoutId); + if (string.IsNullOrEmpty(viewPath)) { - if (contentBlocks?.Header == null) - { - return MvcHtmlString.Empty; - } - - return RenderBlock(contentBlocks.Header, htmlHelper); + return HtmlString.Empty; } - public IHtmlString RenderBlocks(IContentBlocks contentBlocks, HtmlHelper htmlHelper) - => RenderBlocks(contentBlocks?.Blocks, htmlHelper); + IHtmlContent contentBlockHtml = await renderPartialViewAsync(viewPath, contentBlockViewModel); - public IHtmlString RenderBlock(IContentBlockViewModel contentBlockViewModel, HtmlHelper htmlHelper) - { - if (contentBlockViewModel == null) - { - return MvcHtmlString.Empty; - } - - string viewPath = GetViewPath(contentBlockViewModel.DefinitionId, contentBlockViewModel.LayoutId); - if (string.IsNullOrEmpty(viewPath)) - { - return MvcHtmlString.Empty; - } - - IHtmlString contentBlockHtml = htmlHelper.Partial(viewPath, contentBlockViewModel); - - if (!_isPreview) - { - return contentBlockHtml; - } - else - { - // Preview mode: add block id for scroll synchronisation - string blockIdAnchor = $""; - return new MvcHtmlString(blockIdAnchor + contentBlockHtml); - } - } + var builder = new HtmlContentBuilder(); - public IHtmlString RenderBlocks(IEnumerable contentBlocks, HtmlHelper htmlHelper) + if (_isPreview) { - if (contentBlocks?.Any() != true) - { - return MvcHtmlString.Empty; - } - - StringBuilder sb = new StringBuilder(); + // Preview mode: add block id for scroll synchronisation + string blockIdAnchor = $""; + builder.AppendHtml(blockIdAnchor); + } - foreach (var block in contentBlocks) - { - IHtmlString blockHtml = RenderBlock(block, htmlHelper); - sb.Append(blockHtml.ToString()); - } + builder.AppendHtml(contentBlockHtml); - return new HtmlString(sb.ToString()); - } + return builder; + } -#endif + public async Task RenderHeader(IContentBlocks? contentBlocks, RenderPartialViewAsync renderPartialViewAsync) + => await RenderBlock(contentBlocks?.Header, renderPartialViewAsync); - private string GetViewPath(Guid definitionId, Guid layoutId) - { - var definition = _definitionRepository.GetById(definitionId); - return definition - ?.Layouts?.FirstOrDefault(l => l.Id == layoutId) - ?.ViewPath; - } + private string? GetViewPath(Guid definitionId, Guid layoutId) + { + var definition = _definitionRepository.GetById(definitionId); + return definition + ?.Layouts?.FirstOrDefault(l => l.Id == layoutId) + ?.ViewPath; } } diff --git a/src/Perplex.ContentBlocks.Core/Rendering/ContentBlockViewModel.cs b/src/Perplex.ContentBlocks.Core/Rendering/ContentBlockViewModel.cs index 2456857..3ce972f 100644 --- a/src/Perplex.ContentBlocks.Core/Rendering/ContentBlockViewModel.cs +++ b/src/Perplex.ContentBlocks.Core/Rendering/ContentBlockViewModel.cs @@ -1,28 +1,23 @@ using System; -#if NET5_0 using Umbraco.Cms.Core.Models.PublishedContent; -#elif NET472 -using Umbraco.Core.Models.PublishedContent; -#endif -namespace Perplex.ContentBlocks.Rendering +namespace Perplex.ContentBlocks.Rendering; + +public class ContentBlockViewModel : IContentBlockViewModel { - public class ContentBlockViewModel : IContentBlockViewModel - { - public Guid Id { get; } + public Guid Id { get; } - public Guid DefinitionId { get; } + public Guid DefinitionId { get; } - public Guid LayoutId { get; } + public Guid LayoutId { get; } - public IPublishedElement Content { get; } + public IPublishedElement Content { get; } - public ContentBlockViewModel(IPublishedElement content, Guid definitionId, Guid layoutId) - { - Content = content; - DefinitionId = definitionId; - LayoutId = layoutId; - } + public ContentBlockViewModel(IPublishedElement content, Guid definitionId, Guid layoutId) + { + Content = content; + DefinitionId = definitionId; + LayoutId = layoutId; } } diff --git a/src/Perplex.ContentBlocks.Core/Rendering/ContentBlockViewModelFactory{T}.cs b/src/Perplex.ContentBlocks.Core/Rendering/ContentBlockViewModelFactory{T}.cs index b731269..3fa2200 100644 --- a/src/Perplex.ContentBlocks.Core/Rendering/ContentBlockViewModelFactory{T}.cs +++ b/src/Perplex.ContentBlocks.Core/Rendering/ContentBlockViewModelFactory{T}.cs @@ -1,19 +1,15 @@ -using System; -#if NET5_0 -using Umbraco.Cms.Core.Models.PublishedContent; -#elif NET472 -using Umbraco.Core.Models.PublishedContent; -#endif +using Umbraco.Cms.Core.Models.PublishedContent; +namespace Perplex.ContentBlocks.Rendering; -namespace Perplex.ContentBlocks.Rendering +public class ContentBlockViewModelFactory : IContentBlockViewModelFactory where TContent : class, IPublishedElement { - public class ContentBlockViewModelFactory : IContentBlockViewModelFactory where TContent : class, IPublishedElement - { - public virtual IContentBlockViewModel Create(TContent content, Guid id, Guid definitionId, Guid layoutId) - => new ContentBlockViewModel(content, id, definitionId, layoutId); + public virtual IContentBlockViewModel Create(TContent content, Guid id, Guid definitionId, Guid layoutId) + => new ContentBlockViewModel(content, id, definitionId, layoutId); - IContentBlockViewModel IContentBlockViewModelFactory.Create(IPublishedElement content, Guid id, Guid definitionId, Guid layoutId) - => Create(content as TContent, id, definitionId, layoutId); + IContentBlockViewModel? IContentBlockViewModelFactory.Create(IPublishedElement content, Guid id, Guid definitionId, Guid layoutId) + { + if (content is not TContent typedContent) return null; + return Create(typedContent, id, definitionId, layoutId); } } diff --git a/src/Perplex.ContentBlocks.Core/Rendering/ContentBlockViewModel{T}.cs b/src/Perplex.ContentBlocks.Core/Rendering/ContentBlockViewModel{T}.cs index c3f59ee..64cc045 100644 --- a/src/Perplex.ContentBlocks.Core/Rendering/ContentBlockViewModel{T}.cs +++ b/src/Perplex.ContentBlocks.Core/Rendering/ContentBlockViewModel{T}.cs @@ -1,31 +1,26 @@ using System; -#if NET5_0 using Umbraco.Cms.Core.Models.PublishedContent; -#elif NET472 -using Umbraco.Core.Models.PublishedContent; -#endif -namespace Perplex.ContentBlocks.Rendering +namespace Perplex.ContentBlocks.Rendering; + +public class ContentBlockViewModel : IContentBlockViewModel where TContent : IPublishedElement { - public class ContentBlockViewModel : IContentBlockViewModel where TContent : IPublishedElement - { - public Guid Id { get; } + public Guid Id { get; } - public Guid DefinitionId { get; set; } + public Guid DefinitionId { get; set; } - public Guid LayoutId { get; set; } + public Guid LayoutId { get; set; } - public TContent Content { get; set; } + public TContent Content { get; set; } - IPublishedElement IContentBlockViewModel.Content => Content; + IPublishedElement IContentBlockViewModel.Content => Content; - public ContentBlockViewModel(TContent content, Guid id, Guid definitionId, Guid layoutId) - { - Id = id; - DefinitionId = definitionId; - LayoutId = layoutId; - Content = content; - } + public ContentBlockViewModel(TContent content, Guid id, Guid definitionId, Guid layoutId) + { + Id = id; + DefinitionId = definitionId; + LayoutId = layoutId; + Content = content; } } diff --git a/src/Perplex.ContentBlocks.Core/Rendering/ContentBlocks.cs b/src/Perplex.ContentBlocks.Core/Rendering/ContentBlocks.cs index fc7e5f3..5b12229 100644 --- a/src/Perplex.ContentBlocks.Core/Rendering/ContentBlocks.cs +++ b/src/Perplex.ContentBlocks.Core/Rendering/ContentBlocks.cs @@ -1,13 +1,11 @@ -using System.Collections.Generic; +namespace Perplex.ContentBlocks.Rendering; -namespace Perplex.ContentBlocks.Rendering +public class ContentBlocks : IContentBlocks { - public class ContentBlocks : IContentBlocks - { - public static readonly IContentBlocks Empty = new ContentBlocks(); + public static readonly IContentBlocks Empty = new ContentBlocks(); - public IContentBlockViewModel Header { get; set; } + public IContentBlockViewModel? Header { get; set; } - public IEnumerable Blocks { get; set; } - } + public IEnumerable Blocks { get; set; } + = Array.Empty(); } diff --git a/src/Perplex.ContentBlocks.Core/Rendering/ContentBlocksRenderingComposer.cs b/src/Perplex.ContentBlocks.Core/Rendering/ContentBlocksRenderingComposer.cs index 239d1d9..61a6fdc 100644 --- a/src/Perplex.ContentBlocks.Core/Rendering/ContentBlocksRenderingComposer.cs +++ b/src/Perplex.ContentBlocks.Core/Rendering/ContentBlocksRenderingComposer.cs @@ -1,43 +1,20 @@ using Microsoft.Extensions.DependencyInjection; -#if NET5_0 using Umbraco.Cms.Core.Composing; using Umbraco.Cms.Core.DependencyInjection; -#elif NET472 -using Umbraco.Core; -using Umbraco.Core.Composing; -#endif -namespace Perplex.ContentBlocks.Rendering -{ -#if NET5_0 - public class ContentBlocksRenderingComposer : IComposer - { - public void Compose(IUmbracoBuilder builder) - { - // Renderer - builder.Services.AddScoped(); +namespace Perplex.ContentBlocks.Rendering; - // General View Model factory - builder.Services.AddSingleton( - typeof(IContentBlockViewModelFactory<>), - typeof(ContentBlockViewModelFactory<>)); - } - } -#elif NET472 - [RuntimeLevel(MinLevel = RuntimeLevel.Run)] - public class ContentBlocksRenderingComposer : IUserComposer +public class ContentBlocksRenderingComposer : IComposer +{ + public void Compose(IUmbracoBuilder builder) { - public void Compose(Composition composition) - { - // Renderer - composition.Register(Lifetime.Scope); + // Renderer + builder.Services.AddScoped(); - // General View Model factory - composition.Register( - typeof(IContentBlockViewModelFactory<>), - typeof(ContentBlockViewModelFactory<>), Lifetime.Singleton); - } + // General View Model factory + builder.Services.AddSingleton( + typeof(IContentBlockViewModelFactory<>), + typeof(ContentBlockViewModelFactory<>)); } -#endif } diff --git a/src/Perplex.ContentBlocks.Core/Rendering/HtmlHelperExtensions.Rendering.cs b/src/Perplex.ContentBlocks.Core/Rendering/HtmlHelperExtensions.Rendering.cs index f45b53a..ccfbb61 100644 --- a/src/Perplex.ContentBlocks.Core/Rendering/HtmlHelperExtensions.Rendering.cs +++ b/src/Perplex.ContentBlocks.Core/Rendering/HtmlHelperExtensions.Rendering.cs @@ -1,104 +1,42 @@ using System.Collections.Generic; using System.Linq; -#if NET5_0 using Microsoft.AspNetCore.Html; using Microsoft.AspNetCore.Mvc.Rendering; using System.Threading.Tasks; -#elif NET472 -using System.Web; -using System.Web.Mvc; -using Umbraco.Core; -using Umbraco.Core.Composing; -#endif -namespace Perplex.ContentBlocks.Rendering -{ - public static partial class HtmlHelperExtensions - { -#if NET5_0 - - /// - /// Renders all Content Blocks. - /// - /// HtmlHelper - /// Content Blocks to render - /// Content Blocks renderer - /// - public static async Task RenderContentBlocks(this IHtmlHelper html, IContentBlocks contentBlocks, IContentBlockRenderer renderer) - => await renderer.Render(contentBlocks, html.PartialAsync); - - /// - /// Renders a single Content Block - /// - /// HtmlHelper - /// Content Block to render - /// Content Blocks renderer - /// - public static async Task RenderContentBlock(this IHtmlHelper html, IContentBlockViewModel contentBlock, IContentBlockRenderer renderer) - => await renderer.RenderBlock(contentBlock, html.PartialAsync); - - /// - /// Renders multiple Content Blocks - /// - /// HtmlHelper - /// Content Blocks to render - /// Content Blocks renderer - /// - public static async Task RenderContentBlocks(this IHtmlHelper html, IEnumerable contentBlocks, IContentBlockRenderer renderer) - => await renderer.RenderBlocks(contentBlocks, html.PartialAsync); - -#elif NET472 - /// - /// Renders all Content Blocks. - /// - /// HtmlHelper - /// Content Blocks to render - /// - public static IHtmlString RenderContentBlocks(this HtmlHelper html, IContentBlocks contentBlocks) - { - if (contentBlocks == null) - { - return MvcHtmlString.Empty; - } +namespace Perplex.ContentBlocks.Rendering; - var renderer = Current.Factory.GetInstance(); - return renderer.Render(contentBlocks, html); - } - - /// - /// Renders a single Content Block - /// - /// HtmlHelper - /// Content Block to render - /// - public static IHtmlString RenderContentBlock(this HtmlHelper html, IContentBlockViewModel contentBlock) - { - if (contentBlock == null) - { - return MvcHtmlString.Empty; - } - - var renderer = Current.Factory.GetInstance(); - return renderer.RenderBlock(contentBlock, html); - } - - /// - /// Renders multiple Content Blocks - /// - /// HtmlHelper - /// Content Blocks to render - /// - public static IHtmlString RenderContentBlocks(this HtmlHelper html, IEnumerable contentBlocks) - { - if (contentBlocks?.Any() != true) - { - return MvcHtmlString.Empty; - } +public static partial class HtmlHelperExtensions +{ + /// + /// Renders all Content Blocks. + /// + /// HtmlHelper + /// Content Blocks to render + /// Content Blocks renderer + /// + public static async Task RenderContentBlocks(this IHtmlHelper html, IContentBlocks contentBlocks, IContentBlockRenderer renderer) + => await renderer.Render(contentBlocks, html.PartialAsync); + + /// + /// Renders a single Content Block + /// + /// HtmlHelper + /// Content Block to render + /// Content Blocks renderer + /// + public static async Task RenderContentBlock(this IHtmlHelper html, IContentBlockViewModel contentBlock, IContentBlockRenderer renderer) + => await renderer.RenderBlock(contentBlock, html.PartialAsync); + + /// + /// Renders multiple Content Blocks + /// + /// HtmlHelper + /// Content Blocks to render + /// Content Blocks renderer + /// + public static async Task RenderContentBlocks(this IHtmlHelper html, IEnumerable contentBlocks, IContentBlockRenderer renderer) + => await renderer.RenderBlocks(contentBlocks, html.PartialAsync); - var renderer = Current.Factory.GetInstance(); - return renderer.RenderBlocks(contentBlocks, html); - } -#endif - } } diff --git a/src/Perplex.ContentBlocks.Core/Rendering/IContentBlockRenderer.cs b/src/Perplex.ContentBlocks.Core/Rendering/IContentBlockRenderer.cs index 5b35cf2..62a1494 100644 --- a/src/Perplex.ContentBlocks.Core/Rendering/IContentBlockRenderer.cs +++ b/src/Perplex.ContentBlocks.Core/Rendering/IContentBlockRenderer.cs @@ -1,46 +1,18 @@ -using System.Collections.Generic; -using System; -#if NET5_0 -using Microsoft.AspNetCore.Html; -using Microsoft.AspNetCore.Mvc.Rendering; -using System.Threading.Tasks; -#elif NET472 -using System.Web; -using System.Web.Mvc; -#endif +using Microsoft.AspNetCore.Html; -namespace Perplex.ContentBlocks.Rendering -{ -#if NET5_0 - public delegate Task RenderPartialViewAsync(string partialViewName, object model); -#endif - - public interface IContentBlockRenderer - { -#if NET5_0 - - Task Render(IContentBlocks contentBlocks, RenderPartialViewAsync renderPartialViewAsync); - - Task RenderHeader(IContentBlocks contentBlocks, RenderPartialViewAsync renderPartialViewAsync); - - Task RenderBlocks(IContentBlocks contentBlocks, RenderPartialViewAsync renderPartialViewAsync); +namespace Perplex.ContentBlocks.Rendering; - Task RenderBlock(IContentBlockViewModel contentBlockViewModel, RenderPartialViewAsync renderPartialViewAsync); +public delegate Task RenderPartialViewAsync(string partialViewName, object model); - Task RenderBlocks(IEnumerable contentBlocks, RenderPartialViewAsync renderPartialViewAsync); - -#elif NET472 - - IHtmlString Render(IContentBlocks contentBlocks, HtmlHelper htmlHelper); - - IHtmlString RenderHeader(IContentBlocks contentBlocks, HtmlHelper htmlHelper); +public interface IContentBlockRenderer +{ + Task Render(IContentBlocks? contentBlocks, RenderPartialViewAsync renderPartialViewAsync); - IHtmlString RenderBlocks(IContentBlocks contentBlocks, HtmlHelper htmlHelper); + Task RenderHeader(IContentBlocks? contentBlocks, RenderPartialViewAsync renderPartialViewAsync); - IHtmlString RenderBlock(IContentBlockViewModel contentBlockViewModel, HtmlHelper htmlHelper); + Task RenderBlocks(IContentBlocks? contentBlocks, RenderPartialViewAsync renderPartialViewAsync); - IHtmlString RenderBlocks(IEnumerable contentBlocks, HtmlHelper htmlHelper); + Task RenderBlock(IContentBlockViewModel? contentBlockViewModel, RenderPartialViewAsync renderPartialViewAsync); -#endif - } + Task RenderBlocks(IEnumerable? contentBlocks, RenderPartialViewAsync renderPartialViewAsync); } diff --git a/src/Perplex.ContentBlocks.Core/Rendering/IContentBlockViewModel.cs b/src/Perplex.ContentBlocks.Core/Rendering/IContentBlockViewModel.cs index d1cd7f7..037424c 100644 --- a/src/Perplex.ContentBlocks.Core/Rendering/IContentBlockViewModel.cs +++ b/src/Perplex.ContentBlocks.Core/Rendering/IContentBlockViewModel.cs @@ -1,21 +1,16 @@ using System; -#if NET5_0 using Umbraco.Cms.Core.Models.PublishedContent; -#elif NET472 -using Umbraco.Core.Models.PublishedContent; -#endif -namespace Perplex.ContentBlocks.Rendering +namespace Perplex.ContentBlocks.Rendering; + +public interface IContentBlockViewModel { - public interface IContentBlockViewModel - { - Guid Id { get; } + Guid Id { get; } - Guid DefinitionId { get; } + Guid DefinitionId { get; } - Guid LayoutId { get; } + Guid LayoutId { get; } - IPublishedElement Content { get; } - } + IPublishedElement Content { get; } } diff --git a/src/Perplex.ContentBlocks.Core/Rendering/IContentBlockViewModelFactory.cs b/src/Perplex.ContentBlocks.Core/Rendering/IContentBlockViewModelFactory.cs index 959f726..1074584 100644 --- a/src/Perplex.ContentBlocks.Core/Rendering/IContentBlockViewModelFactory.cs +++ b/src/Perplex.ContentBlocks.Core/Rendering/IContentBlockViewModelFactory.cs @@ -1,15 +1,8 @@ -using System; +using Umbraco.Cms.Core.Models.PublishedContent; -#if NET5_0 -using Umbraco.Cms.Core.Models.PublishedContent; -#elif NET472 -using Umbraco.Core.Models.PublishedContent; -#endif +namespace Perplex.ContentBlocks.Rendering; -namespace Perplex.ContentBlocks.Rendering +public interface IContentBlockViewModelFactory { - public interface IContentBlockViewModelFactory - { - IContentBlockViewModel Create(IPublishedElement content, Guid id, Guid definitionId, Guid layoutId); - } + IContentBlockViewModel? Create(IPublishedElement content, Guid id, Guid definitionId, Guid layoutId); } diff --git a/src/Perplex.ContentBlocks.Core/Rendering/IContentBlockViewModelFactory{T}.cs b/src/Perplex.ContentBlocks.Core/Rendering/IContentBlockViewModelFactory{T}.cs index 6077216..b6f5dc5 100644 --- a/src/Perplex.ContentBlocks.Core/Rendering/IContentBlockViewModelFactory{T}.cs +++ b/src/Perplex.ContentBlocks.Core/Rendering/IContentBlockViewModelFactory{T}.cs @@ -1,15 +1,8 @@ -using System; -#if NET5_0 -using Umbraco.Cms.Core.Models.PublishedContent; -#elif NET472 -using Umbraco.Core.Models.PublishedContent; -#endif +using Umbraco.Cms.Core.Models.PublishedContent; +namespace Perplex.ContentBlocks.Rendering; -namespace Perplex.ContentBlocks.Rendering +public interface IContentBlockViewModelFactory : IContentBlockViewModelFactory where TContent : IPublishedElement { - public interface IContentBlockViewModelFactory : IContentBlockViewModelFactory where TContent : IPublishedElement - { - IContentBlockViewModel Create(TContent content, Guid id, Guid definitionId, Guid layoutId); - } + IContentBlockViewModel? Create(TContent content, Guid id, Guid definitionId, Guid layoutId); } diff --git a/src/Perplex.ContentBlocks.Core/Rendering/IContentBlockViewModel{T}.cs b/src/Perplex.ContentBlocks.Core/Rendering/IContentBlockViewModel{T}.cs index cbc91f8..dd7a9ec 100644 --- a/src/Perplex.ContentBlocks.Core/Rendering/IContentBlockViewModel{T}.cs +++ b/src/Perplex.ContentBlocks.Core/Rendering/IContentBlockViewModel{T}.cs @@ -1,13 +1,8 @@ -#if NET5_0 -using Umbraco.Cms.Core.Models.PublishedContent; -#elif NET472 -using Umbraco.Core.Models.PublishedContent; -#endif +using Umbraco.Cms.Core.Models.PublishedContent; -namespace Perplex.ContentBlocks.Rendering +namespace Perplex.ContentBlocks.Rendering; + +public interface IContentBlockViewModel : IContentBlockViewModel where TContent : IPublishedElement { - public interface IContentBlockViewModel : IContentBlockViewModel where TContent : IPublishedElement - { - new TContent Content { get; } - } + new TContent Content { get; } } diff --git a/src/Perplex.ContentBlocks.Core/Rendering/IContentBlocks.cs b/src/Perplex.ContentBlocks.Core/Rendering/IContentBlocks.cs index 40e5701..f512039 100644 --- a/src/Perplex.ContentBlocks.Core/Rendering/IContentBlocks.cs +++ b/src/Perplex.ContentBlocks.Core/Rendering/IContentBlocks.cs @@ -1,10 +1,7 @@ -using System.Collections.Generic; +namespace Perplex.ContentBlocks.Rendering; -namespace Perplex.ContentBlocks.Rendering +public interface IContentBlocks { - public interface IContentBlocks - { - IContentBlockViewModel Header { get; } - IEnumerable Blocks { get; } - } + IContentBlockViewModel? Header { get; } + IEnumerable Blocks { get; } } diff --git a/src/Perplex.ContentBlocks.Core/Utils/ContentBlockUtils.cs b/src/Perplex.ContentBlocks.Core/Utils/ContentBlockUtils.cs index 0bf5cf4..f5fd3de 100644 --- a/src/Perplex.ContentBlocks.Core/Utils/ContentBlockUtils.cs +++ b/src/Perplex.ContentBlocks.Core/Utils/ContentBlockUtils.cs @@ -1,82 +1,74 @@ using Perplex.ContentBlocks.Definitions; -using System; -#if NET5_0 using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services; using static Umbraco.Cms.Core.Constants.PropertyEditors; -#elif NET472 -using Umbraco.Core.Models; -using Umbraco.Core.Services; -using static Umbraco.Core.Constants.PropertyEditors; -#endif -namespace Perplex.ContentBlocks.Utils +namespace Perplex.ContentBlocks.Utils; + +/// +/// General ContentBlocks utility functions +/// +public class ContentBlockUtils { + private readonly IDataTypeService _dataTypeService; + private readonly Lazy _definitionRepository; + + public ContentBlockUtils(IDataTypeService dataTypeService, Lazy definitionRepository) + { + _dataTypeService = dataTypeService; + _definitionRepository = definitionRepository; + } + /// - /// General ContentBlocks utility functions + /// Returns the dataType associated with the ContentBlock with the given definitionId. /// - public class ContentBlockUtils + /// Id of the ContentBlock definition + /// + public IDataType? GetDataType(Guid definitionId) { - private readonly IDataTypeService _dataTypeService; - private readonly Lazy _definitionRepository; - - public ContentBlockUtils(IDataTypeService dataTypeService, Lazy definitionRepository) + var definition = _definitionRepository.Value.GetById(definitionId); + if (definition is null) { - _dataTypeService = dataTypeService; - _definitionRepository = definitionRepository; + return null; } - /// - /// Returns the dataType associated with the ContentBlock with the given definitionId. - /// - /// Id of the ContentBlock definition - /// - public IDataType GetDataType(Guid definitionId) - { - var definition = _definitionRepository.Value.GetById(definitionId); - if (definition == null) - { - return null; - } - - return GetDataType(definition); - } + return GetDataType(definition); + } - /// - /// Returns the dataType associated with the given ContentBlock definition - /// - /// ContentBlock definition - /// - public IDataType GetDataType(IContentBlockDefinition definition) + /// + /// Returns the dataType associated with the given ContentBlock definition + /// + /// ContentBlock definition + /// + public IDataType? GetDataType(IContentBlockDefinition definition) + { + if (definition == null) { - if (definition == null) - { - throw new ArgumentNullException(nameof(definition)); - } - - IDataType dataType = null; + throw new ArgumentNullException(nameof(definition)); + } - if (definition.DataTypeId is int dataTypeId) - { - dataType = _dataTypeService.GetDataType(dataTypeId); - } - else if (definition.DataTypeKey is Guid dataTypeKey) - { - dataType = _dataTypeService.GetDataType(dataTypeKey); - } + IDataType? dataType = null; - if (dataType == null) - { - return null; - } + if (definition.DataTypeId is int dataTypeId) + { + dataType = _dataTypeService.GetDataType(dataTypeId); + } + else if (definition.DataTypeKey is Guid dataTypeKey) + { + dataType = _dataTypeService.GetDataType(dataTypeKey); + } - if (dataType.EditorAlias != Aliases.NestedContent) - { - throw new InvalidOperationException($"DataType should be Nested Content, but was '{dataType.EditorAlias}'"); - } + if (dataType == null) + { + return null; + } - return dataType; + if (dataType.EditorAlias != Aliases.NestedContent) + { + throw new InvalidOperationException($"DataType should be Nested Content, but was '{dataType.EditorAlias}'"); } + + return dataType; } } diff --git a/src/Perplex.ContentBlocks.Core/Utils/ContentBlockUtilsComposer.cs b/src/Perplex.ContentBlocks.Core/Utils/ContentBlockUtilsComposer.cs index 396ca80..22a3278 100644 --- a/src/Perplex.ContentBlocks.Core/Utils/ContentBlockUtilsComposer.cs +++ b/src/Perplex.ContentBlocks.Core/Utils/ContentBlockUtilsComposer.cs @@ -1,30 +1,13 @@ -#if NET5_0 -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.Composing; using Umbraco.Cms.Core.DependencyInjection; -#elif NET472 -using Umbraco.Core; -using Umbraco.Core.Composing; -#endif -namespace Perplex.ContentBlocks.Utils +namespace Perplex.ContentBlocks.Utils; + +public class ContentBlockUtilsComposer : IComposer { -#if NET5_0 - public class ContentBlockUtilsComposer : IComposer - { - public void Compose(IUmbracoBuilder builder) - { - builder.Services.AddSingleton(); - } - } -#elif NET472 - [RuntimeLevel(MinLevel = RuntimeLevel.Boot)] - public class ContentBlockUtilsComposer : IUserComposer + public void Compose(IUmbracoBuilder builder) { - public void Compose(Composition composition) - { - composition.Register(Lifetime.Singleton); - } + builder.Services.AddSingleton(); } -#endif } diff --git a/src/Perplex.ContentBlocks.Core/Utils/Cookies/CookiesComposer.cs b/src/Perplex.ContentBlocks.Core/Utils/Cookies/CookiesComposer.cs index e669cdd..dd43540 100644 --- a/src/Perplex.ContentBlocks.Core/Utils/Cookies/CookiesComposer.cs +++ b/src/Perplex.ContentBlocks.Core/Utils/Cookies/CookiesComposer.cs @@ -1,31 +1,14 @@ -#if NET5_0 -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.Composing; using Umbraco.Cms.Core.DependencyInjection; -#elif NET472 -using Umbraco.Core; -using Umbraco.Core.Composing; -#endif -namespace Perplex.ContentBlocks.Utils.Cookies +namespace Perplex.ContentBlocks.Utils.Cookies; + +public class CookiesComposer : IComposer { -#if NET5_0 - public class CookiesComposer : IComposer - { - public void Compose(IUmbracoBuilder builder) - { - builder.Services.AddScoped(); - } - } -#elif NET472 - [RuntimeLevel(MinLevel = RuntimeLevel.Run)] - public class CookiesComposer : IUserComposer + public void Compose(IUmbracoBuilder builder) { - public void Compose(Composition composition) - { - composition.Register(Lifetime.Scope); - } + builder.Services.AddScoped(); } -#endif } diff --git a/src/Perplex.ContentBlocks.Core/Utils/Cookies/HttpCookiesAccessor.cs b/src/Perplex.ContentBlocks.Core/Utils/Cookies/HttpCookiesAccessor.cs index 4323061..c59481c 100644 --- a/src/Perplex.ContentBlocks.Core/Utils/Cookies/HttpCookiesAccessor.cs +++ b/src/Perplex.ContentBlocks.Core/Utils/Cookies/HttpCookiesAccessor.cs @@ -1,41 +1,24 @@ using System.Collections.Generic; -#if NET5_0 using Microsoft.AspNetCore.Http; -#elif NET472 -using System.Web; -using Umbraco.Web; -#endif -namespace Perplex.ContentBlocks.Utils.Cookies +namespace Perplex.ContentBlocks.Utils.Cookies; + +public class HttpCookiesAccessor : IHttpCookiesAccessor { - public class HttpCookiesAccessor : IHttpCookiesAccessor + public IDictionary Cookies { get; } + + public HttpCookiesAccessor(IHttpContextAccessor httpContextAccessor) { - public IDictionary Cookies { get; } + Cookies = new Dictionary(); - public HttpCookiesAccessor(IHttpContextAccessor httpContextAccessor) + if (httpContextAccessor.HttpContext is HttpContext httpCtx && + httpCtx.Request.Cookies is IRequestCookieCollection cookies) { - Cookies = new Dictionary(); - -#if NET5_0 - if (httpContextAccessor.HttpContext is HttpContext httpCtx && - httpCtx.Request.Cookies is IRequestCookieCollection cookies) - { - foreach (var kv in cookies) - { - Cookies[kv.Key] = kv.Value; - } - } -#elif NET472 - if (httpContextAccessor.HttpContext is HttpContext httpCtx && - httpCtx.Request?.Cookies is HttpCookieCollection cookies) + foreach (var kv in cookies) { - foreach (var key in cookies.AllKeys) - { - Cookies[key] = cookies[key]?.Value; - } + Cookies[kv.Key] = kv.Value; } -#endif } } } diff --git a/src/Perplex.ContentBlocks.Core/Utils/Cookies/IHttpCookiesAccessor.cs b/src/Perplex.ContentBlocks.Core/Utils/Cookies/IHttpCookiesAccessor.cs index d28bdc5..a4b0884 100644 --- a/src/Perplex.ContentBlocks.Core/Utils/Cookies/IHttpCookiesAccessor.cs +++ b/src/Perplex.ContentBlocks.Core/Utils/Cookies/IHttpCookiesAccessor.cs @@ -1,9 +1,8 @@ using System.Collections.Generic; -namespace Perplex.ContentBlocks.Utils.Cookies +namespace Perplex.ContentBlocks.Utils.Cookies; + +public interface IHttpCookiesAccessor { - public interface IHttpCookiesAccessor - { - IDictionary Cookies { get; } - } + IDictionary Cookies { get; } } diff --git a/src/Perplex.ContentBlocks.Core/Variants/ContentBlockDefaultVariantSelector.cs b/src/Perplex.ContentBlocks.Core/Variants/ContentBlockDefaultVariantSelector.cs index 7ce13b9..ea56d5f 100644 --- a/src/Perplex.ContentBlocks.Core/Variants/ContentBlockDefaultVariantSelector.cs +++ b/src/Perplex.ContentBlocks.Core/Variants/ContentBlockDefaultVariantSelector.cs @@ -1,5 +1,5 @@ using Perplex.ContentBlocks.PropertyEditor.ModelValue; -using System.Linq; +using Umbraco.Cms.Core.Models.PublishedContent; #if NET472 using Umbraco.Core.Models.PublishedContent; @@ -7,14 +7,13 @@ using Umbraco.Cms.Core.Models.PublishedContent; #endif -namespace Perplex.ContentBlocks.Variants +namespace Perplex.ContentBlocks.Variants; + +/// +/// Variant selector that never selects a variant but will select the default block content. +/// +public class ContentBlockDefaultVariantSelector : IContentBlockVariantSelector { - /// - /// Variant selector that never selects a variant but will select the default block content. - /// - public class ContentBlockDefaultVariantSelector : IContentBlockVariantSelector - { - public ContentBlockVariantModelValue SelectVariant(ContentBlockModelValue block, IPublishedElement content, bool preview) - => null; - } + public ContentBlockVariantModelValue? SelectVariant(ContentBlockModelValue block, IPublishedElement content, bool preview) + => null; } diff --git a/src/Perplex.ContentBlocks.Core/Variants/ContentBlocksVariantsComposer.cs b/src/Perplex.ContentBlocks.Core/Variants/ContentBlocksVariantsComposer.cs index 1886475..d1e1199 100644 --- a/src/Perplex.ContentBlocks.Core/Variants/ContentBlocksVariantsComposer.cs +++ b/src/Perplex.ContentBlocks.Core/Variants/ContentBlocksVariantsComposer.cs @@ -1,31 +1,14 @@ -#if NET5_0 -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.Composing; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Extensions; -#elif NET472 -using Umbraco.Core; -using Umbraco.Core.Composing; -#endif -namespace Perplex.ContentBlocks.Variants +namespace Perplex.ContentBlocks.Variants; + +public class ContentBlocksVariantsComposer : IComposer { -#if NET5_0 - public class ContentBlocksVariantsComposer : IComposer - { - public void Compose(IUmbracoBuilder builder) - { - builder.Services.AddUnique(); - } - } -#elif NET472 - [RuntimeLevel(MinLevel = RuntimeLevel.Boot)] - public class ContentBlocksVariantsComposer : IUserComposer + public void Compose(IUmbracoBuilder builder) { - public void Compose(Composition composition) - { - composition.RegisterUnique(); - } + builder.Services.AddUnique(); } -#endif } diff --git a/src/Perplex.ContentBlocks.Core/Variants/IContentBlockVariantSelector.cs b/src/Perplex.ContentBlocks.Core/Variants/IContentBlockVariantSelector.cs index 76a9e2e..65d89c6 100644 --- a/src/Perplex.ContentBlocks.Core/Variants/IContentBlockVariantSelector.cs +++ b/src/Perplex.ContentBlocks.Core/Variants/IContentBlockVariantSelector.cs @@ -1,4 +1,5 @@ using Perplex.ContentBlocks.PropertyEditor.ModelValue; +using Umbraco.Cms.Core.Models.PublishedContent; #if NET472 using Umbraco.Core.Models.PublishedContent; @@ -6,18 +7,17 @@ using Umbraco.Cms.Core.Models.PublishedContent; #endif -namespace Perplex.ContentBlocks.Variants +namespace Perplex.ContentBlocks.Variants; + +public interface IContentBlockVariantSelector { - public interface IContentBlockVariantSelector - { - /// - /// Select a variant to render for the given block. - /// To render the default block content; return null. - /// - /// The block to select a variant for - /// The content containing the block - /// Indicates if this block is rendered in preview mode - /// A variant to render for this block; or null if the default content should be rendered. - ContentBlockVariantModelValue SelectVariant(ContentBlockModelValue block, IPublishedElement content, bool preview); - } -} \ No newline at end of file + /// + /// Select a variant to render for the given block. + /// To render the default block content; return null. + /// + /// The block to select a variant for + /// The content containing the block + /// Indicates if this block is rendered in preview mode + /// A variant to render for this block; or null if the default content should be rendered. + ContentBlockVariantModelValue? SelectVariant(ContentBlockModelValue block, IPublishedElement content, bool preview); +} diff --git a/src/Perplex.ContentBlocks/Perplex.ContentBlocks.csproj b/src/Perplex.ContentBlocks/Perplex.ContentBlocks.csproj index 2663be0..a58dff6 100644 --- a/src/Perplex.ContentBlocks/Perplex.ContentBlocks.csproj +++ b/src/Perplex.ContentBlocks/Perplex.ContentBlocks.csproj @@ -1,14 +1,10 @@  - - net6.0 - - Perplex.ContentBlocks umbraco umbraco-marketplace Block based content editor for Umbraco - false + false diff --git a/version b/version index 61eedb9..f68407f 100644 --- a/version +++ b/version @@ -14,16 +14,13 @@ version_info=$(echo $1 | sed 's/-.*//') stash_name="pre-$version" stash_result=`git stash save $stash_name` -csproj=src/Perplex.ContentBlocks/Perplex.ContentBlocks.csproj -csprojCore=src/Perplex.ContentBlocks.Core/Perplex.ContentBlocks.Core.csproj +props=src/Directory.Build.props # Update versions -sed -i "s/<\(Version\)>.*<\/\1>/<\1>$version<\/\1>/" $csproj -sed -i "s/<\(Version\)>.*<\/\1>/<\1>$version<\/\1>/" $csprojCore +sed -i "s/<\(Version\)>.*<\/\1>/<\1>$version<\/\1>/" $props # Add -git add $csproj > /dev/null 2>&1 -git add $csprojCore > /dev/null 2>&1 +git add $props > /dev/null 2>&1 # Commit git commit -m "Version ${version}" > /dev/null 2>&1