diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Content/ContentCollectionControllerBase.cs b/src/Umbraco.Cms.Api.Management/Controllers/Content/ContentCollectionControllerBase.cs index 2adfef9664..a38ade6060 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Content/ContentCollectionControllerBase.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Content/ContentCollectionControllerBase.cs @@ -1,7 +1,10 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Content; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Mapping; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.ContentEditing; @@ -18,8 +21,19 @@ public abstract class ContentCollectionControllerBase _mapper = mapper; + protected ContentCollectionControllerBase(IUmbracoMapper mapper, SignProviderCollection signProvider) + { + _mapper = mapper; + _signProviders = signProvider; + } + + [Obsolete("Use the constructer with all parameters. To be removed in Umbraco 18")] + protected ContentCollectionControllerBase(IUmbracoMapper mapper) + : this(mapper, StaticServiceProvider.Instance.GetRequiredService()) + { + } [Obsolete("This method is no longer used and will be removed in Umbraco 17.")] protected IActionResult CollectionResult(ListViewPagedModel result) @@ -48,6 +62,9 @@ public abstract class ContentCollectionControllerBase + /// Creates a collection result from the provided collection response models and total number of items. + /// protected IActionResult CollectionResult(List collectionResponseModels, long totalNumberOfItems) { var pageViewModel = new PagedViewModel @@ -104,4 +121,15 @@ public abstract class ContentCollectionControllerBase + /// Populates the signs for the collection response models. + /// + protected async Task PopulateSigns(IEnumerable itemViewModels) + { + foreach (ISignProvider signProvider in _signProviders.Where(x => x.CanProvideSigns())) + { + await signProvider.PopulateSignsAsync(itemViewModels); + } + } } diff --git a/src/Umbraco.Cms.Api.Management/Controllers/DataType/Tree/AncestorsDataTypeTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/DataType/Tree/AncestorsDataTypeTreeController.cs index d93b76718d..b3a103a01a 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/DataType/Tree/AncestorsDataTypeTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/DataType/Tree/AncestorsDataTypeTreeController.cs @@ -1,6 +1,8 @@ using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Services; @@ -9,11 +11,18 @@ namespace Umbraco.Cms.Api.Management.Controllers.DataType.Tree; [ApiVersion("1.0")] public class AncestorsDataTypeTreeController : DataTypeTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public AncestorsDataTypeTreeController(IEntityService entityService, IDataTypeService dataTypeService) : base(entityService, dataTypeService) { } + [ActivatorUtilitiesConstructor] + public AncestorsDataTypeTreeController(IEntityService entityService, SignProviderCollection signProviders, IDataTypeService dataTypeService) + : base(entityService, signProviders, dataTypeService) + { + } + [HttpGet("ancestors")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/DataType/Tree/ChildrenDataTypeTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/DataType/Tree/ChildrenDataTypeTreeController.cs index cd9f4171cd..7c801530ac 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/DataType/Tree/ChildrenDataTypeTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/DataType/Tree/ChildrenDataTypeTreeController.cs @@ -1,20 +1,29 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Api.Common.ViewModels.Pagination; using Umbraco.Cms.Api.Management.ViewModels.Tree; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Api.Management.Services.Signs; namespace Umbraco.Cms.Api.Management.Controllers.DataType.Tree; [ApiVersion("1.0")] public class ChildrenDataTypeTreeController : DataTypeTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public ChildrenDataTypeTreeController(IEntityService entityService, IDataTypeService dataTypeService) : base(entityService, dataTypeService) { } + [ActivatorUtilitiesConstructor] + public ChildrenDataTypeTreeController(IEntityService entityService, SignProviderCollection signProviders, IDataTypeService dataTypeService) + : base(entityService, signProviders, dataTypeService) + { + } + [HttpGet("children")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/DataType/Tree/DataTypeTreeControllerBase.cs b/src/Umbraco.Cms.Api.Management/Controllers/DataType/Tree/DataTypeTreeControllerBase.cs index 52a7319b1a..f0dbb8a8ec 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/DataType/Tree/DataTypeTreeControllerBase.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/DataType/Tree/DataTypeTreeControllerBase.cs @@ -1,9 +1,12 @@ -using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Management.Controllers.Tree; using Umbraco.Cms.Api.Management.Routing; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Entities; using Umbraco.Cms.Core.Services; @@ -19,8 +22,17 @@ public class DataTypeTreeControllerBase : FolderTreeControllerBase + : this( + entityService, + StaticServiceProvider.Instance.GetRequiredService(), + dataTypeService) + { + } + + public DataTypeTreeControllerBase(IEntityService entityService, SignProviderCollection signProviders, IDataTypeService dataTypeService) + : base(entityService, signProviders) => _dataTypeService = dataTypeService; protected override UmbracoObjectTypes ItemObjectType => UmbracoObjectTypes.DataType; diff --git a/src/Umbraco.Cms.Api.Management/Controllers/DataType/Tree/RootDataTypeTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/DataType/Tree/RootDataTypeTreeController.cs index 0554bff8e5..fa1b5c7bfb 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/DataType/Tree/RootDataTypeTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/DataType/Tree/RootDataTypeTreeController.cs @@ -1,21 +1,29 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Api.Common.ViewModels.Pagination; -using Umbraco.Cms.Api.Management.ViewModels.DataType.Item; using Umbraco.Cms.Api.Management.ViewModels.Tree; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Api.Management.Services.Signs; namespace Umbraco.Cms.Api.Management.Controllers.DataType.Tree; [ApiVersion("1.0")] public class RootDataTypeTreeController : DataTypeTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public RootDataTypeTreeController(IEntityService entityService, IDataTypeService dataTypeService) : base(entityService, dataTypeService) { } + [ActivatorUtilitiesConstructor] + public RootDataTypeTreeController(IEntityService entityService, SignProviderCollection signProviders, IDataTypeService dataTypeService) + : base(entityService, signProviders, dataTypeService) + { + } + [HttpGet("root")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/DataType/Tree/SiblingsDataTypeTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/DataType/Tree/SiblingsDataTypeTreeController.cs index d487df48ff..fcc496e71d 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/DataType/Tree/SiblingsDataTypeTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/DataType/Tree/SiblingsDataTypeTreeController.cs @@ -1,6 +1,8 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Services; @@ -8,11 +10,18 @@ namespace Umbraco.Cms.Api.Management.Controllers.DataType.Tree; public class SiblingsDataTypeTreeController : DataTypeTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public SiblingsDataTypeTreeController(IEntityService entityService, IDataTypeService dataTypeService) : base(entityService, dataTypeService) { } + [ActivatorUtilitiesConstructor] + public SiblingsDataTypeTreeController(IEntityService entityService, SignProviderCollection signProviders, IDataTypeService dataTypeService) + : base(entityService, signProviders, dataTypeService) + { + } + [HttpGet("siblings")] [ProducesResponseType(typeof(SubsetViewModel), StatusCodes.Status200OK)] public async Task>> Siblings(CancellationToken cancellationToken, Guid target, int before, int after, bool foldersOnly = false) diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Dictionary/Tree/AncestorsDictionaryTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Dictionary/Tree/AncestorsDictionaryTreeController.cs index 2c17199602..f7c94de4db 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Dictionary/Tree/AncestorsDictionaryTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Dictionary/Tree/AncestorsDictionaryTreeController.cs @@ -1,6 +1,8 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Services; @@ -9,11 +11,18 @@ namespace Umbraco.Cms.Api.Management.Controllers.Dictionary.Tree; [ApiVersion("1.0")] public class AncestorsDictionaryTreeController : DictionaryTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public AncestorsDictionaryTreeController(IEntityService entityService, IDictionaryItemService dictionaryItemService) : base(entityService, dictionaryItemService) { } + [ActivatorUtilitiesConstructor] + public AncestorsDictionaryTreeController(IEntityService entityService, SignProviderCollection signProviders, IDictionaryItemService dictionaryItemService) + : base(entityService, signProviders, dictionaryItemService) + { + } + [HttpGet("ancestors")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Dictionary/Tree/ChildrenDictionaryTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Dictionary/Tree/ChildrenDictionaryTreeController.cs index 59b23ff801..39c135be2b 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Dictionary/Tree/ChildrenDictionaryTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Dictionary/Tree/ChildrenDictionaryTreeController.cs @@ -1,21 +1,30 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Api.Common.ViewModels.Pagination; +using Umbraco.Cms.Api.Management.Services.Signs; +using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Api.Common.ViewModels.Pagination; -using Umbraco.Cms.Api.Management.ViewModels.Tree; namespace Umbraco.Cms.Api.Management.Controllers.Dictionary.Tree; [ApiVersion("1.0")] public class ChildrenDictionaryTreeController : DictionaryTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public ChildrenDictionaryTreeController(IEntityService entityService, IDictionaryItemService dictionaryItemService) : base(entityService, dictionaryItemService) { } + [ActivatorUtilitiesConstructor] + public ChildrenDictionaryTreeController(IEntityService entityService, SignProviderCollection signProviders, IDictionaryItemService dictionaryItemService) + : base(entityService, signProviders, dictionaryItemService) + { + } + [HttpGet("children")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Dictionary/Tree/DictionaryTreeControllerBase.cs b/src/Umbraco.Cms.Api.Management/Controllers/Dictionary/Tree/DictionaryTreeControllerBase.cs index 2b02ff541a..6533370245 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Dictionary/Tree/DictionaryTreeControllerBase.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Dictionary/Tree/DictionaryTreeControllerBase.cs @@ -1,10 +1,13 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Management.Controllers.Tree; using Umbraco.Cms.Api.Management.Routing; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Web.Common.Authorization; @@ -18,8 +21,17 @@ namespace Umbraco.Cms.Api.Management.Controllers.Dictionary.Tree; // tree controller base. We'll keep it though, in the hope that we can mend EntityService. public class DictionaryTreeControllerBase : NamedEntityTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public DictionaryTreeControllerBase(IEntityService entityService, IDictionaryItemService dictionaryItemService) - : base(entityService) => + : this( + entityService, + StaticServiceProvider.Instance.GetRequiredService(), + dictionaryItemService) + { + } + + public DictionaryTreeControllerBase(IEntityService entityService, SignProviderCollection signProviders, IDictionaryItemService dictionaryItemService) + : base(entityService, signProviders) => DictionaryItemService = dictionaryItemService; // dictionary items do not currently have a known UmbracoObjectType, so we'll settle with Unknown for now diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Dictionary/Tree/RootDictionaryTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Dictionary/Tree/RootDictionaryTreeController.cs index a6d65ed764..7bac1e66a8 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Dictionary/Tree/RootDictionaryTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Dictionary/Tree/RootDictionaryTreeController.cs @@ -1,10 +1,12 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Api.Common.ViewModels.Pagination; +using Umbraco.Cms.Api.Management.Services.Signs; +using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Api.Common.ViewModels.Pagination; -using Umbraco.Cms.Api.Management.ViewModels.Tree; namespace Umbraco.Cms.Api.Management.Controllers.Dictionary.Tree; @@ -16,6 +18,12 @@ public class RootDictionaryTreeController : DictionaryTreeControllerBase { } + [ActivatorUtilitiesConstructor] + public RootDictionaryTreeController(IEntityService entityService, SignProviderCollection signProviders, IDictionaryItemService dictionaryItemService) + : base(entityService, signProviders, dictionaryItemService) + { + } + [HttpGet("root")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Document/Collection/ByKeyDocumentCollectionController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Document/Collection/ByKeyDocumentCollectionController.cs index f55c666cfc..5ab89ba274 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Document/Collection/ByKeyDocumentCollectionController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Document/Collection/ByKeyDocumentCollectionController.cs @@ -1,10 +1,13 @@ using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; using Umbraco.Cms.Api.Management.Factories; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Document.Collection; using Umbraco.Cms.Core; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Mapping; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Security; @@ -20,16 +23,33 @@ public class ByKeyDocumentCollectionController : DocumentCollectionControllerBas private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor; private readonly IDocumentCollectionPresentationFactory _documentCollectionPresentationFactory; + [ActivatorUtilitiesConstructor] + public ByKeyDocumentCollectionController( + IContentListViewService contentListViewService, + IBackOfficeSecurityAccessor backOfficeSecurityAccessor, + IUmbracoMapper mapper, + IDocumentCollectionPresentationFactory documentCollectionPresentationFactory, + SignProviderCollection signProviders) + : base(mapper, signProviders) + { + _contentListViewService = contentListViewService; + _backOfficeSecurityAccessor = backOfficeSecurityAccessor; + _documentCollectionPresentationFactory = documentCollectionPresentationFactory; + } + + [Obsolete("Please use the constructor with all parameters. Scheduled to be removed in V18")] public ByKeyDocumentCollectionController( IContentListViewService contentListViewService, IBackOfficeSecurityAccessor backOfficeSecurityAccessor, IUmbracoMapper mapper, IDocumentCollectionPresentationFactory documentCollectionPresentationFactory) - : base(mapper) + : this( + contentListViewService, + backOfficeSecurityAccessor, + mapper, + documentCollectionPresentationFactory, + StaticServiceProvider.Instance.GetRequiredService()) { - _contentListViewService = contentListViewService; - _backOfficeSecurityAccessor = backOfficeSecurityAccessor; - _documentCollectionPresentationFactory = documentCollectionPresentationFactory; } [HttpGet("{id:guid}")] @@ -65,6 +85,7 @@ public class ByKeyDocumentCollectionController : DocumentCollectionControllerBas } List collectionResponseModels = await _documentCollectionPresentationFactory.CreateCollectionModelAsync(collectionAttempt.Result!); + await PopulateSigns(collectionResponseModels); return CollectionResult(collectionResponseModels, collectionAttempt.Result!.Items.Total); } } diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Document/Collection/DocumentCollectionControllerBase.cs b/src/Umbraco.Cms.Api.Management/Controllers/Document/Collection/DocumentCollectionControllerBase.cs index b4ac5a86da..8de4daa401 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Document/Collection/DocumentCollectionControllerBase.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Document/Collection/DocumentCollectionControllerBase.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Umbraco.Cms.Api.Management.Controllers.Content; using Umbraco.Cms.Api.Management.Routing; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Document; using Umbraco.Cms.Api.Management.ViewModels.Document.Collection; using Umbraco.Cms.Core; @@ -17,6 +18,12 @@ namespace Umbraco.Cms.Api.Management.Controllers.Document.Collection; [Authorize(Policy = AuthorizationPolicies.TreeAccessDocuments)] public abstract class DocumentCollectionControllerBase : ContentCollectionControllerBase { + protected DocumentCollectionControllerBase(IUmbracoMapper mapper, SignProviderCollection signProviders) + : base(mapper, signProviders) + { + } + + [Obsolete("Please use the constructor with all parameters. Scheduled to be removed in V18")] protected DocumentCollectionControllerBase(IUmbracoMapper mapper) : base(mapper) { diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Document/Item/ItemDocumentItemController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Document/Item/ItemDocumentItemController.cs index ebefb5bfb2..f67f880e57 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Document/Item/ItemDocumentItemController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Document/Item/ItemDocumentItemController.cs @@ -1,8 +1,11 @@ using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Management.Factories; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Document.Item; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Entities; using Umbraco.Cms.Core.Services; @@ -14,30 +17,53 @@ public class ItemDocumentItemController : DocumentItemControllerBase { private readonly IEntityService _entityService; private readonly IDocumentPresentationFactory _documentPresentationFactory; + private readonly SignProviderCollection _signProviders; - public ItemDocumentItemController(IEntityService entityService, IDocumentPresentationFactory documentPresentationFactory) + [ActivatorUtilitiesConstructor] + public ItemDocumentItemController( + IEntityService entityService, + IDocumentPresentationFactory documentPresentationFactory, + SignProviderCollection signProvider) { _entityService = entityService; _documentPresentationFactory = documentPresentationFactory; + _signProviders = signProvider; + } + + [Obsolete("Please use the constructor with all parameters. Scheduled for removal in Umbraco 18")] + public ItemDocumentItemController( + IEntityService entityService, + IDocumentPresentationFactory documentPresentationFactory) + : this(entityService, documentPresentationFactory, StaticServiceProvider.Instance.GetRequiredService()) + { } [HttpGet] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] - public Task Item( + public async Task Item( CancellationToken cancellationToken, [FromQuery(Name = "id")] HashSet ids) { if (ids.Count is 0) { - return Task.FromResult(Ok(Enumerable.Empty())); + return Ok(Enumerable.Empty()); } IEnumerable documents = _entityService .GetAll(UmbracoObjectTypes.Document, ids.ToArray()) .OfType(); - IEnumerable documentItemResponseModels = documents.Select(_documentPresentationFactory.CreateItemResponseModel); - return Task.FromResult(Ok(documentItemResponseModels)); + IEnumerable responseModels = documents.Select(_documentPresentationFactory.CreateItemResponseModel); + await PopulateSigns(responseModels); + return Ok(responseModels); + } + + private async Task PopulateSigns(IEnumerable itemViewModels) + { + foreach (ISignProvider signProvider in _signProviders.Where(x => x.CanProvideSigns())) + { + await signProvider.PopulateSignsAsync(itemViewModels); + } } } diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/AncestorsDocumentTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/AncestorsDocumentTreeController.cs index eef178ea70..5e3c347d00 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/AncestorsDocumentTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/AncestorsDocumentTreeController.cs @@ -1,8 +1,10 @@ using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Management.Factories; using Umbraco.Cms.Api.Management.Services.Entities; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Security; @@ -13,6 +15,7 @@ namespace Umbraco.Cms.Api.Management.Controllers.Document.Tree; [ApiVersion("1.0")] public class AncestorsDocumentTreeController : DocumentTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public AncestorsDocumentTreeController( IEntityService entityService, IUserStartNodeEntitiesService userStartNodeEntitiesService, @@ -32,6 +35,28 @@ public class AncestorsDocumentTreeController : DocumentTreeControllerBase { } + [ActivatorUtilitiesConstructor] + public AncestorsDocumentTreeController( + IEntityService entityService, + SignProviderCollection signProviders, + IUserStartNodeEntitiesService userStartNodeEntitiesService, + IDataTypeService dataTypeService, + IPublicAccessService publicAccessService, + AppCaches appCaches, + IBackOfficeSecurityAccessor backofficeSecurityAccessor, + IDocumentPresentationFactory documentPresentationFactory) + : base( + entityService, + signProviders, + userStartNodeEntitiesService, + dataTypeService, + publicAccessService, + appCaches, + backofficeSecurityAccessor, + documentPresentationFactory) + { + } + [HttpGet("ancestors")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/ChildrenDocumentTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/ChildrenDocumentTreeController.cs index e0eb3df87e..76bcb70deb 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/ChildrenDocumentTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/ChildrenDocumentTreeController.cs @@ -1,19 +1,22 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Api.Common.ViewModels.Pagination; +using Umbraco.Cms.Api.Management.Factories; +using Umbraco.Cms.Api.Management.Services.Entities; +using Umbraco.Cms.Api.Management.Services.Signs; +using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Api.Management.Services.Entities; -using Umbraco.Cms.Api.Common.ViewModels.Pagination; -using Umbraco.Cms.Api.Management.Factories; -using Umbraco.Cms.Api.Management.ViewModels.Tree; namespace Umbraco.Cms.Api.Management.Controllers.Document.Tree; [ApiVersion("1.0")] public class ChildrenDocumentTreeController : DocumentTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public ChildrenDocumentTreeController( IEntityService entityService, IUserStartNodeEntitiesService userStartNodeEntitiesService, @@ -33,6 +36,28 @@ public class ChildrenDocumentTreeController : DocumentTreeControllerBase { } + [ActivatorUtilitiesConstructor] + public ChildrenDocumentTreeController( + IEntityService entityService, + SignProviderCollection signProviders, + IUserStartNodeEntitiesService userStartNodeEntitiesService, + IDataTypeService dataTypeService, + IPublicAccessService publicAccessService, + AppCaches appCaches, + IBackOfficeSecurityAccessor backofficeSecurityAccessor, + IDocumentPresentationFactory documentPresentationFactory) + : base( + entityService, + signProviders, + userStartNodeEntitiesService, + dataTypeService, + publicAccessService, + appCaches, + backofficeSecurityAccessor, + documentPresentationFactory) + { + } + [HttpGet("children")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/DocumentTreeControllerBase.cs b/src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/DocumentTreeControllerBase.cs index cacf862b57..a2015d7c76 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/DocumentTreeControllerBase.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/DocumentTreeControllerBase.cs @@ -1,13 +1,16 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Management.Controllers.Tree; using Umbraco.Cms.Api.Management.Factories; using Umbraco.Cms.Api.Management.Routing; using Umbraco.Cms.Api.Management.Services.Entities; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Cache; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Entities; using Umbraco.Cms.Core.Security; @@ -26,6 +29,7 @@ public abstract class DocumentTreeControllerBase : UserStartNodeTreeControllerBa private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor; private readonly IDocumentPresentationFactory _documentPresentationFactory; + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] protected DocumentTreeControllerBase( IEntityService entityService, IUserStartNodeEntitiesService userStartNodeEntitiesService, @@ -34,7 +38,29 @@ public abstract class DocumentTreeControllerBase : UserStartNodeTreeControllerBa AppCaches appCaches, IBackOfficeSecurityAccessor backofficeSecurityAccessor, IDocumentPresentationFactory documentPresentationFactory) - : base(entityService, userStartNodeEntitiesService, dataTypeService) + : this( + entityService, + StaticServiceProvider.Instance.GetRequiredService(), + userStartNodeEntitiesService, + dataTypeService, + publicAccessService, + appCaches, + backofficeSecurityAccessor, + documentPresentationFactory) + { + } + + [ActivatorUtilitiesConstructor] + protected DocumentTreeControllerBase( + IEntityService entityService, + SignProviderCollection signProviders, + IUserStartNodeEntitiesService userStartNodeEntitiesService, + IDataTypeService dataTypeService, + IPublicAccessService publicAccessService, + AppCaches appCaches, + IBackOfficeSecurityAccessor backofficeSecurityAccessor, + IDocumentPresentationFactory documentPresentationFactory) + : base(entityService, signProviders, userStartNodeEntitiesService, dataTypeService) { _publicAccessService = publicAccessService; _appCaches = appCaches; diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/RootDocumentTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/RootDocumentTreeController.cs index a9d63dc4b0..822679e581 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/RootDocumentTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/RootDocumentTreeController.cs @@ -1,19 +1,22 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Api.Common.ViewModels.Pagination; +using Umbraco.Cms.Api.Management.Factories; +using Umbraco.Cms.Api.Management.Services.Entities; +using Umbraco.Cms.Api.Management.Services.Signs; +using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Api.Management.Services.Entities; -using Umbraco.Cms.Api.Common.ViewModels.Pagination; -using Umbraco.Cms.Api.Management.Factories; -using Umbraco.Cms.Api.Management.ViewModels.Tree; namespace Umbraco.Cms.Api.Management.Controllers.Document.Tree; [ApiVersion("1.0")] public class RootDocumentTreeController : DocumentTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public RootDocumentTreeController( IEntityService entityService, IUserStartNodeEntitiesService userStartNodeEntitiesService, @@ -33,6 +36,28 @@ public class RootDocumentTreeController : DocumentTreeControllerBase { } + [ActivatorUtilitiesConstructor] + public RootDocumentTreeController( + IEntityService entityService, + SignProviderCollection signProviders, + IUserStartNodeEntitiesService userStartNodeEntitiesService, + IDataTypeService dataTypeService, + IPublicAccessService publicAccessService, + AppCaches appCaches, + IBackOfficeSecurityAccessor backofficeSecurityAccessor, + IDocumentPresentationFactory documentPresentationFactory) + : base( + entityService, + signProviders, + userStartNodeEntitiesService, + dataTypeService, + publicAccessService, + appCaches, + backofficeSecurityAccessor, + documentPresentationFactory) + { + } + [HttpGet("root")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/SiblingsDocumentTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/SiblingsDocumentTreeController.cs index 850eb9f856..d9e591b664 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/SiblingsDocumentTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/SiblingsDocumentTreeController.cs @@ -1,9 +1,11 @@ using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; using Umbraco.Cms.Api.Management.Factories; using Umbraco.Cms.Api.Management.Services.Entities; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Security; @@ -14,6 +16,7 @@ namespace Umbraco.Cms.Api.Management.Controllers.Document.Tree; [ApiVersion("1.0")] public class SiblingsDocumentTreeController : DocumentTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public SiblingsDocumentTreeController( IEntityService entityService, IUserStartNodeEntitiesService userStartNodeEntitiesService, @@ -33,6 +36,28 @@ public class SiblingsDocumentTreeController : DocumentTreeControllerBase { } + [ActivatorUtilitiesConstructor] + public SiblingsDocumentTreeController( + IEntityService entityService, + SignProviderCollection signProviders, + IUserStartNodeEntitiesService userStartNodeEntitiesService, + IDataTypeService dataTypeService, + IPublicAccessService publicAccessService, + AppCaches appCaches, + IBackOfficeSecurityAccessor backofficeSecurityAccessor, + IDocumentPresentationFactory documentPresentationFactory) + : base( + entityService, + signProviders, + userStartNodeEntitiesService, + dataTypeService, + publicAccessService, + appCaches, + backofficeSecurityAccessor, + documentPresentationFactory) + { + } + [HttpGet("siblings")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(SubsetViewModel), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/AncestorsDocumentBlueprintTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/AncestorsDocumentBlueprintTreeController.cs index 9124b1ae2a..c3d155e54c 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/AncestorsDocumentBlueprintTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/AncestorsDocumentBlueprintTreeController.cs @@ -1,7 +1,9 @@ using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Management.Factories; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Services; @@ -10,11 +12,18 @@ namespace Umbraco.Cms.Api.Management.Controllers.DocumentBlueprint.Tree; [ApiVersion("1.0")] public class AncestorsDocumentBlueprintTreeController : DocumentBlueprintTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public AncestorsDocumentBlueprintTreeController(IEntityService entityService, IDocumentPresentationFactory documentPresentationFactory) : base(entityService, documentPresentationFactory) { } + [ActivatorUtilitiesConstructor] + public AncestorsDocumentBlueprintTreeController(IEntityService entityService, SignProviderCollection signProviders, IDocumentPresentationFactory documentPresentationFactory) + : base(entityService, signProviders, documentPresentationFactory) + { + } + [HttpGet("ancestors")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/ChildrenDocumentBlueprintTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/ChildrenDocumentBlueprintTreeController.cs index 92c1fe28b2..7f2f3ea226 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/ChildrenDocumentBlueprintTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/ChildrenDocumentBlueprintTreeController.cs @@ -1,8 +1,10 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; using Umbraco.Cms.Api.Management.Factories; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Services; @@ -11,11 +13,18 @@ namespace Umbraco.Cms.Api.Management.Controllers.DocumentBlueprint.Tree; [ApiVersion("1.0")] public class ChildrenDocumentBlueprintTreeController : DocumentBlueprintTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public ChildrenDocumentBlueprintTreeController(IEntityService entityService, IDocumentPresentationFactory documentPresentationFactory) : base(entityService, documentPresentationFactory) { } + [ActivatorUtilitiesConstructor] + public ChildrenDocumentBlueprintTreeController(IEntityService entityService, SignProviderCollection signProviders, IDocumentPresentationFactory documentPresentationFactory) + : base(entityService, signProviders, documentPresentationFactory) + { + } + [HttpGet("children")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/DocumentBlueprintTreeControllerBase.cs b/src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/DocumentBlueprintTreeControllerBase.cs index aeaf65b7ef..3a02abb6f0 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/DocumentBlueprintTreeControllerBase.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/DocumentBlueprintTreeControllerBase.cs @@ -1,10 +1,13 @@ -using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Management.Controllers.Tree; using Umbraco.Cms.Api.Management.Factories; using Umbraco.Cms.Api.Management.Routing; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Entities; using Umbraco.Cms.Core.Services; @@ -19,8 +22,17 @@ public class DocumentBlueprintTreeControllerBase : FolderTreeControllerBase(), + documentPresentationFactory) + { + } + + public DocumentBlueprintTreeControllerBase(IEntityService entityService, SignProviderCollection signProviders, IDocumentPresentationFactory documentPresentationFactory) + : base(entityService, signProviders) => _documentPresentationFactory = documentPresentationFactory; protected override UmbracoObjectTypes ItemObjectType => UmbracoObjectTypes.DocumentBlueprint; diff --git a/src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/RootDocumentBlueprintTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/RootDocumentBlueprintTreeController.cs index 79e20385c1..b2a8bfa9cf 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/RootDocumentBlueprintTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/RootDocumentBlueprintTreeController.cs @@ -1,8 +1,10 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; using Umbraco.Cms.Api.Management.Factories; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Services; @@ -11,11 +13,18 @@ namespace Umbraco.Cms.Api.Management.Controllers.DocumentBlueprint.Tree; [ApiVersion("1.0")] public class RootDocumentBlueprintTreeController : DocumentBlueprintTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public RootDocumentBlueprintTreeController(IEntityService entityService, IDocumentPresentationFactory documentPresentationFactory) : base(entityService, documentPresentationFactory) { } + [ActivatorUtilitiesConstructor] + public RootDocumentBlueprintTreeController(IEntityService entityService, SignProviderCollection signProviders, IDocumentPresentationFactory documentPresentationFactory) + : base(entityService, signProviders, documentPresentationFactory) + { + } + [HttpGet("root")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/SiblingsDocumentBlueprintTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/SiblingsDocumentBlueprintTreeController.cs index 6c5e5314b6..c6592c5dda 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/SiblingsDocumentBlueprintTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/SiblingsDocumentBlueprintTreeController.cs @@ -1,7 +1,9 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; using Umbraco.Cms.Api.Management.Factories; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Services; @@ -9,11 +11,18 @@ namespace Umbraco.Cms.Api.Management.Controllers.DocumentBlueprint.Tree; public class SiblingsDocumentBlueprintTreeController : DocumentBlueprintTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public SiblingsDocumentBlueprintTreeController(IEntityService entityService, IDocumentPresentationFactory documentPresentationFactory) : base(entityService, documentPresentationFactory) { } + [ActivatorUtilitiesConstructor] + public SiblingsDocumentBlueprintTreeController(IEntityService entityService, SignProviderCollection signProviders, IDocumentPresentationFactory documentPresentationFactory) + : base(entityService, signProviders, documentPresentationFactory) + { + } + [HttpGet("siblings")] [ProducesResponseType(typeof(SubsetViewModel), StatusCodes.Status200OK)] public async Task>> Siblings( diff --git a/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Tree/AncestorsDocumentTypeTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Tree/AncestorsDocumentTypeTreeController.cs index c49f7b0d3c..02bb34403f 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Tree/AncestorsDocumentTypeTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Tree/AncestorsDocumentTypeTreeController.cs @@ -1,6 +1,8 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Services; @@ -9,11 +11,18 @@ namespace Umbraco.Cms.Api.Management.Controllers.DocumentType.Tree; [ApiVersion("1.0")] public class AncestorsDocumentTypeTreeController : DocumentTypeTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public AncestorsDocumentTypeTreeController(IEntityService entityService, IContentTypeService contentTypeService) : base(entityService, contentTypeService) { } + [ActivatorUtilitiesConstructor] + public AncestorsDocumentTypeTreeController(IEntityService entityService, SignProviderCollection signProviders, IContentTypeService contentTypeService) + : base(entityService, signProviders, contentTypeService) + { + } + [HttpGet("ancestors")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Tree/ChildrenDocumentTypeTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Tree/ChildrenDocumentTypeTreeController.cs index de25c4c1be..9127a359d3 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Tree/ChildrenDocumentTypeTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Tree/ChildrenDocumentTypeTreeController.cs @@ -1,20 +1,29 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using Umbraco.Cms.Core.Services; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; +using Umbraco.Cms.Core.Services; namespace Umbraco.Cms.Api.Management.Controllers.DocumentType.Tree; [ApiVersion("1.0")] public class ChildrenDocumentTypeTreeController : DocumentTypeTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public ChildrenDocumentTypeTreeController(IEntityService entityService, IContentTypeService contentTypeService) : base(entityService, contentTypeService) { } + [ActivatorUtilitiesConstructor] + public ChildrenDocumentTypeTreeController(IEntityService entityService, SignProviderCollection signProviders, IContentTypeService contentTypeService) + : base(entityService, signProviders, contentTypeService) + { + } + [HttpGet("children")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Tree/DocumentTypeTreeControllerBase.cs b/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Tree/DocumentTypeTreeControllerBase.cs index 0a54417200..a76fd49ee8 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Tree/DocumentTypeTreeControllerBase.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Tree/DocumentTypeTreeControllerBase.cs @@ -1,9 +1,12 @@ -using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Management.Controllers.Tree; using Umbraco.Cms.Api.Management.Routing; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Entities; using Umbraco.Cms.Core.Services; @@ -18,8 +21,17 @@ public class DocumentTypeTreeControllerBase : FolderTreeControllerBase + : this( + entityService, + StaticServiceProvider.Instance.GetRequiredService(), + contentTypeService) + { + } + + public DocumentTypeTreeControllerBase(IEntityService entityService, SignProviderCollection signProviders, IContentTypeService contentTypeService) + : base(entityService, signProviders) => _contentTypeService = contentTypeService; protected override UmbracoObjectTypes ItemObjectType => UmbracoObjectTypes.DocumentType; diff --git a/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Tree/RootDocumentTypeTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Tree/RootDocumentTypeTreeController.cs index 4824dc0495..b581b7bbb4 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Tree/RootDocumentTypeTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Tree/RootDocumentTypeTreeController.cs @@ -1,20 +1,29 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using Umbraco.Cms.Core.Services; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; +using Umbraco.Cms.Core.Services; namespace Umbraco.Cms.Api.Management.Controllers.DocumentType.Tree; [ApiVersion("1.0")] public class RootDocumentTypeTreeController : DocumentTypeTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public RootDocumentTypeTreeController(IEntityService entityService, IContentTypeService contentTypeService) : base(entityService, contentTypeService) { } + [ActivatorUtilitiesConstructor] + public RootDocumentTypeTreeController(IEntityService entityService, SignProviderCollection signProviders, IContentTypeService contentTypeService) + : base(entityService, signProviders, contentTypeService) + { + } + [HttpGet("root")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Tree/SiblingsDocumentTypeTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Tree/SiblingsDocumentTypeTreeController.cs index c0c36ab9d8..3ecce3e383 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Tree/SiblingsDocumentTypeTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Tree/SiblingsDocumentTypeTreeController.cs @@ -1,6 +1,8 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Services; @@ -8,11 +10,18 @@ namespace Umbraco.Cms.Api.Management.Controllers.DocumentType.Tree; public class SiblingsDocumentTypeTreeController : DocumentTypeTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public SiblingsDocumentTypeTreeController(IEntityService entityService, IContentTypeService contentTypeService) : base(entityService, contentTypeService) { } + [ActivatorUtilitiesConstructor] + public SiblingsDocumentTypeTreeController(IEntityService entityService, SignProviderCollection signProviders, IContentTypeService contentTypeService) + : base(entityService, signProviders, contentTypeService) + { + } + [HttpGet("siblings")] [ProducesResponseType(typeof(SubsetViewModel), StatusCodes.Status200OK)] public async Task>> Siblings( diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Media/Collection/ByKeyMediaCollectionController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Media/Collection/ByKeyMediaCollectionController.cs index ba6eb5c8b3..184cfe4de0 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Media/Collection/ByKeyMediaCollectionController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Media/Collection/ByKeyMediaCollectionController.cs @@ -1,10 +1,13 @@ using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; using Umbraco.Cms.Api.Management.Factories; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Media.Collection; using Umbraco.Cms.Core; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Mapping; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Security; @@ -20,16 +23,33 @@ public class ByKeyMediaCollectionController : MediaCollectionControllerBase private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor; private readonly IMediaCollectionPresentationFactory _mediaCollectionPresentationFactory; + [ActivatorUtilitiesConstructor] + public ByKeyMediaCollectionController( + IMediaListViewService mediaListViewService, + IBackOfficeSecurityAccessor backOfficeSecurityAccessor, + IUmbracoMapper mapper, + IMediaCollectionPresentationFactory mediaCollectionPresentationFactory, + SignProviderCollection signProviders) + : base(mapper, signProviders) + { + _mediaListViewService = mediaListViewService; + _backOfficeSecurityAccessor = backOfficeSecurityAccessor; + _mediaCollectionPresentationFactory = mediaCollectionPresentationFactory; + } + + [Obsolete("Please use the constructor with all parameters. Scheduled to be removed in Umbraco 18")] public ByKeyMediaCollectionController( IMediaListViewService mediaListViewService, IBackOfficeSecurityAccessor backOfficeSecurityAccessor, IUmbracoMapper mapper, IMediaCollectionPresentationFactory mediaCollectionPresentationFactory) - : base(mapper) + : this( + mediaListViewService, + backOfficeSecurityAccessor, + mapper, + mediaCollectionPresentationFactory, + StaticServiceProvider.Instance.GetRequiredService()) { - _mediaListViewService = mediaListViewService; - _backOfficeSecurityAccessor = backOfficeSecurityAccessor; - _mediaCollectionPresentationFactory = mediaCollectionPresentationFactory; } [HttpGet] @@ -64,6 +84,7 @@ public class ByKeyMediaCollectionController : MediaCollectionControllerBase } List collectionResponseModels = await _mediaCollectionPresentationFactory.CreateCollectionModelAsync(collectionAttempt.Result!); + await PopulateSigns(collectionResponseModels); return CollectionResult(collectionResponseModels, collectionAttempt.Result!.Items.Total); } } diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Media/Collection/MediaCollectionControllerBase.cs b/src/Umbraco.Cms.Api.Management/Controllers/Media/Collection/MediaCollectionControllerBase.cs index cf6b05d8b9..875c65c7ac 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Media/Collection/MediaCollectionControllerBase.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Media/Collection/MediaCollectionControllerBase.cs @@ -1,10 +1,14 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Management.Controllers.Content; using Umbraco.Cms.Api.Management.Routing; +using Umbraco.Cms.Api.Management.Services.Signs; +using Umbraco.Cms.Api.Management.ViewModels.Document.Collection; using Umbraco.Cms.Api.Management.ViewModels.Media; using Umbraco.Cms.Api.Management.ViewModels.Media.Collection; using Umbraco.Cms.Core; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Mapping; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services.OperationStatus; @@ -17,6 +21,12 @@ namespace Umbraco.Cms.Api.Management.Controllers.Media.Collection; [Authorize(Policy = AuthorizationPolicies.SectionAccessMedia)] public abstract class MediaCollectionControllerBase : ContentCollectionControllerBase { + protected MediaCollectionControllerBase(IUmbracoMapper mapper, SignProviderCollection signProviders) + : base(mapper, signProviders) + { + } + + [Obsolete("Please use the constructor with all parameters. Scheduled to be removed in Umbraco 18")] protected MediaCollectionControllerBase(IUmbracoMapper mapper) : base(mapper) { diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Media/Item/ItemMediaItemController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Media/Item/ItemMediaItemController.cs index 7bab65c3ca..bd8684e7a0 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Media/Item/ItemMediaItemController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Media/Item/ItemMediaItemController.cs @@ -1,8 +1,12 @@ using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Management.Factories; +using Umbraco.Cms.Api.Management.Services.Signs; +using Umbraco.Cms.Api.Management.ViewModels.Document.Item; using Umbraco.Cms.Api.Management.ViewModels.Media.Item; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Mapping; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Entities; @@ -15,23 +19,35 @@ public class ItemMediaItemController : MediaItemControllerBase { private readonly IEntityService _entityService; private readonly IMediaPresentationFactory _mediaPresentationFactory; + private readonly SignProviderCollection _signProviders; - public ItemMediaItemController(IEntityService entityService, IMediaPresentationFactory mediaPresentationFactory) + [ActivatorUtilitiesConstructor] + public ItemMediaItemController( + IEntityService entityService, + IMediaPresentationFactory mediaPresentationFactory, + SignProviderCollection signProvider) { _entityService = entityService; _mediaPresentationFactory = mediaPresentationFactory; + _signProviders = signProvider; + } + + [Obsolete("Please use the constructor with all parameters. Scheduled for removal in Umbraco 18")] + public ItemMediaItemController(IEntityService entityService, IMediaPresentationFactory mediaPresentationFactory) + : this(entityService, mediaPresentationFactory, StaticServiceProvider.Instance.GetRequiredService()) + { } [HttpGet] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] - public Task Item( + public async Task Item( CancellationToken cancellationToken, [FromQuery(Name = "id")] HashSet ids) { if (ids.Count is 0) { - return Task.FromResult(Ok(Enumerable.Empty())); + return Ok(Enumerable.Empty()); } IEnumerable media = _entityService @@ -39,6 +55,16 @@ public class ItemMediaItemController : MediaItemControllerBase .OfType(); IEnumerable responseModels = media.Select(_mediaPresentationFactory.CreateItemResponseModel); - return Task.FromResult(Ok(responseModels)); + await PopulateSigns(responseModels); + + return Ok(responseModels); + } + + private async Task PopulateSigns(IEnumerable itemViewModels) + { + foreach (ISignProvider signProvider in _signProviders.Where(x => x.CanProvideSigns())) + { + await signProvider.PopulateSignsAsync(itemViewModels); + } } } diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Media/Tree/AncestorsMediaTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Media/Tree/AncestorsMediaTreeController.cs index 9fde8d2a8e..bf5bade404 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Media/Tree/AncestorsMediaTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Media/Tree/AncestorsMediaTreeController.cs @@ -1,8 +1,10 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Management.Factories; using Umbraco.Cms.Api.Management.Services.Entities; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Security; @@ -13,6 +15,7 @@ namespace Umbraco.Cms.Api.Management.Controllers.Media.Tree; [ApiVersion("1.0")] public class AncestorsMediaTreeController : MediaTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public AncestorsMediaTreeController( IEntityService entityService, IUserStartNodeEntitiesService userStartNodeEntitiesService, @@ -24,6 +27,19 @@ public class AncestorsMediaTreeController : MediaTreeControllerBase { } + [ActivatorUtilitiesConstructor] + public AncestorsMediaTreeController( + IEntityService entityService, + SignProviderCollection signProviders, + IUserStartNodeEntitiesService userStartNodeEntitiesService, + IDataTypeService dataTypeService, + AppCaches appCaches, + IBackOfficeSecurityAccessor backofficeSecurityAccessor, + IMediaPresentationFactory mediaPresentationFactory) + : base(entityService, signProviders, userStartNodeEntitiesService, dataTypeService, appCaches, backofficeSecurityAccessor, mediaPresentationFactory) + { + } + [HttpGet("ancestors")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Media/Tree/ChildrenMediaTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Media/Tree/ChildrenMediaTreeController.cs index 6aee4b0206..c61de0a65b 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Media/Tree/ChildrenMediaTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Media/Tree/ChildrenMediaTreeController.cs @@ -1,9 +1,11 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; using Umbraco.Cms.Api.Management.Factories; using Umbraco.Cms.Api.Management.Services.Entities; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Security; @@ -14,6 +16,7 @@ namespace Umbraco.Cms.Api.Management.Controllers.Media.Tree; [ApiVersion("1.0")] public class ChildrenMediaTreeController : MediaTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public ChildrenMediaTreeController( IEntityService entityService, IUserStartNodeEntitiesService userStartNodeEntitiesService, @@ -25,6 +28,19 @@ public class ChildrenMediaTreeController : MediaTreeControllerBase { } + [ActivatorUtilitiesConstructor] + public ChildrenMediaTreeController( + IEntityService entityService, + SignProviderCollection signProviders, + IUserStartNodeEntitiesService userStartNodeEntitiesService, + IDataTypeService dataTypeService, + AppCaches appCaches, + IBackOfficeSecurityAccessor backofficeSecurityAccessor, + IMediaPresentationFactory mediaPresentationFactory) + : base(entityService, signProviders, userStartNodeEntitiesService, dataTypeService, appCaches, backofficeSecurityAccessor, mediaPresentationFactory) + { + } + [HttpGet("children")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Media/Tree/MediaTreeControllerBase.cs b/src/Umbraco.Cms.Api.Management/Controllers/Media/Tree/MediaTreeControllerBase.cs index 7b2f7facd4..f3283466c4 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Media/Tree/MediaTreeControllerBase.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Media/Tree/MediaTreeControllerBase.cs @@ -1,12 +1,15 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Management.Controllers.Tree; using Umbraco.Cms.Api.Management.Factories; using Umbraco.Cms.Api.Management.Routing; using Umbraco.Cms.Api.Management.Services.Entities; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Cache; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Entities; using Umbraco.Cms.Core.Security; @@ -24,6 +27,7 @@ public class MediaTreeControllerBase : UserStartNodeTreeControllerBase(), + userStartNodeEntitiesService, + dataTypeService, + appCaches, + backofficeSecurityAccessor, + mediaPresentationFactory) + { + } + + [ActivatorUtilitiesConstructor] + public MediaTreeControllerBase( + IEntityService entityService, + SignProviderCollection signProviders, + IUserStartNodeEntitiesService userStartNodeEntitiesService, + IDataTypeService dataTypeService, + AppCaches appCaches, + IBackOfficeSecurityAccessor backofficeSecurityAccessor, + IMediaPresentationFactory mediaPresentationFactory) + : base(entityService, signProviders, userStartNodeEntitiesService, dataTypeService) { _appCaches = appCaches; _backofficeSecurityAccessor = backofficeSecurityAccessor; diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Media/Tree/RootMediaTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Media/Tree/RootMediaTreeController.cs index d2ffa8a4bb..2cadb4c4fc 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Media/Tree/RootMediaTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Media/Tree/RootMediaTreeController.cs @@ -1,9 +1,11 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; using Umbraco.Cms.Api.Management.Factories; using Umbraco.Cms.Api.Management.Services.Entities; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Security; @@ -14,6 +16,7 @@ namespace Umbraco.Cms.Api.Management.Controllers.Media.Tree; [ApiVersion("1.0")] public class RootMediaTreeController : MediaTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public RootMediaTreeController( IEntityService entityService, IUserStartNodeEntitiesService userStartNodeEntitiesService, @@ -25,6 +28,19 @@ public class RootMediaTreeController : MediaTreeControllerBase { } + [ActivatorUtilitiesConstructor] + public RootMediaTreeController( + IEntityService entityService, + SignProviderCollection signProviders, + IUserStartNodeEntitiesService userStartNodeEntitiesService, + IDataTypeService dataTypeService, + AppCaches appCaches, + IBackOfficeSecurityAccessor backofficeSecurityAccessor, + IMediaPresentationFactory mediaPresentationFactory) + : base(entityService, signProviders, userStartNodeEntitiesService, dataTypeService, appCaches, backofficeSecurityAccessor, mediaPresentationFactory) + { + } + [HttpGet("root")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Media/Tree/SiblingsMediaTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Media/Tree/SiblingsMediaTreeController.cs index 012816dbfc..910eeb0bfb 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Media/Tree/SiblingsMediaTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Media/Tree/SiblingsMediaTreeController.cs @@ -1,8 +1,10 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; using Umbraco.Cms.Api.Management.Factories; using Umbraco.Cms.Api.Management.Services.Entities; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Security; @@ -12,6 +14,7 @@ namespace Umbraco.Cms.Api.Management.Controllers.Media.Tree; public class SiblingsMediaTreeController : MediaTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public SiblingsMediaTreeController( IEntityService entityService, IUserStartNodeEntitiesService userStartNodeEntitiesService, @@ -23,6 +26,19 @@ public class SiblingsMediaTreeController : MediaTreeControllerBase { } + [ActivatorUtilitiesConstructor] + public SiblingsMediaTreeController( + IEntityService entityService, + SignProviderCollection signProviders, + IUserStartNodeEntitiesService userStartNodeEntitiesService, + IDataTypeService dataTypeService, + AppCaches appCaches, + IBackOfficeSecurityAccessor backofficeSecurityAccessor, + IMediaPresentationFactory mediaPresentationFactory) + : base(entityService, signProviders, userStartNodeEntitiesService, dataTypeService, appCaches, backofficeSecurityAccessor, mediaPresentationFactory) + { + } + [HttpGet("siblings")] [ProducesResponseType(typeof(SubsetViewModel), StatusCodes.Status200OK)] public async Task>> Siblings(CancellationToken cancellationToken, Guid target, int before, int after, Guid? dataTypeId = null) diff --git a/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Tree/AncestorsMediaTypeTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Tree/AncestorsMediaTypeTreeController.cs index ff90cea529..eeb3c73c5e 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Tree/AncestorsMediaTypeTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Tree/AncestorsMediaTypeTreeController.cs @@ -1,6 +1,8 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Services; @@ -9,11 +11,18 @@ namespace Umbraco.Cms.Api.Management.Controllers.MediaType.Tree; [ApiVersion("1.0")] public class AncestorsMediaTypeTreeController : MediaTypeTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public AncestorsMediaTypeTreeController(IEntityService entityService, IMediaTypeService mediaTypeService) : base(entityService, mediaTypeService) { } + [ActivatorUtilitiesConstructor] + public AncestorsMediaTypeTreeController(IEntityService entityService, SignProviderCollection signProviders, IMediaTypeService mediaTypeService) + : base(entityService, signProviders, mediaTypeService) + { + } + [HttpGet("ancestors")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Tree/ChildrenMediaTypeTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Tree/ChildrenMediaTypeTreeController.cs index 3662360c89..545c5178e3 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Tree/ChildrenMediaTypeTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Tree/ChildrenMediaTypeTreeController.cs @@ -1,7 +1,9 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Services; @@ -10,11 +12,18 @@ namespace Umbraco.Cms.Api.Management.Controllers.MediaType.Tree; [ApiVersion("1.0")] public class ChildrenMediaTypeTreeController : MediaTypeTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public ChildrenMediaTypeTreeController(IEntityService entityService, IMediaTypeService mediaTypeService) : base(entityService, mediaTypeService) { } + [ActivatorUtilitiesConstructor] + public ChildrenMediaTypeTreeController(IEntityService entityService, SignProviderCollection signProviders, IMediaTypeService mediaTypeService) + : base(entityService, signProviders, mediaTypeService) + { + } + [HttpGet("children")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Tree/MediaTypeTreeControllerBase.cs b/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Tree/MediaTypeTreeControllerBase.cs index a3cc202b28..9731a7fb4a 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Tree/MediaTypeTreeControllerBase.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Tree/MediaTypeTreeControllerBase.cs @@ -1,9 +1,12 @@ -using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Management.Controllers.Tree; using Umbraco.Cms.Api.Management.Routing; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Entities; using Umbraco.Cms.Core.Services; @@ -19,8 +22,17 @@ public class MediaTypeTreeControllerBase : FolderTreeControllerBase + : this( + entityService, + StaticServiceProvider.Instance.GetRequiredService(), + mediaTypeService) + { + } + + public MediaTypeTreeControllerBase(IEntityService entityService, SignProviderCollection signProviders, IMediaTypeService mediaTypeService) + : base(entityService, signProviders) => _mediaTypeService = mediaTypeService; protected override UmbracoObjectTypes ItemObjectType => UmbracoObjectTypes.MediaType; diff --git a/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Tree/RootMediaTypeTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Tree/RootMediaTypeTreeController.cs index 7c0aca4791..3def7719cf 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Tree/RootMediaTypeTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Tree/RootMediaTypeTreeController.cs @@ -1,7 +1,9 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Services; @@ -10,11 +12,18 @@ namespace Umbraco.Cms.Api.Management.Controllers.MediaType.Tree; [ApiVersion("1.0")] public class RootMediaTypeTreeController : MediaTypeTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public RootMediaTypeTreeController(IEntityService entityService, IMediaTypeService mediaTypeService) : base(entityService, mediaTypeService) { } + [ActivatorUtilitiesConstructor] + public RootMediaTypeTreeController(IEntityService entityService, SignProviderCollection signProviders, IMediaTypeService mediaTypeService) + : base(entityService, signProviders, mediaTypeService) + { + } + [HttpGet("root")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Tree/SiblingsMediaTypeTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Tree/SiblingsMediaTypeTreeController.cs index f4dd06d632..5e873fb9cc 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Tree/SiblingsMediaTypeTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/MediaType/Tree/SiblingsMediaTypeTreeController.cs @@ -1,6 +1,8 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Services; @@ -8,11 +10,18 @@ namespace Umbraco.Cms.Api.Management.Controllers.MediaType.Tree; public class SiblingsMediaTypeTreeController : MediaTypeTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public SiblingsMediaTypeTreeController(IEntityService entityService, IMediaTypeService mediaTypeService) : base(entityService, mediaTypeService) { } + [ActivatorUtilitiesConstructor] + public SiblingsMediaTypeTreeController(IEntityService entityService, SignProviderCollection signProviders, IMediaTypeService mediaTypeService) + : base(entityService, signProviders, mediaTypeService) + { + } + [HttpGet("siblings")] [ProducesResponseType(typeof(SubsetViewModel), StatusCodes.Status200OK)] public async Task>> Siblings( diff --git a/src/Umbraco.Cms.Api.Management/Controllers/MemberGroup/Tree/MemberGroupTreeControllerBase.cs b/src/Umbraco.Cms.Api.Management/Controllers/MemberGroup/Tree/MemberGroupTreeControllerBase.cs index 2066e79768..90ef8d12d9 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/MemberGroup/Tree/MemberGroupTreeControllerBase.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/MemberGroup/Tree/MemberGroupTreeControllerBase.cs @@ -1,7 +1,8 @@ -using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Umbraco.Cms.Api.Management.Controllers.Tree; using Umbraco.Cms.Api.Management.Routing; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Models; @@ -15,10 +16,16 @@ namespace Umbraco.Cms.Api.Management.Controllers.MemberGroup.Tree; [Authorize(Policy = AuthorizationPolicies.TreeAccessMemberGroups)] public class MemberGroupTreeControllerBase : NamedEntityTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public MemberGroupTreeControllerBase(IEntityService entityService) : base(entityService) { } + public MemberGroupTreeControllerBase(IEntityService entityService, SignProviderCollection signProviders) + : base(entityService, signProviders) + { + } + protected override UmbracoObjectTypes ItemObjectType => UmbracoObjectTypes.MemberGroup; } diff --git a/src/Umbraco.Cms.Api.Management/Controllers/MemberGroup/Tree/RootMemberGroupTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/MemberGroup/Tree/RootMemberGroupTreeController.cs index 3328df5514..08f8319205 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/MemberGroup/Tree/RootMemberGroupTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/MemberGroup/Tree/RootMemberGroupTreeController.cs @@ -1,20 +1,29 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Api.Common.ViewModels.Pagination; using Umbraco.Cms.Api.Management.ViewModels.Tree; +using Umbraco.Cms.Api.Management.Services.Signs; +using Microsoft.Extensions.DependencyInjection; namespace Umbraco.Cms.Api.Management.Controllers.MemberGroup.Tree; [ApiVersion("1.0")] public class RootMemberGroupTreeController : MemberGroupTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public RootMemberGroupTreeController(IEntityService entityService) : base(entityService) { } + [ActivatorUtilitiesConstructor] + public RootMemberGroupTreeController(IEntityService entityService, SignProviderCollection signProviders) + : base(entityService, signProviders) + { + } + [HttpGet("root")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/MemberType/Tree/MemberTypeTreeControllerBase.cs b/src/Umbraco.Cms.Api.Management/Controllers/MemberType/Tree/MemberTypeTreeControllerBase.cs index 9fc8111b6c..a612b32d87 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/MemberType/Tree/MemberTypeTreeControllerBase.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/MemberType/Tree/MemberTypeTreeControllerBase.cs @@ -1,9 +1,12 @@ -using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Management.Controllers.Tree; using Umbraco.Cms.Api.Management.Routing; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Entities; using Umbraco.Cms.Core.Services; @@ -18,10 +21,20 @@ public class MemberTypeTreeControllerBase : NamedEntityTreeControllerBase + : this( + entityService, + StaticServiceProvider.Instance.GetRequiredService(), + memberTypeService) + { + } + + public MemberTypeTreeControllerBase(IEntityService entityService, SignProviderCollection signProviders, IMemberTypeService memberTypeService) + : base(entityService, signProviders) => _memberTypeService = memberTypeService; + protected override UmbracoObjectTypes ItemObjectType => UmbracoObjectTypes.MemberType; protected override MemberTypeTreeItemResponseModel[] MapTreeItemViewModels(Guid? parentKey, IEntitySlim[] entities) diff --git a/src/Umbraco.Cms.Api.Management/Controllers/MemberType/Tree/RootMemberTypeTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/MemberType/Tree/RootMemberTypeTreeController.cs index eeae87da51..4ce9248ecc 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/MemberType/Tree/RootMemberTypeTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/MemberType/Tree/RootMemberTypeTreeController.cs @@ -1,20 +1,29 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using Umbraco.Cms.Core.Services; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; +using Umbraco.Cms.Core.Services; namespace Umbraco.Cms.Api.Management.Controllers.MemberType.Tree; [ApiVersion("1.0")] public class RootMemberTypeTreeController : MemberTypeTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public RootMemberTypeTreeController(IEntityService entityService, IMemberTypeService memberTypeService) : base(entityService, memberTypeService) { } + [ActivatorUtilitiesConstructor] + public RootMemberTypeTreeController(IEntityService entityService, SignProviderCollection signProviders, IMemberTypeService memberTypeService) + : base(entityService, signProviders, memberTypeService) + { + } + [HttpGet("root")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Template/Tree/AncestorsTemplateTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Template/Tree/AncestorsTemplateTreeController.cs index 3d5f0d3ff5..943aeba37f 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Template/Tree/AncestorsTemplateTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Template/Tree/AncestorsTemplateTreeController.cs @@ -1,6 +1,8 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Services; @@ -9,11 +11,18 @@ namespace Umbraco.Cms.Api.Management.Controllers.Template.Tree; [ApiVersion("1.0")] public class AncestorsTemplateTreeController : TemplateTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public AncestorsTemplateTreeController(IEntityService entityService) : base(entityService) { } + [ActivatorUtilitiesConstructor] + public AncestorsTemplateTreeController(IEntityService entityService, SignProviderCollection signProviders) + : base(entityService, signProviders) + { + } + [HttpGet("ancestors")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Template/Tree/ChildrenTemplateTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Template/Tree/ChildrenTemplateTreeController.cs index b5d487b0ed..030be7d062 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Template/Tree/ChildrenTemplateTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Template/Tree/ChildrenTemplateTreeController.cs @@ -1,20 +1,29 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using Umbraco.Cms.Core.Services; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; +using Umbraco.Cms.Core.Services; namespace Umbraco.Cms.Api.Management.Controllers.Template.Tree; [ApiVersion("1.0")] public class ChildrenTemplateTreeController : TemplateTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public ChildrenTemplateTreeController(IEntityService entityService) : base(entityService) { } + [ActivatorUtilitiesConstructor] + public ChildrenTemplateTreeController(IEntityService entityService, SignProviderCollection signProviders) + : base(entityService, signProviders) + { + } + [HttpGet("children")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Template/Tree/RootTemplateTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Template/Tree/RootTemplateTreeController.cs index 4de5731c40..871fdcf368 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Template/Tree/RootTemplateTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Template/Tree/RootTemplateTreeController.cs @@ -1,20 +1,29 @@ -using Asp.Versioning; +using Asp.Versioning; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using Umbraco.Cms.Core.Services; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; +using Umbraco.Cms.Core.Services; namespace Umbraco.Cms.Api.Management.Controllers.Template.Tree; [ApiVersion("1.0")] public class RootTemplateTreeController : TemplateTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public RootTemplateTreeController(IEntityService entityService) : base(entityService) { } + [ActivatorUtilitiesConstructor] + public RootTemplateTreeController(IEntityService entityService, SignProviderCollection signProviders) + : base(entityService, signProviders) + { + } + [HttpGet("root")] [MapToApiVersion("1.0")] [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)] diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Template/Tree/SiblingsTemplateTreeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Template/Tree/SiblingsTemplateTreeController.cs index f566dd52f6..542014c042 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Template/Tree/SiblingsTemplateTreeController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Template/Tree/SiblingsTemplateTreeController.cs @@ -1,6 +1,8 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Services; @@ -8,11 +10,19 @@ namespace Umbraco.Cms.Api.Management.Controllers.Template.Tree; public class SiblingsTemplateTreeController : TemplateTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public SiblingsTemplateTreeController(IEntityService entityService) : base(entityService) { } + [ActivatorUtilitiesConstructor] + public SiblingsTemplateTreeController(IEntityService entityService, SignProviderCollection signProviders) + : base(entityService, signProviders) + { + } + + [HttpGet("siblings")] [ProducesResponseType(typeof(SubsetViewModel), StatusCodes.Status200OK)] public async Task>> Siblings( diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Template/Tree/TemplateTreeControllerBase.cs b/src/Umbraco.Cms.Api.Management/Controllers/Template/Tree/TemplateTreeControllerBase.cs index 2ab19a1ee5..aa65c4f7a5 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Template/Tree/TemplateTreeControllerBase.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Template/Tree/TemplateTreeControllerBase.cs @@ -1,7 +1,8 @@ -using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Umbraco.Cms.Api.Management.Controllers.Tree; using Umbraco.Cms.Api.Management.Routing; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Models; @@ -15,10 +16,16 @@ namespace Umbraco.Cms.Api.Management.Controllers.Template.Tree; [Authorize(Policy = AuthorizationPolicies.TreeAccessTemplates)] public class TemplateTreeControllerBase : NamedEntityTreeControllerBase { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] public TemplateTreeControllerBase(IEntityService entityService) : base(entityService) { } + public TemplateTreeControllerBase(IEntityService entityService, SignProviderCollection signProviders) + : base(entityService, signProviders) + { + } + protected override UmbracoObjectTypes ItemObjectType => UmbracoObjectTypes.Template; } diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Tree/EntityTreeControllerBase.cs b/src/Umbraco.Cms.Api.Management/Controllers/Tree/EntityTreeControllerBase.cs index 2f5a62b9bb..8a5cc27ece 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Tree/EntityTreeControllerBase.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Tree/EntityTreeControllerBase.cs @@ -1,8 +1,11 @@ using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.ViewModels.Pagination; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Extensions; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Entities; @@ -13,8 +16,21 @@ namespace Umbraco.Cms.Api.Management.Controllers.Tree; public abstract class EntityTreeControllerBase : ManagementApiControllerBase where TItem : EntityTreeItemResponseModel, new() { + private readonly SignProviderCollection _signProviders; + + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] protected EntityTreeControllerBase(IEntityService entityService) - => EntityService = entityService; + : this( + entityService, + StaticServiceProvider.Instance.GetRequiredService()) + { + } + + protected EntityTreeControllerBase(IEntityService entityService, SignProviderCollection signProviders) + { + EntityService = entityService; + _signProviders = signProviders; + } protected IEntityService EntityService { get; } @@ -22,34 +38,38 @@ public abstract class EntityTreeControllerBase : ManagementApiControllerB protected virtual Ordering ItemOrdering => Ordering.By(nameof(Infrastructure.Persistence.Dtos.NodeDto.Text)); - protected Task>> GetRoot(int skip, int take) + protected async Task>> GetRoot(int skip, int take) { IEntitySlim[] rootEntities = GetPagedRootEntities(skip, take, out var totalItems); TItem[] treeItemViewModels = MapTreeItemViewModels(null, rootEntities); + await PopulateSigns(treeItemViewModels); + PagedViewModel result = PagedViewModel(treeItemViewModels, totalItems); - return Task.FromResult>>(Ok(result)); + return Ok(result); } - protected Task>> GetChildren(Guid parentId, int skip, int take) + protected async Task>> GetChildren(Guid parentId, int skip, int take) { IEntitySlim[] children = GetPagedChildEntities(parentId, skip, take, out var totalItems); TItem[] treeItemViewModels = MapTreeItemViewModels(parentId, children); + await PopulateSigns(treeItemViewModels); + PagedViewModel result = PagedViewModel(treeItemViewModels, totalItems); - return Task.FromResult>>(Ok(result)); + return Ok(result); } - protected Task>> GetSiblings(Guid target, int before, int after) + protected async Task>> GetSiblings(Guid target, int before, int after) { IEntitySlim[] siblings = GetSiblingEntities(target, before, after, out var totalBefore, out var totalAfter); if (siblings.Length == 0) { - return Task.FromResult>>(NotFound()); + return NotFound(); } IEntitySlim? entity = siblings.FirstOrDefault(); @@ -59,16 +79,18 @@ public abstract class EntityTreeControllerBase : ManagementApiControllerB TItem[] treeItemViewModels = MapTreeItemViewModels(parentKey, siblings); + await PopulateSigns(treeItemViewModels); + SubsetViewModel result = SubsetViewModel(treeItemViewModels, totalBefore, totalAfter); - return Task.FromResult>>(Ok(result)); + return Ok(result); } protected virtual async Task>> GetAncestors(Guid descendantKey, bool includeSelf = true) { IEntitySlim[] ancestorEntities = await GetAncestorEntitiesAsync(descendantKey, includeSelf); - TItem[] result = ancestorEntities + TItem[] treeItemViewModels = ancestorEntities .Select(ancestor => { IEntitySlim? parent = ancestor.ParentId > 0 @@ -79,7 +101,9 @@ public abstract class EntityTreeControllerBase : ManagementApiControllerB }) .ToArray(); - return Ok(result); + await PopulateSigns(treeItemViewModels); + + return Ok(treeItemViewModels); } protected virtual Task GetAncestorEntitiesAsync(Guid descendantKey, bool includeSelf) @@ -138,6 +162,14 @@ public abstract class EntityTreeControllerBase : ManagementApiControllerB protected virtual TItem[] MapTreeItemViewModels(Guid? parentKey, IEntitySlim[] entities) => entities.Select(entity => MapTreeItemViewModel(parentKey, entity)).ToArray(); + protected virtual async Task PopulateSigns(TItem[] treeItemViewModels) + { + foreach (ISignProvider signProvider in _signProviders.Where(x => x.CanProvideSigns())) + { + await signProvider.PopulateSignsAsync(treeItemViewModels); + } + } + protected virtual TItem MapTreeItemViewModel(Guid? parentKey, IEntitySlim entity) { var viewModel = new TItem @@ -147,9 +179,9 @@ public abstract class EntityTreeControllerBase : ManagementApiControllerB Parent = parentKey.HasValue ? new ReferenceByIdModel { - Id = parentKey.Value + Id = parentKey.Value, } - : null + : null, }; return viewModel; diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Tree/FolderTreeControllerBase.cs b/src/Umbraco.Cms.Api.Management/Controllers/Tree/FolderTreeControllerBase.cs index 4e52bbe4e8..d54e537637 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Tree/FolderTreeControllerBase.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Tree/FolderTreeControllerBase.cs @@ -1,9 +1,12 @@ +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core; +using Umbraco.Cms.Core.DependencyInjection; +using Umbraco.Cms.Core.Extensions; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Entities; using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Core.Extensions; using Umbraco.Extensions; namespace Umbraco.Cms.Api.Management.Controllers.Tree; @@ -28,9 +31,16 @@ public abstract class FolderTreeControllerBase : NamedEntityTreeControlle } } + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] protected FolderTreeControllerBase(IEntityService entityService) - : base(entityService) => - // ReSharper disable once VirtualMemberCallInConstructor + : this( + entityService, + StaticServiceProvider.Instance.GetRequiredService()) + { + } + + protected FolderTreeControllerBase(IEntityService entityService, SignProviderCollection signProviders) + : base(entityService, signProviders) => _folderObjectTypeId = FolderObjectType.GetGuid(); protected abstract UmbracoObjectTypes FolderObjectType { get; } diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Tree/NamedEntityTreeControllerBase.cs b/src/Umbraco.Cms.Api.Management/Controllers/Tree/NamedEntityTreeControllerBase.cs index a50c6b1cbe..be1fc3c6ce 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Tree/NamedEntityTreeControllerBase.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Tree/NamedEntityTreeControllerBase.cs @@ -1,4 +1,5 @@ -using Umbraco.Cms.Api.Management.ViewModels.Tree; +using Umbraco.Cms.Api.Management.Services.Signs; +using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core.Models.Entities; using Umbraco.Cms.Core.Services; @@ -7,11 +8,17 @@ namespace Umbraco.Cms.Api.Management.Controllers.Tree; public abstract class NamedEntityTreeControllerBase : EntityTreeControllerBase where TItem : NamedEntityTreeItemResponseModel, new() { + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] protected NamedEntityTreeControllerBase(IEntityService entityService) : base(entityService) { } + protected NamedEntityTreeControllerBase(IEntityService entityService, SignProviderCollection signProviders) + : base(entityService, signProviders) + { + } + protected override TItem MapTreeItemViewModel(Guid? parentKey, IEntitySlim entity) { TItem item = base.MapTreeItemViewModel(parentKey, entity); diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Tree/UserStartNodeTreeControllerBase.cs b/src/Umbraco.Cms.Api.Management/Controllers/Tree/UserStartNodeTreeControllerBase.cs index 6f95e6210e..a6d3ba5ff5 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Tree/UserStartNodeTreeControllerBase.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Tree/UserStartNodeTreeControllerBase.cs @@ -1,7 +1,10 @@ +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Management.Models.Entities; using Umbraco.Cms.Api.Management.Services.Entities; +using Umbraco.Cms.Api.Management.Services.Signs; using Umbraco.Cms.Api.Management.ViewModels.Tree; using Umbraco.Cms.Core; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Models.Entities; using Umbraco.Cms.Core.Services; using Umbraco.Extensions; @@ -19,11 +22,25 @@ public abstract class UserStartNodeTreeControllerBase : EntityTreeControl private Dictionary _accessMap = new(); private Guid? _dataTypeKey; + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")] protected UserStartNodeTreeControllerBase( IEntityService entityService, IUserStartNodeEntitiesService userStartNodeEntitiesService, IDataTypeService dataTypeService) - : base(entityService) + : this( + entityService, + StaticServiceProvider.Instance.GetRequiredService(), + userStartNodeEntitiesService, + dataTypeService) + { + } + + protected UserStartNodeTreeControllerBase( + IEntityService entityService, + SignProviderCollection signProviders, + IUserStartNodeEntitiesService userStartNodeEntitiesService, + IDataTypeService dataTypeService) + : base(entityService, signProviders) { _userStartNodeEntitiesService = userStartNodeEntitiesService; _dataTypeService = dataTypeService; diff --git a/src/Umbraco.Cms.Api.Management/DependencyInjection/UmbracoBuilder.Collections.cs b/src/Umbraco.Cms.Api.Management/DependencyInjection/UmbracoBuilder.Collections.cs new file mode 100644 index 0000000000..e93fb98dfc --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/DependencyInjection/UmbracoBuilder.Collections.cs @@ -0,0 +1,27 @@ +using Umbraco.Cms.Api.Management.Services.Signs; +using Umbraco.Cms.Core.DependencyInjection; + +namespace Umbraco.Extensions +{ + /// + /// Extension methods for for the Umbraco back office + /// + public static partial class UmbracoBuilderExtensions + { + internal static void AddCollectionBuilders(this IUmbracoBuilder builder) + { + builder.SignProviders() + .Append() + .Append() + .Append() + .Append(); + } + + /// + /// Gets the sign providers collection builder. + /// + /// The builder. + public static SignProviderCollectionBuilder SignProviders(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); + } +} diff --git a/src/Umbraco.Cms.Api.Management/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Cms.Api.Management/DependencyInjection/UmbracoBuilderExtensions.cs index 48e53c97e0..a788b1fad2 100644 --- a/src/Umbraco.Cms.Api.Management/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Cms.Api.Management/DependencyInjection/UmbracoBuilderExtensions.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.Configuration; using Umbraco.Cms.Api.Common.DependencyInjection; using Umbraco.Cms.Api.Management.Configuration; @@ -95,6 +95,8 @@ public static partial class UmbracoBuilderExtensions }); } + builder.AddCollectionBuilders(); + return builder; } } diff --git a/src/Umbraco.Cms.Api.Management/Mapping/DocumentType/DocumentTypeMapDefinition.cs b/src/Umbraco.Cms.Api.Management/Mapping/DocumentType/DocumentTypeMapDefinition.cs index 0e9aeba492..7aeb4f1b15 100644 --- a/src/Umbraco.Cms.Api.Management/Mapping/DocumentType/DocumentTypeMapDefinition.cs +++ b/src/Umbraco.Cms.Api.Management/Mapping/DocumentType/DocumentTypeMapDefinition.cs @@ -115,6 +115,7 @@ public class DocumentTypeMapDefinition : ContentTypeMapDefinition +/// Implements a that provides signs for entities that have a collection. +/// +public class HasCollectionSignProvider : ISignProvider +{ + private const string Alias = Constants.Conventions.Signs.Prefix + "HasCollection"; + + /// + public bool CanProvideSigns() + where TItem : IHasSigns => + typeof(TItem) == typeof(DocumentTreeItemResponseModel) || + typeof(TItem) == typeof(DocumentCollectionResponseModel) || + typeof(TItem) == typeof(DocumentItemResponseModel) || + typeof(TItem) == typeof(MediaTreeItemResponseModel) || + typeof(TItem) == typeof(MediaCollectionResponseModel) || + typeof(TItem) == typeof(MediaItemResponseModel); + + /// + public Task PopulateSignsAsync(IEnumerable itemViewModels) + where TItem : IHasSigns + { + foreach (TItem item in itemViewModels) + { + if (HasCollection(item)) + { + item.AddSign(Alias); + } + } + + return Task.CompletedTask; + } + + /// + /// Determines if the given view model contains a collection. + /// + private static bool HasCollection(object item) => item switch + { + DocumentTreeItemResponseModel { DocumentType.Collection: not null } => true, + DocumentCollectionResponseModel { DocumentType.Collection: not null } => true, + DocumentItemResponseModel { DocumentType.Collection: not null } => true, + MediaTreeItemResponseModel { MediaType.Collection: not null } => true, + MediaCollectionResponseModel { MediaType.Collection: not null } => true, + MediaItemResponseModel { MediaType.Collection: not null } => true, + _ => false, + }; +} diff --git a/src/Umbraco.Cms.Api.Management/Services/Signs/HasPendingChangesSignProvider.cs b/src/Umbraco.Cms.Api.Management/Services/Signs/HasPendingChangesSignProvider.cs new file mode 100644 index 0000000000..50c421a792 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Services/Signs/HasPendingChangesSignProvider.cs @@ -0,0 +1,49 @@ +using Umbraco.Cms.Api.Management.ViewModels; +using Umbraco.Cms.Api.Management.ViewModels.Document; +using Umbraco.Cms.Api.Management.ViewModels.Document.Collection; +using Umbraco.Cms.Api.Management.ViewModels.Document.Item; +using Umbraco.Cms.Api.Management.ViewModels.Tree; +using Umbraco.Cms.Core; + +namespace Umbraco.Cms.Api.Management.Services.Signs; + +/// +/// Implements a that provides signs for documents that have pending changes. +/// +public class HasPendingChangesSignProvider : ISignProvider +{ + private const string Alias = Constants.Conventions.Signs.Prefix + "PendingChanges"; + + /// + public bool CanProvideSigns() + where TItem : IHasSigns => + typeof(TItem) == typeof(DocumentTreeItemResponseModel) || + typeof(TItem) == typeof(DocumentCollectionResponseModel) || + typeof(TItem) == typeof(DocumentItemResponseModel); + + /// + public Task PopulateSignsAsync(IEnumerable itemViewModels) + where TItem : IHasSigns + { + foreach (TItem item in itemViewModels) + { + if (HasPendingChanges(item)) + { + item.AddSign(Alias); + } + } + + return Task.CompletedTask; + } + + /// + /// Determines if the given item has any variant that has pending changes. + /// + private bool HasPendingChanges(object item) => item switch + { + DocumentTreeItemResponseModel { Variants: var v } when v.Any(x => x.State == DocumentVariantState.PublishedPendingChanges) => true, + DocumentCollectionResponseModel { Variants: var v } when v.Any(x => x.State == DocumentVariantState.PublishedPendingChanges) => true, + DocumentItemResponseModel { Variants: var v } when v.Any(x => x.State == DocumentVariantState.PublishedPendingChanges) => true, + _ => false, + }; +} diff --git a/src/Umbraco.Cms.Api.Management/Services/Signs/HasScheduleSignProvider.cs b/src/Umbraco.Cms.Api.Management/Services/Signs/HasScheduleSignProvider.cs new file mode 100644 index 0000000000..599d10ae67 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Services/Signs/HasScheduleSignProvider.cs @@ -0,0 +1,43 @@ +using Umbraco.Cms.Api.Management.ViewModels; +using Umbraco.Cms.Api.Management.ViewModels.Document.Collection; +using Umbraco.Cms.Api.Management.ViewModels.Document.Item; +using Umbraco.Cms.Api.Management.ViewModels.Tree; +using Umbraco.Cms.Core.Services; +using Constants = Umbraco.Cms.Core.Constants; + +namespace Umbraco.Cms.Api.Management.Services.Signs; + +/// +/// Implements a that provides signs for documents that are scheduled for publication. +/// +internal class HasScheduleSignProvider : ISignProvider +{ + private const string Alias = Constants.Conventions.Signs.Prefix + "ScheduledForPublish"; + + private readonly IContentService _contentService; + + /// + /// Initializes a new instance of the class. + /// + public HasScheduleSignProvider(IContentService contentService) => _contentService = contentService; + + /// + public bool CanProvideSigns() + where TItem : IHasSigns => + typeof(TItem) == typeof(DocumentTreeItemResponseModel) || + typeof(TItem) == typeof(DocumentCollectionResponseModel) || + typeof(TItem) == typeof(DocumentItemResponseModel); + + /// + public Task PopulateSignsAsync(IEnumerable itemViewModels) + where TItem : IHasSigns + { + IEnumerable contentKeysScheduledForPublishing = _contentService.GetScheduledContentKeys(itemViewModels.Select(x => x.Id)); + foreach (Guid key in contentKeysScheduledForPublishing) + { + itemViewModels.First(x => x.Id == key).AddSign(Alias); + } + + return Task.CompletedTask; + } +} diff --git a/src/Umbraco.Cms.Api.Management/Services/Signs/ISignProvider.cs b/src/Umbraco.Cms.Api.Management/Services/Signs/ISignProvider.cs new file mode 100644 index 0000000000..e0324f05c8 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Services/Signs/ISignProvider.cs @@ -0,0 +1,24 @@ +using Umbraco.Cms.Api.Management.ViewModels; + +namespace Umbraco.Cms.Api.Management.Services.Signs; + +/// +/// Defines operation for the provision of presentation signs for item, tree and collection nodes. +/// +public interface ISignProvider +{ + /// + /// Gets a value indicating whether this provider can provide signs for the specified item type. + /// + /// Type of view model supporting signs. + bool CanProvideSigns() + where TItem : IHasSigns; + + /// + /// Populates the provided item view models with signs. + /// + /// Type of item view model supporting signs. + /// The collection of item view models to be populated with signs. + Task PopulateSignsAsync(IEnumerable itemViewModels) + where TItem : IHasSigns; +} diff --git a/src/Umbraco.Cms.Api.Management/Services/Signs/IsProtectedSignProvider.cs b/src/Umbraco.Cms.Api.Management/Services/Signs/IsProtectedSignProvider.cs new file mode 100644 index 0000000000..acd375ca9e --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Services/Signs/IsProtectedSignProvider.cs @@ -0,0 +1,32 @@ +using Umbraco.Cms.Api.Management.ViewModels; +using Umbraco.Cms.Core; + +namespace Umbraco.Cms.Api.Management.Services.Signs; + +/// +/// Implements a that provides signs for documents that are protected. +/// +internal class IsProtectedSignProvider : ISignProvider +{ + private const string Alias = Constants.Conventions.Signs.Prefix + "IsProtected"; + + /// > + public bool CanProvideSigns() + where TItem : IHasSigns => + typeof(IIsProtected).IsAssignableFrom(typeof(TItem)); + + /// > + public Task PopulateSignsAsync(IEnumerable itemViewModels) + where TItem : IHasSigns + { + foreach (TItem item in itemViewModels) + { + if (item is IIsProtected { IsProtected: true }) + { + item.AddSign(Alias); + } + } + + return Task.CompletedTask; + } +} diff --git a/src/Umbraco.Cms.Api.Management/Services/Signs/SignProviderCollection.cs b/src/Umbraco.Cms.Api.Management/Services/Signs/SignProviderCollection.cs new file mode 100644 index 0000000000..81c50aafd5 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Services/Signs/SignProviderCollection.cs @@ -0,0 +1,18 @@ +using Umbraco.Cms.Core.Composing; + +namespace Umbraco.Cms.Api.Management.Services.Signs; + +/// +/// Defines an ordered collection of . +/// +public class SignProviderCollection : BuilderCollectionBase +{ + /// + /// Initializes a new instance of the class. + /// + /// The collection items. + public SignProviderCollection(Func> items) + : base(items) + { + } +} diff --git a/src/Umbraco.Cms.Api.Management/Services/Signs/SignProviderCollectionBuilder.cs b/src/Umbraco.Cms.Api.Management/Services/Signs/SignProviderCollectionBuilder.cs new file mode 100644 index 0000000000..a07d67634f --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Services/Signs/SignProviderCollectionBuilder.cs @@ -0,0 +1,12 @@ +using Umbraco.Cms.Core.Composing; + +namespace Umbraco.Cms.Api.Management.Services.Signs; + +/// +/// Builds an ordered collection of . +/// +public class SignProviderCollectionBuilder : OrderedCollectionBuilderBase +{ + /// + protected override SignProviderCollectionBuilder This => this; +} diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/Content/ContentResponseModelBase.cs b/src/Umbraco.Cms.Api.Management/ViewModels/Content/ContentResponseModelBase.cs index 1eddf7af46..8425079f52 100644 --- a/src/Umbraco.Cms.Api.Management/ViewModels/Content/ContentResponseModelBase.cs +++ b/src/Umbraco.Cms.Api.Management/ViewModels/Content/ContentResponseModelBase.cs @@ -1,11 +1,19 @@ -using Umbraco.Cms.Core.Models.ContentEditing; +using Umbraco.Cms.Core.Models.ContentEditing; namespace Umbraco.Cms.Api.Management.ViewModels.Content; public abstract class ContentResponseModelBase - : ContentModelBase + : ContentModelBase, IHasSigns where TValueResponseModelBase : ValueModelBase where TVariantResponseModel : VariantResponseModelBase { + private readonly List _signs = []; + public Guid Id { get; set; } + + public IEnumerable Signs => _signs.AsEnumerable(); + + public void AddSign(string alias) => _signs.Add(new SignModel { Alias = alias }); + + public void RemoveSign(string alias) => _signs.RemoveAll(x => x.Alias == alias); } diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/ContentType/ContentTypeCollectionReferenceResponseModelBase.cs b/src/Umbraco.Cms.Api.Management/ViewModels/ContentType/ContentTypeCollectionReferenceResponseModelBase.cs index 70d3b992ad..1760b8d364 100644 --- a/src/Umbraco.Cms.Api.Management/ViewModels/ContentType/ContentTypeCollectionReferenceResponseModelBase.cs +++ b/src/Umbraco.Cms.Api.Management/ViewModels/ContentType/ContentTypeCollectionReferenceResponseModelBase.cs @@ -7,4 +7,6 @@ public abstract class ContentTypeCollectionReferenceResponseModelBase public string Alias { get; set; } = string.Empty; public string Icon { get; set; } = string.Empty; + + public ReferenceByIdModel? Collection { get; set; } } diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/Document/Collection/DocumentCollectionResponseModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/Document/Collection/DocumentCollectionResponseModel.cs index 391714346a..107ec0c891 100644 --- a/src/Umbraco.Cms.Api.Management/ViewModels/Document/Collection/DocumentCollectionResponseModel.cs +++ b/src/Umbraco.Cms.Api.Management/ViewModels/Document/Collection/DocumentCollectionResponseModel.cs @@ -3,7 +3,7 @@ using Umbraco.Cms.Api.Management.ViewModels.DocumentType; namespace Umbraco.Cms.Api.Management.ViewModels.Document.Collection; -public class DocumentCollectionResponseModel : ContentCollectionResponseModelBase +public class DocumentCollectionResponseModel : ContentCollectionResponseModelBase, IHasSigns, IIsProtected { public DocumentTypeCollectionReferenceResponseModel DocumentType { get; set; } = new(); diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/Document/Item/DocumentItemResponseModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/Document/Item/DocumentItemResponseModel.cs index 25f4975b9f..4301b8096d 100644 --- a/src/Umbraco.Cms.Api.Management/ViewModels/Document/Item/DocumentItemResponseModel.cs +++ b/src/Umbraco.Cms.Api.Management/ViewModels/Document/Item/DocumentItemResponseModel.cs @@ -1,10 +1,9 @@ -using Umbraco.Cms.Api.Management.ViewModels.Content; using Umbraco.Cms.Api.Management.ViewModels.DocumentType; using Umbraco.Cms.Api.Management.ViewModels.Item; namespace Umbraco.Cms.Api.Management.ViewModels.Document.Item; -public class DocumentItemResponseModel : ItemResponseModelBase +public class DocumentItemResponseModel : ItemResponseModelBase, IIsProtected { public bool IsTrashed { get; set; } diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/IHasSigns.cs b/src/Umbraco.Cms.Api.Management/ViewModels/IHasSigns.cs new file mode 100644 index 0000000000..23aafd1e2b --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/ViewModels/IHasSigns.cs @@ -0,0 +1,30 @@ +namespace Umbraco.Cms.Api.Management.ViewModels; + +/// +/// Marker interface that indicates the type has support for backoffice signs (presented as icons +/// overlaying the main icon for the entity). +/// +public interface IHasSigns +{ + /// + /// Gets the unique identifier for the entity. + /// + Guid Id { get; } + + /// + /// Gets the collection of signs for the entity. + /// + IEnumerable Signs { get; } + + /// + /// Adds a sign to the entity with the specified alias. + /// + /// + void AddSign(string alias); + + /// + /// Removes a sign from the entity with the specified alias. + /// + /// + void RemoveSign(string alias); +} diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/IIsProtected.cs b/src/Umbraco.Cms.Api.Management/ViewModels/IIsProtected.cs new file mode 100644 index 0000000000..3babb19b82 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/ViewModels/IIsProtected.cs @@ -0,0 +1,12 @@ +namespace Umbraco.Cms.Api.Management.ViewModels; + +/// +/// Marker interface that indicates the type can represent the state of protected content. +/// +public interface IIsProtected +{ + /// + /// Gets or sets a value indicating whether the model represents content that is protected. + /// + bool IsProtected { get; set; } +} diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/Item/ItemResponseModelBase.cs b/src/Umbraco.Cms.Api.Management/ViewModels/Item/ItemResponseModelBase.cs index f39ee8c578..01622557fd 100644 --- a/src/Umbraco.Cms.Api.Management/ViewModels/Item/ItemResponseModelBase.cs +++ b/src/Umbraco.Cms.Api.Management/ViewModels/Item/ItemResponseModelBase.cs @@ -1,6 +1,14 @@ namespace Umbraco.Cms.Api.Management.ViewModels.Item; -public abstract class ItemResponseModelBase +public abstract class ItemResponseModelBase : IHasSigns { + private readonly List _signs = []; + public Guid Id { get; set; } + + public IEnumerable Signs => _signs.AsEnumerable(); + + public void AddSign(string alias) => _signs.Add(new SignModel { Alias = alias }); + + public void RemoveSign(string alias) => _signs.RemoveAll(x => x.Alias == alias); } diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/SignModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/SignModel.cs new file mode 100644 index 0000000000..0cfec8e36f --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/ViewModels/SignModel.cs @@ -0,0 +1,6 @@ +namespace Umbraco.Cms.Api.Management.ViewModels; + +public class SignModel +{ + public required string Alias { get; set; } +} diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/Tree/ContentTreeItemResponseModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/Tree/ContentTreeItemResponseModel.cs index a18f1c8ea8..aab2af128d 100644 --- a/src/Umbraco.Cms.Api.Management/ViewModels/Tree/ContentTreeItemResponseModel.cs +++ b/src/Umbraco.Cms.Api.Management/ViewModels/Tree/ContentTreeItemResponseModel.cs @@ -6,7 +6,5 @@ public abstract class ContentTreeItemResponseModel : EntityTreeItemResponseModel public bool IsTrashed { get; set; } - public Guid Id { get; set; } - public DateTimeOffset CreateDate { get; set; } } diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/Tree/DocumentTreeItemResponseModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/Tree/DocumentTreeItemResponseModel.cs index 1bde763102..f784665657 100644 --- a/src/Umbraco.Cms.Api.Management/ViewModels/Tree/DocumentTreeItemResponseModel.cs +++ b/src/Umbraco.Cms.Api.Management/ViewModels/Tree/DocumentTreeItemResponseModel.cs @@ -3,7 +3,7 @@ using Umbraco.Cms.Api.Management.ViewModels.DocumentType; namespace Umbraco.Cms.Api.Management.ViewModels.Tree; -public class DocumentTreeItemResponseModel : ContentTreeItemResponseModel +public class DocumentTreeItemResponseModel : ContentTreeItemResponseModel, IIsProtected { public bool IsProtected { get; set; } diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/Tree/EntityTreeItemResponseModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/Tree/EntityTreeItemResponseModel.cs index 3373daf20d..ac1057e29e 100644 --- a/src/Umbraco.Cms.Api.Management/ViewModels/Tree/EntityTreeItemResponseModel.cs +++ b/src/Umbraco.Cms.Api.Management/ViewModels/Tree/EntityTreeItemResponseModel.cs @@ -1,8 +1,16 @@ -namespace Umbraco.Cms.Api.Management.ViewModels.Tree; +namespace Umbraco.Cms.Api.Management.ViewModels.Tree; -public class EntityTreeItemResponseModel : TreeItemPresentationModel +public class EntityTreeItemResponseModel : TreeItemPresentationModel, IHasSigns { + private readonly List _signs = []; + public Guid Id { get; set; } public ReferenceByIdModel? Parent { get; set; } + + public IEnumerable Signs => _signs.AsEnumerable(); + + public void AddSign(string alias) => _signs.Add(new SignModel { Alias = alias }); + + public void RemoveSign(string alias) => _signs.RemoveAll(x => x.Alias == alias); } diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/Tree/MediaTreeItemResponseModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/Tree/MediaTreeItemResponseModel.cs index 8e6aa960cd..a952269e12 100644 --- a/src/Umbraco.Cms.Api.Management/ViewModels/Tree/MediaTreeItemResponseModel.cs +++ b/src/Umbraco.Cms.Api.Management/ViewModels/Tree/MediaTreeItemResponseModel.cs @@ -1,4 +1,4 @@ -using Umbraco.Cms.Api.Management.ViewModels.Content; +using Umbraco.Cms.Api.Management.ViewModels.Content; using Umbraco.Cms.Api.Management.ViewModels.MediaType; namespace Umbraco.Cms.Api.Management.ViewModels.Tree; diff --git a/src/Umbraco.Core/Constants-Conventions.cs b/src/Umbraco.Core/Constants-Conventions.cs index 989b947adc..fd57fef49a 100644 --- a/src/Umbraco.Core/Constants-Conventions.cs +++ b/src/Umbraco.Core/Constants-Conventions.cs @@ -303,5 +303,16 @@ public static partial class Constants { public const string Prefix = "umb://"; } + + /// + /// Constants for relating to view model signs. + /// + public static class Signs + { + /// + /// Prefix for all sign aliases. + /// + public const string Prefix = "Umb."; + } } } diff --git a/src/Umbraco.Core/Persistence/Repositories/IDocumentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IDocumentRepository.cs index f6ee0b6926..9ff75c2b3d 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IDocumentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IDocumentRepository.cs @@ -50,6 +50,15 @@ public interface IDocumentRepository : IContentRepository, IReadR /// IEnumerable GetContentForRelease(DateTime date); + /// + /// Gets the content keys from the provided collection of keys that are scheduled for publishing. + /// + /// The content keys. + /// + /// The provided collection of content keys filtered for those that are scheduled for publishing. + /// + IEnumerable GetScheduledContentKeys(Guid[] keys) => []; + /// /// Get the count of published items /// diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index 0c3b61a1c3..016d4a83ca 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -1007,6 +1007,23 @@ public class ContentService : RepositoryService, IContentService /// True if the content has any children otherwise False public bool HasChildren(int id) => CountChildren(id) > 0; + + /// + public IEnumerable GetScheduledContentKeys(IEnumerable keys) + { + Guid[] idsA = keys.ToArray(); + if (idsA.Length == 0) + { + return Enumerable.Empty(); + } + + using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) + { + scope.ReadLock(Constants.Locks.ContentTree); + return _documentRepository.GetScheduledContentKeys(idsA); + } + } + /// /// Checks if the passed in can be published based on the ancestors publish state. /// diff --git a/src/Umbraco.Core/Services/IContentService.cs b/src/Umbraco.Core/Services/IContentService.cs index a7bde2dc46..228d7fa6db 100644 --- a/src/Umbraco.Core/Services/IContentService.cs +++ b/src/Umbraco.Core/Services/IContentService.cs @@ -275,6 +275,15 @@ public interface IContentService : IContentServiceBase /// bool HasChildren(int id); + /// + /// Gets the content keys from the provided collection of keys that are scheduled for publishing. + /// + /// The content keys. + /// + /// The provided collection of content keys filtered for those that are scheduled for publishing. + /// + IEnumerable GetScheduledContentKeys(IEnumerable keys) => []; + #endregion #region Save, Delete Document diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DocumentRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DocumentRepository.cs index 687a878c83..1279d62186 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DocumentRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DocumentRepository.cs @@ -1671,6 +1671,27 @@ public class DocumentRepository : ContentRepositoryBase(sql)); } + /// + public IEnumerable GetScheduledContentKeys(Guid[] keys) + { + var action = ContentScheduleAction.Release.ToString(); + DateTime now = DateTime.UtcNow; + + Sql sql = SqlContext.Sql(); + sql + .Select(x => x.UniqueId) + .From() + .InnerJoin().On(left => left.NodeId, right => right.NodeId) + .InnerJoin().On(left => left.NodeId, right => right.NodeId) + .WhereIn(x => x.UniqueId, keys) + .WhereIn(x => x.NodeId, Sql() + .Select(x => x.NodeId) + .From() + .Where(x => x.Action == action && x.Date >= now)); + + return Database.Fetch(sql); + } + /// public IEnumerable GetContentForExpiration(DateTime date) { diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentServiceTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentServiceTests.cs index 3d04a9fa6c..0271b77e84 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentServiceTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentServiceTests.cs @@ -687,6 +687,25 @@ internal sealed class ContentServiceTests : UmbracoIntegrationTestWithContent Assert.That(contents.Count(), Is.EqualTo(1)); } + [Test] + public void Can_Get_Scheduled_Content_Keys() + { + // Arrange + var root = ContentService.GetById(Textpage.Id); + ContentService.Publish(root!, root!.AvailableCultures.ToArray()); + var content = ContentService.GetById(Subpage.Id); + var contentSchedule = ContentScheduleCollection.CreateWithEntry(DateTime.UtcNow.AddDays(1), null); + ContentService.PersistContentSchedule(content!, contentSchedule); + ContentService.Publish(content, content.AvailableCultures.ToArray()); + + // Act + var keys = ContentService.GetScheduledContentKeys([Textpage.Key, Subpage.Key, Subpage2.Key]).ToList(); + + // Assert + Assert.AreEqual(1, keys.Count); + Assert.AreEqual(Subpage.Key, keys.First()); + } + [Test] public void Can_Get_Content_For_Release() { diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Cms.Api.Management/Services/Signs/HasCollectionSignProviderTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Cms.Api.Management/Services/Signs/HasCollectionSignProviderTests.cs new file mode 100644 index 0000000000..8c9a4cb3e3 --- /dev/null +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Cms.Api.Management/Services/Signs/HasCollectionSignProviderTests.cs @@ -0,0 +1,196 @@ +using NUnit.Framework; +using Umbraco.Cms.Api.Management.Services.Signs; +using Umbraco.Cms.Api.Management.ViewModels; +using Umbraco.Cms.Api.Management.ViewModels.Document.Collection; +using Umbraco.Cms.Api.Management.ViewModels.Document.Item; +using Umbraco.Cms.Api.Management.ViewModels.DocumentType; +using Umbraco.Cms.Api.Management.ViewModels.Media.Collection; +using Umbraco.Cms.Api.Management.ViewModels.Media.Item; +using Umbraco.Cms.Api.Management.ViewModels.MediaType; +using Umbraco.Cms.Api.Management.ViewModels.Tree; + +namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Cms.Api.Management.Services.Signs; + +[TestFixture] +internal class HasCollectionSignProviderTests +{ + [Test] + public void HasCollectionSignProvider_Can_Provide_Document_Tree_Signs() + { + var sut = new HasCollectionSignProvider(); + Assert.IsTrue(sut.CanProvideSigns()); + } + + [Test] + public void HasCollectionSignProvider_Can_Provide_Document_Collection_Signs() + { + var sut = new HasCollectionSignProvider(); + Assert.IsTrue(sut.CanProvideSigns()); + } + + [Test] + public void HasCollectionSignProvider_Can_Provide_Document_Item_Signs() + { + var sut = new HasCollectionSignProvider(); + Assert.IsTrue(sut.CanProvideSigns()); + } + + [Test] + public void HasCollectionSignProvider_Can_Provide_Media_Tree_Signs() + { + var sut = new HasCollectionSignProvider(); + Assert.IsTrue(sut.CanProvideSigns()); + } + + [Test] + public void HasCollectionSignProvider_Can_Provide_Media_Collection_Signs() + { + var sut = new HasCollectionSignProvider(); + Assert.IsTrue(sut.CanProvideSigns()); + } + + [Test] + public void HasCollectionSignProvider_Can_Provide_Media_Item_Signs() + { + var sut = new HasCollectionSignProvider(); + Assert.IsTrue(sut.CanProvideSigns()); + } + + [Test] + public async Task HasCollectionSignProvider_Should_Populate_Document_Tree_Signs() + { + var sut = new HasCollectionSignProvider(); + + var viewModels = new List + { + new() + { + Id = Guid.NewGuid(), DocumentType = new DocumentTypeReferenceResponseModel() { Collection = new ReferenceByIdModel(Guid.NewGuid()) }, + }, + new() { Id = Guid.NewGuid() }, + }; + + await sut.PopulateSignsAsync(viewModels); + + Assert.AreEqual(viewModels[0].Signs.Count(), 1); + Assert.AreEqual(viewModels[1].Signs.Count(), 0); + + var signModel = viewModels[0].Signs.First(); + Assert.AreEqual("Umb.HasCollection", signModel.Alias); + } + + [Test] + public async Task HasCollectionSignProvider_Should_Populate_Document_Collection_Signs() + { + var sut = new HasCollectionSignProvider(); + + var viewModels = new List + { + new() + { + Id = Guid.NewGuid(), DocumentType = new DocumentTypeCollectionReferenceResponseModel() { Collection = new ReferenceByIdModel(Guid.NewGuid()) }, + }, + new() { Id = Guid.NewGuid() }, + }; + + await sut.PopulateSignsAsync(viewModels); + + Assert.AreEqual(viewModels[0].Signs.Count(), 1); + Assert.AreEqual(viewModels[1].Signs.Count(), 0); + + var signModel = viewModels[0].Signs.First(); + Assert.AreEqual("Umb.HasCollection", signModel.Alias); + } + + [Test] + public async Task HasCollectionSignProvider_Should_Populate_Document_Item_Signs() + { + var sut = new HasCollectionSignProvider(); + + var viewModels = new List + { + new() + { + Id = Guid.NewGuid(), DocumentType = new DocumentTypeReferenceResponseModel() { Collection = new ReferenceByIdModel(Guid.NewGuid()) }, + }, + new() { Id = Guid.NewGuid() }, + }; + + await sut.PopulateSignsAsync(viewModels); + + Assert.AreEqual(viewModels[0].Signs.Count(), 1); + Assert.AreEqual(viewModels[1].Signs.Count(), 0); + + var signModel = viewModels[0].Signs.First(); + Assert.AreEqual("Umb.HasCollection", signModel.Alias); + } + + [Test] + public async Task HasCollectionSignProvider_Should_Populate_Media_Tree_Signs() + { + var sut = new HasCollectionSignProvider(); + + var viewModels = new List + { + new() + { + Id = Guid.NewGuid(), MediaType = new MediaTypeReferenceResponseModel() { Collection = new ReferenceByIdModel(Guid.NewGuid()) }, + }, + new() { Id = Guid.NewGuid() }, + }; + + await sut.PopulateSignsAsync(viewModels); + + Assert.AreEqual(viewModels[0].Signs.Count(), 1); + Assert.AreEqual(viewModels[1].Signs.Count(), 0); + + var signModel = viewModels[0].Signs.First(); + Assert.AreEqual("Umb.HasCollection", signModel.Alias); + } + + [Test] + public async Task HasCollectionSignProvider_Should_Populate_Media_Collection_Signs() + { + var sut = new HasCollectionSignProvider(); + + var viewModels = new List + { + new() + { + Id = Guid.NewGuid(), MediaType = new MediaTypeCollectionReferenceResponseModel() { Collection = new ReferenceByIdModel(Guid.NewGuid()) }, + }, + new() { Id = Guid.NewGuid() }, + }; + + await sut.PopulateSignsAsync(viewModels); + + Assert.AreEqual(viewModels[0].Signs.Count(), 1); + Assert.AreEqual(viewModels[1].Signs.Count(), 0); + + var signModel = viewModels[0].Signs.First(); + Assert.AreEqual("Umb.HasCollection", signModel.Alias); + } + + [Test] + public async Task HasCollectionSignProvider_Should_Populate_Media_Item_Signs() + { + var sut = new HasCollectionSignProvider(); + + var viewModels = new List + { + new() + { + Id = Guid.NewGuid(), MediaType = new MediaTypeReferenceResponseModel() { Collection = new ReferenceByIdModel(Guid.NewGuid()) }, + }, + new() { Id = Guid.NewGuid() }, + }; + + await sut.PopulateSignsAsync(viewModels); + + Assert.AreEqual(viewModels[0].Signs.Count(), 1); + Assert.AreEqual(viewModels[1].Signs.Count(), 0); + + var signModel = viewModels[0].Signs.First(); + Assert.AreEqual("Umb.HasCollection", signModel.Alias); + } +} diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Cms.Api.Management/Services/Signs/HasPendingChangesSignProviderTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Cms.Api.Management/Services/Signs/HasPendingChangesSignProviderTests.cs new file mode 100644 index 0000000000..7bc7435919 --- /dev/null +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Cms.Api.Management/Services/Signs/HasPendingChangesSignProviderTests.cs @@ -0,0 +1,126 @@ +using NUnit.Framework; +using Umbraco.Cms.Api.Management.Services.Signs; +using Umbraco.Cms.Api.Management.ViewModels.Document; +using Umbraco.Cms.Api.Management.ViewModels.Document.Collection; +using Umbraco.Cms.Api.Management.ViewModels.Document.Item; +using Umbraco.Cms.Api.Management.ViewModels.Tree; + +namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Cms.Api.Management.Services.Signs; + +[TestFixture] +internal class HasPendingChangesSignProviderTests +{ + [Test] + public void HasPendingChangesSignProvider_Can_Provide_Document_Tree_Signs() + { + var sut = new HasPendingChangesSignProvider(); + Assert.IsTrue(sut.CanProvideSigns()); + } + + [Test] + public void HasPendingChangesSignProvider_Can_Provide_Document_Collection_Signs() + { + var sut = new HasPendingChangesSignProvider(); + Assert.IsTrue(sut.CanProvideSigns()); + } + + [Test] + public void HasPendingChangesSignProvider_Can_Provide_Document_Item_Signs() + { + var sut = new HasPendingChangesSignProvider(); + Assert.IsTrue(sut.CanProvideSigns()); + } + + [Test] + public async Task HasPendingChangesSignProvider_Should_Populate_Document_Tree_Signs() + { + var sut = new HasPendingChangesSignProvider(); + + var viewModels = new List + { + new() { Id = Guid.NewGuid() }, + new() + { + Id = Guid.NewGuid(), Variants = + [ + new() + { + State = DocumentVariantState.PublishedPendingChanges, + Culture = null, + Name = "Test", + }, + ], + }, + }; + + await sut.PopulateSignsAsync(viewModels); + + Assert.AreEqual(viewModels[0].Signs.Count(), 0); + Assert.AreEqual(viewModels[1].Signs.Count(), 1); + + var signModel = viewModels[1].Signs.First(); + Assert.AreEqual("Umb.PendingChanges", signModel.Alias); + } + + [Test] + public async Task HasPendingChangesSignProvider_Should_Populate_Document_Collection_Signs() + { + var sut = new HasPendingChangesSignProvider(); + + var viewModels = new List + { + new() { Id = Guid.NewGuid() }, + new() + { + Id = Guid.NewGuid(), Variants = + [ + new() + { + State = DocumentVariantState.PublishedPendingChanges, + Culture = null, + Name = "Test", + }, + ], + }, + }; + + await sut.PopulateSignsAsync(viewModels); + + Assert.AreEqual(viewModels[0].Signs.Count(), 0); + Assert.AreEqual(viewModels[1].Signs.Count(), 1); + + var signModel = viewModels[1].Signs.First(); + Assert.AreEqual("Umb.PendingChanges", signModel.Alias); + } + + [Test] + public async Task HasPendingChangesSignProvider_Should_Populate_Document_Item_Signs() + { + var sut = new HasPendingChangesSignProvider(); + + var viewModels = new List + { + new() { Id = Guid.NewGuid() }, + new() + { + Id = Guid.NewGuid(), Variants = + [ + new() + { + State = DocumentVariantState.PublishedPendingChanges, + Culture = null, + Name = "Test", + }, + ], + }, + }; + + await sut.PopulateSignsAsync(viewModels); + + Assert.AreEqual(viewModels[0].Signs.Count(), 0); + Assert.AreEqual(viewModels[1].Signs.Count(), 1); + + var signModel = viewModels[1].Signs.First(); + Assert.AreEqual("Umb.PendingChanges", signModel.Alias); + } +} diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Cms.Api.Management/Services/Signs/HasScheduleSignProviderTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Cms.Api.Management/Services/Signs/HasScheduleSignProviderTests.cs new file mode 100644 index 0000000000..48b97ff30b --- /dev/null +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Cms.Api.Management/Services/Signs/HasScheduleSignProviderTests.cs @@ -0,0 +1,125 @@ +using Moq; +using NUnit.Framework; +using Umbraco.Cms.Api.Management.Services.Signs; +using Umbraco.Cms.Api.Management.ViewModels.Document.Collection; +using Umbraco.Cms.Api.Management.ViewModels.Document.Item; +using Umbraco.Cms.Api.Management.ViewModels.Tree; +using Umbraco.Cms.Core.Models.Entities; +using Umbraco.Cms.Core.Services; + +namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Cms.Api.Management.Services.Signs; + +[TestFixture] +internal class HasScheduleSignProviderTests +{ + [Test] + public void HasScheduleSignProvider_Can_Provide_Document_Tree_Signs() + { + var contentServiceMock = new Mock(); + + var sut = new HasScheduleSignProvider(contentServiceMock.Object); + Assert.IsTrue(sut.CanProvideSigns()); + } + + [Test] + public void HasScheduleSignProvider_Can_Provide_Document_Collection_Signs() + { + var contentServiceMock = new Mock(); + + var sut = new HasScheduleSignProvider(contentServiceMock.Object); + Assert.IsTrue(sut.CanProvideSigns()); + } + + [Test] + public void HasScheduleSignProvider_Can_Provide_Document_Item_Signs() + { + var contentServiceMock = new Mock(); + + var sut = new HasScheduleSignProvider(contentServiceMock.Object); + Assert.IsTrue(sut.CanProvideSigns()); + } + + [Test] + public async Task HasScheduleSignProvider_Should_Populate_Document_Tree_Signs() + { + var entities = new List + { + new() { Key = Guid.NewGuid(), Name = "Item 1" }, new() { Key = Guid.NewGuid(), Name = "Item 2" }, + }; + + var contentServiceMock = new Mock(); + contentServiceMock + .Setup(x => x.GetScheduledContentKeys(It.IsAny>())) + .Returns([entities[1].Key]); + var sut = new HasScheduleSignProvider(contentServiceMock.Object); + + var viewModels = new List + { + new() { Id = entities[0].Key }, new() { Id = entities[1].Key }, + }; + + await sut.PopulateSignsAsync(viewModels); + + Assert.AreEqual(viewModels[0].Signs.Count(), 0); + Assert.AreEqual(viewModels[1].Signs.Count(), 1); + + var signModel = viewModels[1].Signs.First(); + Assert.AreEqual("Umb.ScheduledForPublish", signModel.Alias); + } + + [Test] + public async Task HasScheduleSignProvider_Should_Populate_Document_Collection_Signs() + { + var entities = new List + { + new() { Key = Guid.NewGuid(), Name = "Item 1" }, new() { Key = Guid.NewGuid(), Name = "Item 2" }, + }; + + var contentServiceMock = new Mock(); + contentServiceMock + .Setup(x => x.GetScheduledContentKeys(It.IsAny>())) + .Returns([entities[1].Key]); + var sut = new HasScheduleSignProvider(contentServiceMock.Object); + + var viewModels = new List + { + new() { Id = entities[0].Key }, new() { Id = entities[1].Key }, + }; + + await sut.PopulateSignsAsync(viewModels); + + Assert.AreEqual(viewModels[0].Signs.Count(), 0); + Assert.AreEqual(viewModels[1].Signs.Count(), 1); + + var signModel = viewModels[1].Signs.First(); + Assert.AreEqual("Umb.ScheduledForPublish", signModel.Alias); + } + + [Test] + public async Task HasScheduleSignProvider_Should_Populate_Document_Item_Signs() + { + var entities = new List + { + new() { Key = Guid.NewGuid(), Name = "Item 1" }, new() { Key = Guid.NewGuid(), Name = "Item 2" }, + }; + + var contentServiceMock = new Mock(); + contentServiceMock + .Setup(x => x.GetScheduledContentKeys(It.IsAny>())) + .Returns([entities[1].Key]); + var sut = new HasScheduleSignProvider(contentServiceMock.Object); + + var viewModels = new List + { + new() { Id = entities[0].Key }, new() { Id = entities[1].Key }, + }; + + await sut.PopulateSignsAsync(viewModels); + + Assert.AreEqual(viewModels[0].Signs.Count(), 0); + Assert.AreEqual(viewModels[1].Signs.Count(), 1); + + var signModel = viewModels[1].Signs.First(); + Assert.AreEqual("Umb.ScheduledForPublish", signModel.Alias); + } +} diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Cms.Api.Management/Services/Signs/IsProtectedSignProviderTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Cms.Api.Management/Services/Signs/IsProtectedSignProviderTests.cs new file mode 100644 index 0000000000..c15fec787c --- /dev/null +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Cms.Api.Management/Services/Signs/IsProtectedSignProviderTests.cs @@ -0,0 +1,92 @@ +using NUnit.Framework; +using Umbraco.Cms.Api.Management.Services.Signs; +using Umbraco.Cms.Api.Management.ViewModels.Document.Collection; +using Umbraco.Cms.Api.Management.ViewModels.Document.Item; +using Umbraco.Cms.Api.Management.ViewModels.Tree; + +namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Cms.Api.Management.Services.Signs; + +[TestFixture] +internal class IsProtectedSignProviderTests +{ + [Test] + public void IsProtectedSignProvider_Can_Provide_Tree_Signs() + { + var sut = new IsProtectedSignProvider(); + Assert.IsTrue(sut.CanProvideSigns()); + } + + [Test] + public void IsProtectedSignProvider_Can_Provide_Collection_Signs() + { + var sut = new IsProtectedSignProvider(); + Assert.IsTrue(sut.CanProvideSigns()); + } + + [Test] + public void IsProtectedSignProvider_Can_Provide_Plain_Signs() + { + var sut = new IsProtectedSignProvider(); + Assert.IsTrue(sut.CanProvideSigns()); + } + + [Test] + public async Task IsProtectedSignProvider_Should_Populate_Tree_Signs() + { + var sut = new IsProtectedSignProvider(); + + var viewModels = new List + { + new(), + new() { IsProtected = true }, + }; + + await sut.PopulateSignsAsync(viewModels); + + Assert.AreEqual(viewModels[0].Signs.Count(), 0); + Assert.AreEqual(viewModels[1].Signs.Count(), 1); + + var signModel = viewModels[1].Signs.First(); + Assert.AreEqual("Umb.IsProtected", signModel.Alias); + } + + [Test] + public async Task IsProtectedSignProvider_Should_Populate_Collection_Signs() + { + var sut = new IsProtectedSignProvider(); + + var viewModels = new List + { + new(), + new() { IsProtected = true }, + }; + + await sut.PopulateSignsAsync(viewModels); + + Assert.AreEqual(viewModels[0].Signs.Count(), 0); + Assert.AreEqual(viewModels[1].Signs.Count(), 1); + + var signModel = viewModels[1].Signs.First(); + Assert.AreEqual("Umb.IsProtected", signModel.Alias); + } + + [Test] + public async Task IsProtectedSignProvider_Should_Populate_Plain_Signs() + { + var sut = new IsProtectedSignProvider(); + + var viewModels = new List + { + new(), + new() { IsProtected = true }, + }; + + await sut.PopulateSignsAsync(viewModels); + + Assert.AreEqual(viewModels[0].Signs.Count(), 0); + Assert.AreEqual(viewModels[1].Signs.Count(), 1); + + var signModel = viewModels[1].Signs.First(); + Assert.AreEqual("Umb.IsProtected", signModel.Alias); + } +}