Files
Umbraco-CMS/src/Umbraco.Cms.Api.Management/Controllers/Tree/EntityTreeControllerBase.cs

133 lines
4.8 KiB
C#

using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Entities;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Api.Management.Services.Paging;
using Umbraco.Cms.Api.Management.ViewModels.Pagination;
using Umbraco.Cms.Api.Management.ViewModels.Tree;
using Umbraco.Extensions;
namespace Umbraco.Cms.Api.Management.Controllers.Tree;
public abstract class EntityTreeControllerBase<TItem> : ManagementApiControllerBase
where TItem : EntityTreeItemViewModel, new()
{
private readonly string _itemUdiType;
protected EntityTreeControllerBase(IEntityService entityService)
{
EntityService = entityService;
// ReSharper disable once VirtualMemberCallInConstructor
_itemUdiType = ItemObjectType.GetUdiType();
}
protected IEntityService EntityService { get; }
protected abstract UmbracoObjectTypes ItemObjectType { get; }
protected virtual Ordering ItemOrdering => Ordering.By(nameof(Infrastructure.Persistence.Dtos.NodeDto.Text));
protected async Task<ActionResult<PagedViewModel<TItem>>> GetRoot(int skip, int take)
{
if (PaginationService.ConvertSkipTakeToPaging(skip, take, out var pageNumber, out var pageSize, out ProblemDetails? error) == false)
{
return BadRequest(error);
}
IEntitySlim[] rootEntities = GetPagedRootEntities(pageNumber, pageSize, out var totalItems);
TItem[] treeItemViewModels = MapTreeItemViewModels(null, rootEntities);
PagedViewModel<TItem> result = PagedViewModel(treeItemViewModels, totalItems);
return await Task.FromResult(Ok(result));
}
protected async Task<ActionResult<PagedViewModel<TItem>>> GetChildren(Guid parentKey, int skip, int take)
{
if (PaginationService.ConvertSkipTakeToPaging(skip, take, out var pageNumber, out var pageSize, out ProblemDetails? error) == false)
{
return BadRequest(error);
}
IEntitySlim[] children = GetPagedChildEntities(parentKey, pageNumber, pageSize, out var totalItems);
TItem[] treeItemViewModels = MapTreeItemViewModels(parentKey, children);
PagedViewModel<TItem> result = PagedViewModel(treeItemViewModels, totalItems);
return await Task.FromResult(Ok(result));
}
protected async Task<ActionResult<IEnumerable<TItem>>> GetItems(Guid[] keys)
{
if (keys.IsCollectionEmpty())
{
return await Task.FromResult(Ok(PagedViewModel(Array.Empty<TItem>(), 0)));
}
IEntitySlim[] itemEntities = GetEntities(keys);
TItem[] treeItemViewModels = MapTreeItemViewModels(null, itemEntities);
return await Task.FromResult(Ok(treeItemViewModels));
}
protected virtual IEntitySlim[] GetPagedRootEntities(long pageNumber, int pageSize, out long totalItems)
=> EntityService
.GetPagedChildren(
Constants.System.Root,
ItemObjectType,
pageNumber,
pageSize,
out totalItems,
ordering: ItemOrdering)
.ToArray();
protected virtual IEntitySlim[] GetPagedChildEntities(Guid parentKey, long pageNumber, int pageSize, out long totalItems)
{
// EntityService is only able to get paged children by parent ID, so we must first map parent key to parent ID
Attempt<int> parentId = EntityService.GetId(parentKey, ItemObjectType);
if (parentId.Success == false)
{
// not much else we can do here but return nothing
totalItems = 0;
return Array.Empty<IEntitySlim>();
}
IEntitySlim[] children = EntityService.GetPagedChildren(
parentId.Result,
ItemObjectType,
pageNumber,
pageSize,
out totalItems,
ordering: ItemOrdering)
.ToArray();
return children;
}
protected virtual IEntitySlim[] GetEntities(Guid[] keys) => EntityService.GetAll(ItemObjectType, keys).ToArray();
protected virtual TItem[] MapTreeItemViewModels(Guid? parentKey, IEntitySlim[] entities)
=> entities.Select(entity => MapTreeItemViewModel(parentKey, entity)).ToArray();
protected virtual TItem MapTreeItemViewModel(Guid? parentKey, IEntitySlim entity)
{
var viewModel = new TItem
{
Icon = _itemUdiType,
Name = entity.Name!,
Key = entity.Key,
Type = _itemUdiType,
HasChildren = entity.HasChildren,
IsContainer = entity.IsContainer,
ParentKey = parentKey
};
return viewModel;
}
protected PagedViewModel<TItem> PagedViewModel(IEnumerable<TItem> treeItemViewModels, long totalItems)
=> new() { Total = totalItems, Items = treeItemViewModels };
}