diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Document/ByKeyDocumentController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Document/ByKeyDocumentController.cs index 2b078f9dd7..a9a60196a0 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Document/ByKeyDocumentController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Document/ByKeyDocumentController.cs @@ -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(content)!; - return await Task.FromResult(Ok(model)); + DocumentViewModel model = await _documentViewModelFactory.CreateViewModelAsync(content); + return Ok(model); } } diff --git a/src/Umbraco.Cms.Api.Management/DependencyInjection/DocumentBuilderExtensions.cs b/src/Umbraco.Cms.Api.Management/DependencyInjection/DocumentBuilderExtensions.cs index 6fa6e02a04..826325c56b 100644 --- a/src/Umbraco.Cms.Api.Management/DependencyInjection/DocumentBuilderExtensions.cs +++ b/src/Umbraco.Cms.Api.Management/DependencyInjection/DocumentBuilderExtensions.cs @@ -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(); + builder.Services.AddTransient(); + builder.WithCollectionBuilder().Add(); return builder; diff --git a/src/Umbraco.Cms.Api.Management/Factories/DocumentUrlFactory.cs b/src/Umbraco.Cms.Api.Management/Factories/DocumentUrlFactory.cs new file mode 100644 index 0000000000..260be6b47b --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Factories/DocumentUrlFactory.cs @@ -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> GetUrlsAsync(IContent content) + { + if (_umbracoContextAccessor.TryGetUmbracoContext(out IUmbracoContext? umbracoContext) == false) + { + _loggerFactory.CreateLogger().LogWarning($"Unable to create an Umbraco context while attempting to get URLs for content: {content.Key}"); + return Array.Empty(); + } + + UrlInfo[] urlInfos = (await content.GetContentUrlsAsync( + _publishedRouter, + umbracoContext, + _languageService, + _localizedTextService, + _contentService, + _variationContextAccessor, + _loggerFactory.CreateLogger(), + _uriUtility, + _publishedUrlProvider)).ToArray(); + + return urlInfos + .Where(urlInfo => urlInfo.IsUrl) + .Select(urlInfo => new DocumentUrlInfo { Culture = urlInfo.Culture, Url = urlInfo.Text }) + .ToArray(); + } +} diff --git a/src/Umbraco.Cms.Api.Management/Factories/DocumentViewModelFactory.cs b/src/Umbraco.Cms.Api.Management/Factories/DocumentViewModelFactory.cs new file mode 100644 index 0000000000..68819f5af7 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Factories/DocumentViewModelFactory.cs @@ -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 CreateViewModelAsync(IContent content) + { + DocumentViewModel viewModel = _umbracoMapper.Map(content)!; + + viewModel.Urls = await _documentUrlFactory.GetUrlsAsync(content); + + viewModel.TemplateKey = content.TemplateId.HasValue + ? _fileService.GetTemplate(content.TemplateId.Value)?.Key + : null; + + return viewModel; + } +} diff --git a/src/Umbraco.Cms.Api.Management/Factories/IDocumentUrlFactory.cs b/src/Umbraco.Cms.Api.Management/Factories/IDocumentUrlFactory.cs new file mode 100644 index 0000000000..ab6c83776e --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Factories/IDocumentUrlFactory.cs @@ -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> GetUrlsAsync(IContent content); +} diff --git a/src/Umbraco.Cms.Api.Management/Factories/IDocumentViewModelFactory.cs b/src/Umbraco.Cms.Api.Management/Factories/IDocumentViewModelFactory.cs new file mode 100644 index 0000000000..46da5746b6 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Factories/IDocumentViewModelFactory.cs @@ -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 CreateViewModelAsync(IContent content); +} diff --git a/src/Umbraco.Cms.Api.Management/Mapping/Document/DocumentMapDefinition.cs b/src/Umbraco.Cms.Api.Management/Mapping/Document/DocumentMapDefinition.cs index 6051a093ac..13dacd46a9 100644 --- a/src/Umbraco.Cms.Api.Management/Mapping/Document/DocumentMapDefinition.cs +++ b/src/Umbraco.Cms.Api.Management/Mapping/Document/DocumentMapDefinition.cs @@ -17,7 +17,7 @@ public class DocumentMapDefinition : ContentMapDefinition mapper.Define((_, _) => new DocumentViewModel(), Map); - // Umbraco.Code.MapAll + // Umbraco.Code.MapAll -Urls -TemplateKey private void Map(IContent source, DocumentViewModel target, MapperContext context) { target.Key = source.Key; diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/Content/ContentViewModelBase.cs b/src/Umbraco.Cms.Api.Management/ViewModels/Content/ContentViewModelBase.cs index 854e28131d..ab29cd5088 100644 --- a/src/Umbraco.Cms.Api.Management/ViewModels/Content/ContentViewModelBase.cs +++ b/src/Umbraco.Cms.Api.Management/ViewModels/Content/ContentViewModelBase.cs @@ -1,14 +1,14 @@ namespace Umbraco.Cms.Api.Management.ViewModels.Content; -public abstract class ContentViewModelBase - where TProperty : PropertyViewModelBase - where TVariant: VariantViewModelBase +public abstract class ContentViewModelBase + where TPropertyViewModel : PropertyViewModelBase + where TVariantViewModel: VariantViewModelBase { public Guid Key { get; set; } public Guid ContentTypeKey { get; set; } - public IEnumerable Properties { get; set; } = Array.Empty(); + public IEnumerable Properties { get; set; } = Array.Empty(); - public IEnumerable Variants { get; set; } = Array.Empty(); + public IEnumerable Variants { get; set; } = Array.Empty(); } diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/Document/DocumentUrlInfo.cs b/src/Umbraco.Cms.Api.Management/ViewModels/Document/DocumentUrlInfo.cs new file mode 100644 index 0000000000..e19588b442 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/ViewModels/Document/DocumentUrlInfo.cs @@ -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; } +} diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/Document/DocumentViewModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/Document/DocumentViewModel.cs index 67afeaa557..556a6ea6f2 100644 --- a/src/Umbraco.Cms.Api.Management/ViewModels/Document/DocumentViewModel.cs +++ b/src/Umbraco.Cms.Api.Management/ViewModels/Document/DocumentViewModel.cs @@ -4,4 +4,7 @@ namespace Umbraco.Cms.Api.Management.ViewModels.Document; public class DocumentViewModel : ContentViewModelBase { + public IEnumerable Urls { get; set; } = Array.Empty(); + + public Guid? TemplateKey { get; set; } }