Add URLs and template data to document view model

This commit is contained in:
kjac
2023-02-04 13:21:34 +01:00
parent 0d7d8edaae
commit c88d00797a
10 changed files with 155 additions and 13 deletions

View File

@@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Api.Management.ViewModels.Document;
using Umbraco.Cms.Core.Mapping;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
@@ -10,12 +10,12 @@ namespace Umbraco.Cms.Api.Management.Controllers.Document;
public class ByKeyDocumentController : DocumentControllerBase
{
private readonly IContentService _contentService;
private readonly IUmbracoMapper _umbracoMapper;
private readonly IDocumentViewModelFactory _documentViewModelFactory;
public ByKeyDocumentController(IContentService contentService, IUmbracoMapper umbracoMapper)
public ByKeyDocumentController(IContentService contentService, IDocumentViewModelFactory documentViewModelFactory)
{
_contentService = contentService;
_umbracoMapper = umbracoMapper;
_documentViewModelFactory = documentViewModelFactory;
}
[HttpGet("{key:guid}")]
@@ -30,7 +30,7 @@ public class ByKeyDocumentController : DocumentControllerBase
return NotFound();
}
DocumentViewModel model = _umbracoMapper.Map<DocumentViewModel>(content)!;
return await Task.FromResult(Ok(model));
DocumentViewModel model = await _documentViewModelFactory.CreateViewModelAsync(content);
return Ok(model);
}
}

View File

@@ -1,4 +1,6 @@
using Umbraco.Cms.Api.Management.Mapping.Document;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Api.Management.Mapping.Document;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Mapping;
@@ -8,6 +10,9 @@ internal static class DocumentBuilderExtensions
{
internal static IUmbracoBuilder AddDocuments(this IUmbracoBuilder builder)
{
builder.Services.AddTransient<IDocumentViewModelFactory, DocumentViewModelFactory>();
builder.Services.AddTransient<IDocumentUrlFactory, DocumentUrlFactory>();
builder.WithCollectionBuilder<MapDefinitionCollectionBuilder>().Add<DocumentMapDefinition>();
return builder;

View File

@@ -0,0 +1,70 @@
using Microsoft.Extensions.Logging;
using Umbraco.Cms.Api.Management.ViewModels.Document;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Web;
using Umbraco.Extensions;
namespace Umbraco.Cms.Api.Management.Factories;
public class DocumentUrlFactory : IDocumentUrlFactory
{
private readonly IPublishedRouter _publishedRouter;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly ILanguageService _languageService;
private readonly ILocalizedTextService _localizedTextService;
private readonly IContentService _contentService;
private readonly IVariationContextAccessor _variationContextAccessor;
private readonly ILoggerFactory _loggerFactory;
private readonly UriUtility _uriUtility;
private readonly IPublishedUrlProvider _publishedUrlProvider;
public DocumentUrlFactory(
IPublishedRouter publishedRouter,
IUmbracoContextAccessor umbracoContextAccessor,
ILanguageService languageService,
ILocalizedTextService localizedTextService,
IContentService contentService,
IVariationContextAccessor variationContextAccessor,
ILoggerFactory loggerFactory,
UriUtility uriUtility,
IPublishedUrlProvider publishedUrlProvider)
{
_publishedRouter = publishedRouter;
_umbracoContextAccessor = umbracoContextAccessor;
_languageService = languageService;
_localizedTextService = localizedTextService;
_contentService = contentService;
_variationContextAccessor = variationContextAccessor;
_loggerFactory = loggerFactory;
_uriUtility = uriUtility;
_publishedUrlProvider = publishedUrlProvider;
}
public async Task<IEnumerable<DocumentUrlInfo>> GetUrlsAsync(IContent content)
{
if (_umbracoContextAccessor.TryGetUmbracoContext(out IUmbracoContext? umbracoContext) == false)
{
_loggerFactory.CreateLogger<DocumentUrlFactory>().LogWarning($"Unable to create an Umbraco context while attempting to get URLs for content: {content.Key}");
return Array.Empty<DocumentUrlInfo>();
}
UrlInfo[] urlInfos = (await content.GetContentUrlsAsync(
_publishedRouter,
umbracoContext,
_languageService,
_localizedTextService,
_contentService,
_variationContextAccessor,
_loggerFactory.CreateLogger<IContent>(),
_uriUtility,
_publishedUrlProvider)).ToArray();
return urlInfos
.Where(urlInfo => urlInfo.IsUrl)
.Select(urlInfo => new DocumentUrlInfo { Culture = urlInfo.Culture, Url = urlInfo.Text })
.ToArray();
}
}

View File

@@ -0,0 +1,36 @@
using Umbraco.Cms.Api.Management.ViewModels.Document;
using Umbraco.Cms.Core.Mapping;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
namespace Umbraco.Cms.Api.Management.Factories;
public class DocumentViewModelFactory : IDocumentViewModelFactory
{
private readonly IUmbracoMapper _umbracoMapper;
private readonly IDocumentUrlFactory _documentUrlFactory;
private readonly IFileService _fileService;
public DocumentViewModelFactory(
IUmbracoMapper umbracoMapper,
IDocumentUrlFactory documentUrlFactory,
IFileService fileService)
{
_umbracoMapper = umbracoMapper;
_documentUrlFactory = documentUrlFactory;
_fileService = fileService;
}
public async Task<DocumentViewModel> CreateViewModelAsync(IContent content)
{
DocumentViewModel viewModel = _umbracoMapper.Map<DocumentViewModel>(content)!;
viewModel.Urls = await _documentUrlFactory.GetUrlsAsync(content);
viewModel.TemplateKey = content.TemplateId.HasValue
? _fileService.GetTemplate(content.TemplateId.Value)?.Key
: null;
return viewModel;
}
}

View File

@@ -0,0 +1,10 @@
using Umbraco.Cms.Api.Management.ViewModels.Document;
using Umbraco.Cms.Core.Models;
namespace Umbraco.Cms.Api.Management.Factories;
// FIXME: rename to IContentUrlFactory if we want to prepare media etc. for variations
public interface IDocumentUrlFactory
{
Task<IEnumerable<DocumentUrlInfo>> GetUrlsAsync(IContent content);
}

View File

@@ -0,0 +1,9 @@
using Umbraco.Cms.Api.Management.ViewModels.Document;
using Umbraco.Cms.Core.Models;
namespace Umbraco.Cms.Api.Management.Factories;
public interface IDocumentViewModelFactory
{
Task<DocumentViewModel> CreateViewModelAsync(IContent content);
}

View File

@@ -17,7 +17,7 @@ public class DocumentMapDefinition : ContentMapDefinition<IContent, DocumentProp
public void DefineMaps(IUmbracoMapper mapper)
=> mapper.Define<IContent, DocumentViewModel>((_, _) => new DocumentViewModel(), Map);
// Umbraco.Code.MapAll
// Umbraco.Code.MapAll -Urls -TemplateKey
private void Map(IContent source, DocumentViewModel target, MapperContext context)
{
target.Key = source.Key;

View File

@@ -1,14 +1,14 @@
namespace Umbraco.Cms.Api.Management.ViewModels.Content;
public abstract class ContentViewModelBase<TProperty, TVariant>
where TProperty : PropertyViewModelBase
where TVariant: VariantViewModelBase
public abstract class ContentViewModelBase<TPropertyViewModel, TVariantViewModel>
where TPropertyViewModel : PropertyViewModelBase
where TVariantViewModel: VariantViewModelBase
{
public Guid Key { get; set; }
public Guid ContentTypeKey { get; set; }
public IEnumerable<TProperty> Properties { get; set; } = Array.Empty<TProperty>();
public IEnumerable<TPropertyViewModel> Properties { get; set; } = Array.Empty<TPropertyViewModel>();
public IEnumerable<TVariant> Variants { get; set; } = Array.Empty<TVariant>();
public IEnumerable<TVariantViewModel> Variants { get; set; } = Array.Empty<TVariantViewModel>();
}

View File

@@ -0,0 +1,9 @@
namespace Umbraco.Cms.Api.Management.ViewModels.Document;
// FIXME: rename to ContentUrlInfo and move to .Content namespace if we want to prepare media etc. for variations
public class DocumentUrlInfo
{
public required string? Culture { get; init; }
public required string Url { get; init; }
}

View File

@@ -4,4 +4,7 @@ namespace Umbraco.Cms.Api.Management.ViewModels.Document;
public class DocumentViewModel : ContentViewModelBase<DocumentPropertyViewModel, DocumentVariantViewModel>
{
public IEnumerable<DocumentUrlInfo> Urls { get; set; } = Array.Empty<DocumentUrlInfo>();
public Guid? TemplateKey { get; set; }
}