diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Document/DocumentUrlController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Document/DocumentUrlController.cs new file mode 100644 index 000000000000..9d0b88a2e105 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Controllers/Document/DocumentUrlController.cs @@ -0,0 +1,35 @@ +using Asp.Versioning; +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.Models; +using Umbraco.Cms.Core.Services; +using Umbraco.Extensions; + +namespace Umbraco.Cms.Api.Management.Controllers.Document; + +[ApiVersion("1.0")] +public class DocumentUrlController : DocumentControllerBase +{ + private readonly IContentService _contentService; + private readonly IDocumentUrlFactory _documentUrlFactory; + + public DocumentUrlController( + IContentService contentService, + IDocumentUrlFactory documentUrlFactory) + { + _contentService = contentService; + _documentUrlFactory = documentUrlFactory; + } + + [MapToApiVersion("1.0")] + [HttpGet("urls")] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + public async Task GetUrls([FromQuery(Name = "id")] HashSet ids) + { + IEnumerable items = _contentService.GetByIds(ids); + + return Ok(await _documentUrlFactory.CreateUrlSetsAsync(items)); + } +} diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Media/ByKeyMediaController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Media/ByKeyMediaController.cs index 3f00e7f17e60..35d2468e39fe 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/Media/ByKeyMediaController.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/Media/ByKeyMediaController.cs @@ -52,7 +52,7 @@ public async Task ByKey(CancellationToken cancellationToken, Guid return MediaNotFound(); } - MediaResponseModel model = await _mediaPresentationFactory.CreateResponseModelAsync(media); + MediaResponseModel model = _mediaPresentationFactory.CreateResponseModel(media); return Ok(model); } } diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Media/MediaUrlController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Media/MediaUrlController.cs new file mode 100644 index 000000000000..1edd8d40553c --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Controllers/Media/MediaUrlController.cs @@ -0,0 +1,34 @@ +using Asp.Versioning; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Umbraco.Cms.Api.Management.Factories; +using Umbraco.Cms.Api.Management.ViewModels.Media; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Services; + +namespace Umbraco.Cms.Api.Management.Controllers.Media; + +[ApiVersion("1.0")] +public class MediaUrlController : MediaControllerBase +{ + private readonly IMediaService _mediaService; + private readonly IMediaUrlFactory _mediaUrlFactory; + + public MediaUrlController( + IMediaService mediaService, + IMediaUrlFactory mediaUrlFactory) + { + _mediaService = mediaService; + _mediaUrlFactory = mediaUrlFactory; + } + + [MapToApiVersion("1.0")] + [HttpGet("urls")] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + public ActionResult GetUrls([FromQuery(Name = "id")] HashSet ids) + { + IEnumerable items = _mediaService.GetByIds(ids); + + return Ok(_mediaUrlFactory.CreateUrlSets(items)); + } +} diff --git a/src/Umbraco.Cms.Api.Management/DependencyInjection/MediaBuilderExtensions.cs b/src/Umbraco.Cms.Api.Management/DependencyInjection/MediaBuilderExtensions.cs index 4cdf2f6e140b..59dc5063eedb 100644 --- a/src/Umbraco.Cms.Api.Management/DependencyInjection/MediaBuilderExtensions.cs +++ b/src/Umbraco.Cms.Api.Management/DependencyInjection/MediaBuilderExtensions.cs @@ -15,6 +15,7 @@ internal static IUmbracoBuilder AddMedia(this IUmbracoBuilder builder) builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); + builder.Services.AddTransient(); builder.Services.AddScoped(); builder.WithCollectionBuilder().Add(); diff --git a/src/Umbraco.Cms.Api.Management/Factories/DocumentPresentationFactory.cs b/src/Umbraco.Cms.Api.Management/Factories/DocumentPresentationFactory.cs index d6dbb4d45ed0..c6291f4db07d 100644 --- a/src/Umbraco.Cms.Api.Management/Factories/DocumentPresentationFactory.cs +++ b/src/Umbraco.Cms.Api.Management/Factories/DocumentPresentationFactory.cs @@ -41,7 +41,7 @@ public async Task CreateResponseModelAsync(IContent conte { DocumentResponseModel responseModel = _umbracoMapper.Map(content)!; - responseModel.Urls = await _documentUrlFactory.GetUrlsAsync(content); + responseModel.Urls = await _documentUrlFactory.CreateUrlsAsync(content); Guid? templateKey = content.TemplateId.HasValue ? _templateService.GetAsync(content.TemplateId.Value).Result?.Key diff --git a/src/Umbraco.Cms.Api.Management/Factories/DocumentUrlFactory.cs b/src/Umbraco.Cms.Api.Management/Factories/DocumentUrlFactory.cs index 84beb18134b4..cee548ed5ca5 100644 --- a/src/Umbraco.Cms.Api.Management/Factories/DocumentUrlFactory.cs +++ b/src/Umbraco.Cms.Api.Management/Factories/DocumentUrlFactory.cs @@ -44,11 +44,11 @@ public DocumentUrlFactory( _publishedUrlProvider = publishedUrlProvider; } - public async Task> GetUrlsAsync(IContent content) + public async Task> CreateUrlsAsync(IContent content) { IUmbracoContext umbracoContext = _umbracoContextAccessor.GetRequiredUmbracoContext(); - UrlInfo[] urlInfos = (await content.GetContentUrlsAsync( + IEnumerable urlInfos = await content.GetContentUrlsAsync( _publishedRouter, umbracoContext, _languageService, @@ -57,11 +57,24 @@ public async Task> GetUrlsAsync(IContent content) _variationContextAccessor, _loggerFactory.CreateLogger(), _uriUtility, - _publishedUrlProvider)).ToArray(); + _publishedUrlProvider); return urlInfos .Where(urlInfo => urlInfo.IsUrl) .Select(urlInfo => new DocumentUrlInfo { Culture = urlInfo.Culture, Url = urlInfo.Text }) .ToArray(); } + + public async Task> CreateUrlSetsAsync(IEnumerable contentItems) + { + var documentUrlInfoResourceSets = new List(); + + foreach (IContent content in contentItems) + { + IEnumerable urls = await CreateUrlsAsync(content); + documentUrlInfoResourceSets.Add(new DocumentUrlInfoResponseModel(content.Key, urls)); + } + + return documentUrlInfoResourceSets; + } } diff --git a/src/Umbraco.Cms.Api.Management/Factories/IDocumentUrlFactory.cs b/src/Umbraco.Cms.Api.Management/Factories/IDocumentUrlFactory.cs index aa550961177a..f87a0aaec8bf 100644 --- a/src/Umbraco.Cms.Api.Management/Factories/IDocumentUrlFactory.cs +++ b/src/Umbraco.Cms.Api.Management/Factories/IDocumentUrlFactory.cs @@ -5,5 +5,6 @@ namespace Umbraco.Cms.Api.Management.Factories; public interface IDocumentUrlFactory { - Task> GetUrlsAsync(IContent content); + Task> CreateUrlsAsync(IContent content); + Task> CreateUrlSetsAsync(IEnumerable contentItems); } diff --git a/src/Umbraco.Cms.Api.Management/Factories/IMediaPresentationFactory.cs b/src/Umbraco.Cms.Api.Management/Factories/IMediaPresentationFactory.cs index 76faa64dbc65..a0ed0e7c4a49 100644 --- a/src/Umbraco.Cms.Api.Management/Factories/IMediaPresentationFactory.cs +++ b/src/Umbraco.Cms.Api.Management/Factories/IMediaPresentationFactory.cs @@ -9,7 +9,7 @@ namespace Umbraco.Cms.Api.Management.Factories; public interface IMediaPresentationFactory { - Task CreateResponseModelAsync(IMedia media); + MediaResponseModel CreateResponseModel(IMedia media); MediaItemResponseModel CreateItemResponseModel(IMediaEntitySlim entity); diff --git a/src/Umbraco.Cms.Api.Management/Factories/IMediaUrlFactory.cs b/src/Umbraco.Cms.Api.Management/Factories/IMediaUrlFactory.cs new file mode 100644 index 000000000000..a15905edb3b5 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Factories/IMediaUrlFactory.cs @@ -0,0 +1,10 @@ +using Umbraco.Cms.Api.Management.ViewModels.Media; +using Umbraco.Cms.Core.Models; + +namespace Umbraco.Cms.Api.Management.Factories; + +public interface IMediaUrlFactory +{ + IEnumerable CreateUrls(IMedia media); + IEnumerable CreateUrlSets(IEnumerable mediaItems); +} diff --git a/src/Umbraco.Cms.Api.Management/Factories/MediaPresentationFactory.cs b/src/Umbraco.Cms.Api.Management/Factories/MediaPresentationFactory.cs index e6155a19a7a8..7948e0d01936 100644 --- a/src/Umbraco.Cms.Api.Management/Factories/MediaPresentationFactory.cs +++ b/src/Umbraco.Cms.Api.Management/Factories/MediaPresentationFactory.cs @@ -1,53 +1,33 @@ -using Microsoft.Extensions.Options; -using Umbraco.Cms.Api.Management.Routing; -using Umbraco.Cms.Api.Management.ViewModels.Content; +using Umbraco.Cms.Api.Management.ViewModels.Content; using Umbraco.Cms.Api.Management.ViewModels.Media; using Umbraco.Cms.Api.Management.ViewModels.Media.Item; using Umbraco.Cms.Api.Management.ViewModels.MediaType; -using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Mapping; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Entities; -using Umbraco.Cms.Core.PropertyEditors; -using Umbraco.Cms.Core.Services; -using Umbraco.Extensions; namespace Umbraco.Cms.Api.Management.Factories; internal sealed class MediaPresentationFactory : IMediaPresentationFactory { private readonly IUmbracoMapper _umbracoMapper; - private readonly ContentSettings _contentSettings; - private readonly MediaUrlGeneratorCollection _mediaUrlGenerators; - private readonly IAbsoluteUrlBuilder _absoluteUrlBuilder; + private readonly IMediaUrlFactory _mediaUrlFactory; public MediaPresentationFactory( IUmbracoMapper umbracoMapper, - IOptions contentSettings, - MediaUrlGeneratorCollection mediaUrlGenerators, - IAbsoluteUrlBuilder absoluteUrlBuilder) + IMediaUrlFactory mediaUrlFactory) { _umbracoMapper = umbracoMapper; - _contentSettings = contentSettings.Value; - _mediaUrlGenerators = mediaUrlGenerators; - _absoluteUrlBuilder = absoluteUrlBuilder; + _mediaUrlFactory = mediaUrlFactory; } - public Task CreateResponseModelAsync(IMedia media) + public MediaResponseModel CreateResponseModel(IMedia media) { MediaResponseModel responseModel = _umbracoMapper.Map(media)!; - responseModel.Urls = media - .GetUrls(_contentSettings, _mediaUrlGenerators) - .WhereNotNull() - .Select(mediaUrl => new MediaUrlInfo - { - Culture = null, - Url = _absoluteUrlBuilder.ToAbsoluteUrl(mediaUrl).ToString(), - }) - .ToArray(); + responseModel.Urls = _mediaUrlFactory.CreateUrls(media); - return Task.FromResult(responseModel); + return responseModel; } public MediaItemResponseModel CreateItemResponseModel(IMediaEntitySlim entity) diff --git a/src/Umbraco.Cms.Api.Management/Factories/MediaUrlFactory.cs b/src/Umbraco.Cms.Api.Management/Factories/MediaUrlFactory.cs new file mode 100644 index 000000000000..b1e9406289db --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Factories/MediaUrlFactory.cs @@ -0,0 +1,48 @@ +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Umbraco.Cms.Api.Management.Routing; +using Umbraco.Cms.Api.Management.ViewModels.Content; +using Umbraco.Cms.Api.Management.ViewModels.Document; +using Umbraco.Cms.Api.Management.ViewModels.Media; +using Umbraco.Cms.Core.Configuration.Models; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models.PublishedContent; +using Umbraco.Cms.Core.PropertyEditors; +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 MediaUrlFactory : IMediaUrlFactory +{ + private readonly ContentSettings _contentSettings; + private readonly MediaUrlGeneratorCollection _mediaUrlGenerators; + private readonly IAbsoluteUrlBuilder _absoluteUrlBuilder; + + + public MediaUrlFactory( + IOptions contentSettings, + MediaUrlGeneratorCollection mediaUrlGenerators, + IAbsoluteUrlBuilder absoluteUrlBuilder) + { + _contentSettings = contentSettings.Value; + _mediaUrlGenerators = mediaUrlGenerators; + _absoluteUrlBuilder = absoluteUrlBuilder; + } + + public IEnumerable CreateUrls(IMedia media) => + media + .GetUrls(_contentSettings, _mediaUrlGenerators) + .WhereNotNull() + .Select(mediaUrl => new MediaUrlInfo + { + Culture = null, + Url = _absoluteUrlBuilder.ToAbsoluteUrl(mediaUrl).ToString(), + }) + .ToArray(); + + public IEnumerable CreateUrlSets(IEnumerable mediaItems) => + mediaItems.Select(media => new MediaUrlInfoResponseModel(media.Key, CreateUrls(media))).ToArray(); +} diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/Document/DocumentUrlInfoResponseModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/Document/DocumentUrlInfoResponseModel.cs new file mode 100644 index 000000000000..dc8a501d163f --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/ViewModels/Document/DocumentUrlInfoResponseModel.cs @@ -0,0 +1,14 @@ +namespace Umbraco.Cms.Api.Management.ViewModels.Document; + +public sealed class DocumentUrlInfoResponseModel +{ + public DocumentUrlInfoResponseModel(Guid id, IEnumerable urlInfos) + { + Id = id; + UrlInfos = urlInfos; + } + + public Guid Id { get; } + + public IEnumerable UrlInfos { get; } +} diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/Media/MediaUrlInfoResponseModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/Media/MediaUrlInfoResponseModel.cs new file mode 100644 index 000000000000..f65231bb47e6 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/ViewModels/Media/MediaUrlInfoResponseModel.cs @@ -0,0 +1,14 @@ +namespace Umbraco.Cms.Api.Management.ViewModels.Media; + +public sealed class MediaUrlInfoResponseModel +{ + public MediaUrlInfoResponseModel(Guid id, IEnumerable urlInfos) + { + Id = id; + UrlInfos = urlInfos; + } + + public Guid Id { get; } + + public IEnumerable UrlInfos { get; } +}