diff --git a/src/OrchardCore.Modules/OrchardCore.ContentTypes/Editors/ContentTypeSettingsDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.ContentTypes/Editors/ContentTypeSettingsDisplayDriver.cs index 36b86fb09f7..59f2d144389 100644 --- a/src/OrchardCore.Modules/OrchardCore.ContentTypes/Editors/ContentTypeSettingsDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.ContentTypes/Editors/ContentTypeSettingsDisplayDriver.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Options; +using OrchardCore.ContentManagement; using OrchardCore.ContentManagement.Metadata.Models; using OrchardCore.ContentManagement.Metadata.Settings; using OrchardCore.ContentTypes.ViewModels; @@ -12,24 +13,25 @@ namespace OrchardCore.ContentTypes.Editors public class ContentTypeSettingsDisplayDriver : ContentTypeDefinitionDisplayDriver { private static readonly ContentTypeDefinitionDriverOptions _defaultOptions = new(); - + private readonly IStereotypeService _stereotypeService; private readonly ContentTypeDefinitionOptions _options; protected readonly IStringLocalizer S; public ContentTypeSettingsDisplayDriver( IStringLocalizer stringLocalizer, - IOptions options) + IOptions options, + IStereotypeService stereotypeService) { S = stringLocalizer; _options = options.Value; + _stereotypeService = stereotypeService; } public override IDisplayResult Edit(ContentTypeDefinition contentTypeDefinition) - => Initialize("ContentTypeSettings_Edit", model => + => Initialize("ContentTypeSettings_Edit", async model => { var settings = contentTypeDefinition.GetSettings(); - model.Creatable = settings.Creatable; model.Listable = settings.Listable; model.Draftable = settings.Draftable; @@ -37,7 +39,7 @@ public override IDisplayResult Edit(ContentTypeDefinition contentTypeDefinition) model.Securable = settings.Securable; model.Stereotype = settings.Stereotype; model.Description = settings.Description; - model.Options = GetOptions(contentTypeDefinition, settings.Stereotype); + model.Options = await GetOptionsAsync(contentTypeDefinition, settings.Stereotype); }).Location("Content:5"); public override async Task UpdateAsync(ContentTypeDefinition contentTypeDefinition, UpdateTypeEditorContext context) @@ -54,10 +56,11 @@ public override async Task UpdateAsync(ContentTypeDefinition con { context.Updater.ModelState.AddModelError(nameof(ContentTypeSettingsViewModel.Stereotype), S["The stereotype should be alphanumeric."]); } - - var options = GetOptions(contentTypeDefinition, stereotype); + + var options = await GetOptionsAsync(contentTypeDefinition, stereotype); + Apply(context, model, options); - + return Edit(contentTypeDefinition); } @@ -84,21 +87,25 @@ private static void Apply(UpdateTypeEditorContext context, ContentTypeSettingsVi } } - private ContentTypeDefinitionDriverOptions GetOptions(ContentTypeDefinition contentTypeDefinition, string stereotype) + private async Task GetOptionsAsync(ContentTypeDefinition contentTypeDefinition, string stereotype) { + var options = _defaultOptions; + if (contentTypeDefinition.Name != null && _options.ContentTypes.TryGetValue(contentTypeDefinition.Name, out var typeOptions)) { - return typeOptions; + options = typeOptions; } if (stereotype != null && _options.Stereotypes.TryGetValue(stereotype, out var stereotypesOptions)) { - return stereotypesOptions; + options = stereotypesOptions; } - return _defaultOptions; + options.Stereotypes = await _stereotypeService.GetStereotypesAsync(); + + return options; } private static bool IsAlphaNumericOrEmpty(string value) diff --git a/src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/DefaultStereotypesProvider.cs b/src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/DefaultStereotypesProvider.cs deleted file mode 100644 index 5c647b26cd4..00000000000 --- a/src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/DefaultStereotypesProvider.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace OrchardCore.ContentTypes.Services -{ - public class DefaultStereotypesProvider : IStereotypesProvider - { - private readonly IContentDefinitionService _contentDefinitionService; - public DefaultStereotypesProvider(IContentDefinitionService contentDefinitionService) - { - _contentDefinitionService = contentDefinitionService; - } - - public async Task> GetStereotypesAsync() - { - // Harvest all available stereotypes by finding out about the stereotype of all content types - var stereotypes = (await _contentDefinitionService.GetTypesAsync()) - .Where(x => x.Settings["Stereotype"] != null) - .Select(x => x.Settings["Stereotype"].ToString()) - .Distinct(); - - return stereotypes.Select(x => new StereotypeDescription { DisplayName = x, Stereotype = x }); - } - } -} diff --git a/src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/StereotypeService.cs b/src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/StereotypeService.cs index 64539e6c21f..11d69b203b5 100644 --- a/src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/StereotypeService.cs +++ b/src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/StereotypeService.cs @@ -1,27 +1,53 @@ +using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using OrchardCore.ContentManagement; +using OrchardCore.ContentManagement.Metadata.Models; +using OrchardCore.Modules; namespace OrchardCore.ContentTypes.Services { public class StereotypeService : IStereotypeService { private readonly IEnumerable _providers; + private readonly IContentDefinitionService _contentDefinitionService; + private readonly ILogger _logger; - public StereotypeService(IEnumerable providers) + public StereotypeService( + IEnumerable providers, + IContentDefinitionService contentDefinitionService, + ILogger logger) { _providers = providers; + _contentDefinitionService = contentDefinitionService; + _logger = logger; } public async Task> GetStereotypesAsync() { - var descriptions = new List(); + var providerStereotypes = (await _providers.InvokeAsync(provider => provider.GetStereotypesAsync(), _logger)).ToList(); - foreach (var provider in _providers) + var stereotypes = providerStereotypes.Select(providerStereotype => providerStereotype.Stereotype) + .ToHashSet(StringComparer.OrdinalIgnoreCase); + + foreach (var contentType in await _contentDefinitionService.GetTypesAsync()) { - descriptions.AddRange(await provider.GetStereotypesAsync()); + if (!contentType.TypeDefinition.TryGetStereotype(out var stereotype) || + stereotypes.Contains(stereotype)) + { + continue; + } + + providerStereotypes.Add(new StereotypeDescription + { + Stereotype = stereotype, + DisplayName = stereotype + }); } - return descriptions; + return providerStereotypes.OrderBy(x => x.DisplayName); } } } diff --git a/src/OrchardCore.Modules/OrchardCore.ContentTypes/Startup.cs b/src/OrchardCore.Modules/OrchardCore.ContentTypes/Startup.cs index 0a789a5ac52..a0e447bcb4b 100644 --- a/src/OrchardCore.Modules/OrchardCore.ContentTypes/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.ContentTypes/Startup.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.DependencyInjection; +using OrchardCore.ContentManagement; using OrchardCore.ContentTypes.Deployment; using OrchardCore.ContentTypes.Editors; using OrchardCore.ContentTypes.RecipeSteps; @@ -19,7 +20,6 @@ public override void ConfigureServices(IServiceCollection services) services.AddScoped(); services.AddScoped(); services.AddScoped(); - services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); diff --git a/src/OrchardCore.Modules/OrchardCore.ContentTypes/Views/ContentTypeSettings.Edit.cshtml b/src/OrchardCore.Modules/OrchardCore.ContentTypes/Views/ContentTypeSettings.Edit.cshtml index e79dab08f65..e11b0280415 100644 --- a/src/OrchardCore.Modules/OrchardCore.ContentTypes/Views/ContentTypeSettings.Edit.cshtml +++ b/src/OrchardCore.Modules/OrchardCore.ContentTypes/Views/ContentTypeSettings.Edit.cshtml @@ -66,7 +66,13 @@
- + + + @foreach (var item in Model.Options.Stereotypes) + { + + } +
@T["(Optional) The stereotype of the content type. e.g., Widget, MenuItem, ..."]
diff --git a/src/OrchardCore.Modules/OrchardCore.CustomSettings/Services/CustomSettingsStereotypesProvider.cs b/src/OrchardCore.Modules/OrchardCore.CustomSettings/Services/CustomSettingsStereotypesProvider.cs new file mode 100644 index 00000000000..dd88377c173 --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.CustomSettings/Services/CustomSettingsStereotypesProvider.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.Localization; +using OrchardCore.ContentManagement; +using OrchardCore.ContentManagement.Metadata.Models; + +namespace OrchardCore.CustomSettings.Services; + +public class CustomSettingsStereotypesProvider : IStereotypesProvider +{ + protected readonly IStringLocalizer S; + + public CustomSettingsStereotypesProvider(IStringLocalizer stringLocalizer) + { + S = stringLocalizer; + } + + public Task> GetStereotypesAsync() + => Task.FromResult>( + [new StereotypeDescription { Stereotype = "CustomSettings", DisplayName = S["Custom Settings"] }]); + +} diff --git a/src/OrchardCore.Modules/OrchardCore.CustomSettings/Startup.cs b/src/OrchardCore.Modules/OrchardCore.CustomSettings/Startup.cs index 7aa3c175c99..2e61ec23362 100644 --- a/src/OrchardCore.Modules/OrchardCore.CustomSettings/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.CustomSettings/Startup.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.DependencyInjection; +using OrchardCore.ContentManagement; using OrchardCore.ContentManagement.Metadata.Models; using OrchardCore.CustomSettings.Deployment; using OrchardCore.CustomSettings.Drivers; @@ -22,7 +23,7 @@ public override void ConfigureServices(IServiceCollection services) services.AddScoped(); services.AddScoped, CustomSettingsDisplayDriver>(); services.AddScoped(); - + services.AddScoped(); // Permissions services.AddScoped(); services.AddScoped(); diff --git a/src/OrchardCore.Modules/OrchardCore.Menu/Services/MenuItemStereotypesProvider.cs b/src/OrchardCore.Modules/OrchardCore.Menu/Services/MenuItemStereotypesProvider.cs new file mode 100644 index 00000000000..b2e69c7d841 --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Menu/Services/MenuItemStereotypesProvider.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.Localization; +using OrchardCore.ContentManagement; +using OrchardCore.ContentManagement.Metadata.Models; + +namespace OrchardCore.Menu.Services; + +public class MenuItemStereotypesProvider : IStereotypesProvider +{ + protected readonly IStringLocalizer S; + + public MenuItemStereotypesProvider(IStringLocalizer stringLocalizer) + { + S = stringLocalizer; + } + + public Task> GetStereotypesAsync() + => Task.FromResult>( + [new StereotypeDescription { Stereotype = "MenuItem", DisplayName = S["Menu Item"] }]); +} diff --git a/src/OrchardCore.Modules/OrchardCore.Menu/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Menu/Startup.cs index fe576a8c95e..395e5b9ea32 100644 --- a/src/OrchardCore.Modules/OrchardCore.Menu/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Menu/Startup.cs @@ -8,6 +8,7 @@ using OrchardCore.Menu.Drivers; using OrchardCore.Menu.Handlers; using OrchardCore.Menu.Models; +using OrchardCore.Menu.Services; using OrchardCore.Menu.Settings; using OrchardCore.Menu.TagHelpers; using OrchardCore.Modules; @@ -25,6 +26,8 @@ public override void ConfigureServices(IServiceCollection services) services.AddScoped(); services.AddScoped(); + services.AddScoped(); + // MenuPart services.AddScoped(); services.AddContentPart() diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Services/CustomUserSettingsStereotypesProvider.cs b/src/OrchardCore.Modules/OrchardCore.Users/Services/CustomUserSettingsStereotypesProvider.cs new file mode 100644 index 00000000000..edb550ec81a --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Users/Services/CustomUserSettingsStereotypesProvider.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.Localization; +using OrchardCore.ContentManagement; +using OrchardCore.ContentManagement.Metadata.Models; + +namespace OrchardCore.Users.Services; + +public class CustomUserSettingsStereotypesProvider : IStereotypesProvider +{ + protected readonly IStringLocalizer S; + + public CustomUserSettingsStereotypesProvider(IStringLocalizer stringLocalizer) + { + S = stringLocalizer; + } + + public Task> GetStereotypesAsync() + => Task.FromResult>( + [new StereotypeDescription { Stereotype = "CustomUserSettings", DisplayName = S["Custom User Settings"] }]); + +} diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Users/Startup.cs index 21166067722..566248d4c2e 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/Startup.cs @@ -14,6 +14,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; using OrchardCore.Admin.Models; +using OrchardCore.ContentManagement; using OrchardCore.ContentManagement.Metadata.Models; using OrchardCore.Data; using OrchardCore.Data.Migration; @@ -468,6 +469,7 @@ public override void ConfigureServices(IServiceCollection services) services.AddScoped, CustomUserSettingsDisplayDriver>(); services.AddScoped(); services.AddDeployment(); + services.AddScoped(); services.Configure(options => { diff --git a/src/OrchardCore.Modules/OrchardCore.Widgets/Services/WidgetStereotypesProvider.cs b/src/OrchardCore.Modules/OrchardCore.Widgets/Services/WidgetStereotypesProvider.cs new file mode 100644 index 00000000000..9cc76026c68 --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Widgets/Services/WidgetStereotypesProvider.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.Localization; +using OrchardCore.ContentManagement; +using OrchardCore.ContentManagement.Metadata.Models; + +namespace OrchardCore.Widgets.Services; + +public class WidgetStereotypesProvider : IStereotypesProvider +{ + protected readonly IStringLocalizer S; + + public WidgetStereotypesProvider(IStringLocalizer stringLocalizer) + { + S = stringLocalizer; + } + + public Task> GetStereotypesAsync() + => Task.FromResult>( + [new StereotypeDescription { Stereotype = "Widget", DisplayName = S["Widget"] }]); +} diff --git a/src/OrchardCore.Modules/OrchardCore.Widgets/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Widgets/Startup.cs index fbd9e6f0da5..5b66ac9335a 100644 --- a/src/OrchardCore.Modules/OrchardCore.Widgets/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Widgets/Startup.cs @@ -9,6 +9,7 @@ using OrchardCore.ResourceManagement; using OrchardCore.Widgets.Drivers; using OrchardCore.Widgets.Models; +using OrchardCore.Widgets.Services; using OrchardCore.Widgets.Settings; namespace OrchardCore.Widgets @@ -23,6 +24,8 @@ public override void ConfigureServices(IServiceCollection services) services.AddContentPart() .UseDisplayDriver(); + services.AddScoped(); + services.AddScoped(); services.AddContentPart(); services.AddDataMigration(); diff --git a/src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/IStereotypeService.cs b/src/OrchardCore/OrchardCore.ContentManagement.Abstractions/IStereotypeService.cs similarity index 64% rename from src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/IStereotypeService.cs rename to src/OrchardCore/OrchardCore.ContentManagement.Abstractions/IStereotypeService.cs index 1e5d99dfd6e..6c2210a1545 100644 --- a/src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/IStereotypeService.cs +++ b/src/OrchardCore/OrchardCore.ContentManagement.Abstractions/IStereotypeService.cs @@ -1,7 +1,8 @@ using System.Collections.Generic; using System.Threading.Tasks; +using OrchardCore.ContentManagement.Metadata.Models; -namespace OrchardCore.ContentTypes.Services; +namespace OrchardCore.ContentManagement; public interface IStereotypeService { diff --git a/src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/IStereotypesProvider.cs b/src/OrchardCore/OrchardCore.ContentManagement.Abstractions/IStereotypesProvider.cs similarity index 65% rename from src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/IStereotypesProvider.cs rename to src/OrchardCore/OrchardCore.ContentManagement.Abstractions/IStereotypesProvider.cs index 8c4b997334c..d7e4b634f7b 100644 --- a/src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/IStereotypesProvider.cs +++ b/src/OrchardCore/OrchardCore.ContentManagement.Abstractions/IStereotypesProvider.cs @@ -1,7 +1,8 @@ using System.Collections.Generic; using System.Threading.Tasks; +using OrchardCore.ContentManagement.Metadata.Models; -namespace OrchardCore.ContentTypes.Services; +namespace OrchardCore.ContentManagement; public interface IStereotypesProvider { diff --git a/src/OrchardCore/OrchardCore.ContentManagement.Abstractions/Metadata/Models/ContentTypeDefinitionDriverOptions.cs b/src/OrchardCore/OrchardCore.ContentManagement.Abstractions/Metadata/Models/ContentTypeDefinitionDriverOptions.cs index bd080481b88..63c4b9bc2c5 100644 --- a/src/OrchardCore/OrchardCore.ContentManagement.Abstractions/Metadata/Models/ContentTypeDefinitionDriverOptions.cs +++ b/src/OrchardCore/OrchardCore.ContentManagement.Abstractions/Metadata/Models/ContentTypeDefinitionDriverOptions.cs @@ -1,3 +1,5 @@ +using System.Collections.Generic; + namespace OrchardCore.ContentManagement.Metadata.Models; public class ContentTypeDefinitionDriverOptions @@ -11,4 +13,6 @@ public class ContentTypeDefinitionDriverOptions public bool ShowVersionable { get; set; } = true; public bool ShowSecurable { get; set; } = true; + + public IEnumerable Stereotypes { get; set; } } diff --git a/src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/StereotypeDescription.cs b/src/OrchardCore/OrchardCore.ContentManagement.Abstractions/Metadata/Models/StereotypeDescription.cs similarity index 68% rename from src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/StereotypeDescription.cs rename to src/OrchardCore/OrchardCore.ContentManagement.Abstractions/Metadata/Models/StereotypeDescription.cs index 98e4cf532dc..370237ed14e 100644 --- a/src/OrchardCore.Modules/OrchardCore.ContentTypes/Services/StereotypeDescription.cs +++ b/src/OrchardCore/OrchardCore.ContentManagement.Abstractions/Metadata/Models/StereotypeDescription.cs @@ -1,7 +1,8 @@ -namespace OrchardCore.ContentTypes.Services; +namespace OrchardCore.ContentManagement.Metadata.Models; public class StereotypeDescription { public string Stereotype { get; set; } + public string DisplayName { get; set; } }