diff --git a/src/Umbraco.Core/Models/DeliveryApi/ApiLink.cs b/src/Umbraco.Core/Models/DeliveryApi/ApiLink.cs index d255f6ab32..fcfe12b339 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/ApiLink.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/ApiLink.cs @@ -2,19 +2,32 @@ namespace Umbraco.Cms.Core.Models.DeliveryApi; public sealed class ApiLink { + [Obsolete("Please use the overload that accepts a query string. Will be removed in V14.")] public static ApiLink Content(string title, string? target, Guid destinationId, string destinationType, IApiContentRoute route) - => new(LinkType.Content, null, title, target, destinationId, destinationType, route); + => Content(title, queryString: null, target, destinationId, destinationType, route); + public static ApiLink Content(string title, string? queryString, string? target, Guid destinationId, string destinationType, IApiContentRoute route) + => new(LinkType.Content, url: null, queryString, title, target, destinationId, destinationType, route); + + [Obsolete("Please use the overload that accepts a query string. Will be removed in V14.")] public static ApiLink Media(string title, string url, string? target, Guid destinationId, string destinationType) - => new(LinkType.Media, url, title, target, destinationId, destinationType, null); + => Media(title, url, queryString: null, target, destinationId, destinationType); + public static ApiLink Media(string title, string url, string? queryString, string? target, Guid destinationId, string destinationType) + => new(LinkType.Media, url, queryString, title, target, destinationId, destinationType, route: null); + + [Obsolete("Please use the overload that accepts a query string. Will be removed in V14.")] public static ApiLink External(string? title, string url, string? target) - => new(LinkType.External, url, title, target, null, null, null); + => External(title, url, queryString: null, target); - private ApiLink(LinkType linkType, string? url, string? title, string? target, Guid? destinationId, string? destinationType, IApiContentRoute? route) + public static ApiLink External(string? title, string url, string? queryString, string? target) + => new(LinkType.External, url, queryString, title, target, null, null, null); + + private ApiLink(LinkType linkType, string? url, string? queryString, string? title, string? target, Guid? destinationId, string? destinationType, IApiContentRoute? route) { LinkType = linkType; Url = url; + QueryString = queryString; Title = title; Target = target; DestinationId = destinationId; @@ -24,6 +37,8 @@ public sealed class ApiLink public string? Url { get; } + public string? QueryString { get; } + public string? Title { get; } public string? Target { get; } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MultiUrlPickerValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MultiUrlPickerValueConverter.cs index dfc64bdad5..61cc0e1c7d 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MultiUrlPickerValueConverter.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MultiUrlPickerValueConverter.cs @@ -185,6 +185,7 @@ public class MultiUrlPickerValueConverter : PropertyValueConverterBase, IDeliver ? null : ApiLink.Content( item.Name.IfNullOrWhiteSpace(_apiContentNameProvider.GetName(content)), + item.QueryString, item.Target, content.Key, content.ContentType.Alias, @@ -195,12 +196,13 @@ public class MultiUrlPickerValueConverter : PropertyValueConverterBase, IDeliver ? null : ApiLink.Media( item.Name.IfNullOrWhiteSpace(_apiContentNameProvider.GetName(media)), - _apiMediaUrlProvider.GetUrl(media), + $"{_apiMediaUrlProvider.GetUrl(media)}{item.QueryString}", + item.QueryString, item.Target, media.Key, media.ContentType.Alias); default: - return ApiLink.External(item.Name, $"{item.Url}{item.QueryString}", item.Target); + return ApiLink.External(item.Name, $"{item.Url}{item.QueryString}", item.QueryString, item.Target); } } diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/MultiUrlPickerValueConverterTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/MultiUrlPickerValueConverterTests.cs index 818f55861d..a3bd140ce6 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/MultiUrlPickerValueConverterTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/MultiUrlPickerValueConverterTests.cs @@ -157,11 +157,45 @@ public class MultiUrlPickerValueConverterTests : PropertyValueConverterTests var link = result.First(); Assert.AreEqual("The link", link.Title); Assert.AreEqual("https://umbraco.com/?something=true", link.Url); + Assert.AreEqual("?something=true", link.QueryString); Assert.AreEqual(LinkType.External, link.LinkType); Assert.AreEqual("_blank", link.Target); Assert.Null(link.Route); } + [Test] + public void MultiUrlPickerValueConverter_AppliesExplicitConfigurationToMediaLink() + { + var publishedDataType = new PublishedDataType(123, "test", new Lazy(() => new MultiUrlPickerConfiguration { MaxNumber = 1 })); + var publishedPropertyType = new Mock(); + publishedPropertyType.SetupGet(p => p.DataType).Returns(publishedDataType); + + var valueConverter = MultiUrlPickerValueConverter(); + + var inter = Serializer().Serialize(new[] + { + new MultiUrlPickerValueEditor.LinkDto + { + Udi = new GuidUdi(Constants.UdiEntityType.Media, PublishedMedia.Key), + Name = "Custom link name", + QueryString = "?something=true", + Target = "_blank" + } + }); + var result = valueConverter.ConvertIntermediateToDeliveryApiObject(Mock.Of(), publishedPropertyType.Object, PropertyCacheLevel.Element, inter, false, false) as IEnumerable; + Assert.NotNull(result); + Assert.AreEqual(1, result.Count()); + var link = result.First(); + Assert.AreEqual("Custom link name", link.Title); + Assert.AreEqual(PublishedMedia.Key, link.DestinationId); + Assert.AreEqual("TheMediaType", link.DestinationType); + Assert.AreEqual("the-media-url?something=true", link.Url); + Assert.AreEqual(LinkType.Media, link.LinkType); + Assert.AreEqual("_blank", link.Target); + Assert.AreEqual("?something=true", link.QueryString); + Assert.AreEqual(null, link.Route); + } + [Test] public void MultiUrlPickerValueConverter_AppliesExplicitConfigurationToContentLink() { @@ -190,6 +224,7 @@ public class MultiUrlPickerValueConverterTests : PropertyValueConverterTests Assert.AreEqual("/the-page-url", link.Route!.Path); Assert.AreEqual(LinkType.Content, link.LinkType); Assert.AreEqual("_blank", link.Target); + Assert.AreEqual("?something=true", link.QueryString); Assert.Null(link.Url); }