Skip to content

Commit e7ee7c6

Browse files
authored
Fix to GetCultureFromDomains extensions following changes to routing and published content cache (#17884)
1 parent 22e993f commit e7ee7c6

File tree

3 files changed

+106
-16
lines changed

3 files changed

+106
-16
lines changed

src/Umbraco.Core/Routing/DomainUtilities.cs

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
using System.Diagnostics.CodeAnalysis;
22
using System.Globalization;
3+
using Microsoft.Extensions.DependencyInjection;
4+
using Umbraco.Cms.Core.DependencyInjection;
5+
using Umbraco.Cms.Core.Models.PublishedContent;
36
using Umbraco.Cms.Core.PublishedCache;
7+
using Umbraco.Cms.Core.Services.Navigation;
48
using Umbraco.Cms.Core.Web;
59
using Umbraco.Extensions;
610

@@ -27,7 +31,49 @@ public static class DomainUtilities
2731
/// one document per culture), and domains, withing the context of a current Uri, assign
2832
/// a culture to that document.</para>
2933
/// </remarks>
30-
public static string? GetCultureFromDomains(int contentId, string contentPath, Uri? current, IUmbracoContext umbracoContext, ISiteDomainMapper siteDomainMapper)
34+
[Obsolete("Please use the method taking all parameters. This overload will be removed in V17.")]
35+
public static string? GetCultureFromDomains(
36+
int contentId,
37+
string contentPath,
38+
Uri? current,
39+
IUmbracoContext umbracoContext,
40+
ISiteDomainMapper siteDomainMapper)
41+
=> GetCultureFromDomains(
42+
contentId,
43+
contentPath,
44+
current,
45+
umbracoContext,
46+
siteDomainMapper,
47+
StaticServiceProvider.Instance.GetRequiredService<IDomainCache>(),
48+
StaticServiceProvider.Instance.GetRequiredService<IPublishedCache>(),
49+
StaticServiceProvider.Instance.GetRequiredService<INavigationQueryService>());
50+
51+
/// <summary>
52+
/// Gets the culture assigned to a document by domains, in the context of a current Uri.
53+
/// </summary>
54+
/// <param name="contentId">The document identifier.</param>
55+
/// <param name="contentPath">The document path.</param>
56+
/// <param name="current">An optional current Uri.</param>
57+
/// <param name="umbracoContext">An Umbraco context.</param>
58+
/// <param name="siteDomainMapper">The site domain helper.</param>
59+
/// <param name="domainCache">The domain cache.</param>
60+
/// <param name="publishedCache">The published content cache.</param>
61+
/// <param name="navigationQueryService">The navigation query service.</param>
62+
/// <returns>The culture assigned to the document by domains.</returns>
63+
/// <remarks>
64+
/// <para>In 1:1 multilingual setup, a document contains several cultures (there is not
65+
/// one document per culture), and domains, withing the context of a current Uri, assign
66+
/// a culture to that document.</para>
67+
/// </remarks>
68+
public static string? GetCultureFromDomains(
69+
int contentId,
70+
string contentPath,
71+
Uri? current,
72+
IUmbracoContext umbracoContext,
73+
ISiteDomainMapper siteDomainMapper,
74+
IDomainCache domainCache,
75+
IPublishedCache publishedCache,
76+
INavigationQueryService navigationQueryService)
3177
{
3278
if (umbracoContext == null)
3379
{
@@ -39,20 +85,11 @@ public static class DomainUtilities
3985
current = umbracoContext.CleanedUmbracoUrl;
4086
}
4187

42-
// get the published route, else the preview route
43-
// if both are null then the content does not exist
44-
var route = umbracoContext.Content?.GetRouteById(contentId) ??
45-
umbracoContext.Content?.GetRouteById(true, contentId);
88+
var domainNodeId = GetAncestorNodeWithDomainsAssigned(contentId, umbracoContext, domainCache, publishedCache, navigationQueryService);
4689

47-
if (route == null)
48-
{
49-
return null;
50-
}
51-
52-
var pos = route.IndexOf('/');
53-
DomainAndUri? domain = pos == 0
54-
? null
55-
: DomainForNode(umbracoContext.Domains, siteDomainMapper, int.Parse(route.Substring(0, pos), CultureInfo.InvariantCulture), current);
90+
DomainAndUri? domain = domainNodeId.HasValue
91+
? DomainForNode(umbracoContext.Domains, siteDomainMapper, domainNodeId.Value, current)
92+
: null;
5693

5794
var rootContentId = domain?.ContentId ?? -1;
5895
Domain? wcDomain = FindWildcardDomainInPath(umbracoContext.Domains?.GetAll(true), contentPath, rootContentId);
@@ -70,6 +107,22 @@ public static class DomainUtilities
70107
return umbracoContext.Domains?.DefaultCulture;
71108
}
72109

110+
private static int? GetAncestorNodeWithDomainsAssigned(int contentId, IUmbracoContext umbracoContext, IDomainCache domainCache, IPublishedCache publishedCache, INavigationQueryService navigationQueryService)
111+
{
112+
IPublishedContent? content = umbracoContext.Content.GetById(contentId);
113+
var hasDomains = ContentHasAssignedDomains(content, domainCache);
114+
while (content is not null && !hasDomains)
115+
{
116+
content = content.Parent<IPublishedContent>(publishedCache, navigationQueryService);
117+
hasDomains = content is not null && domainCache.HasAssigned(content.Id, true);
118+
}
119+
120+
return content?.Id;
121+
}
122+
123+
private static bool ContentHasAssignedDomains(IPublishedContent? content, IDomainCache domainCache)
124+
=> content is not null && domainCache.HasAssigned(content.Id, true);
125+
73126
#endregion
74127

75128
#region Domain for Document

src/Umbraco.Web.Common/Extensions/FriendlyPublishedContentExtensions.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ public static class FriendlyPublishedContentExtensions
1919
private static IVariationContextAccessor VariationContextAccessor { get; } =
2020
StaticServiceProvider.Instance.GetRequiredService<IVariationContextAccessor>();
2121

22+
private static IDomainCache DomainCache { get; } =
23+
StaticServiceProvider.Instance.GetRequiredService<IDomainCache>();
24+
2225
private static IPublishedContentCache PublishedContentCache { get; } =
2326
StaticServiceProvider.Instance.GetRequiredService<IPublishedContentCache>();
2427

@@ -731,7 +734,7 @@ public static string MediaUrl(
731734
public static string? GetCultureFromDomains(
732735
this IPublishedContent content,
733736
Uri? current = null)
734-
=> content.GetCultureFromDomains(UmbracoContextAccessor, SiteDomainHelper, current);
737+
=> content.GetCultureFromDomains(UmbracoContextAccessor, SiteDomainHelper, DomainCache, PublishedContentCache, DocumentNavigationQueryService, current);
735738

736739
public static IEnumerable<PublishedSearchResult> SearchDescendants(
737740
this IPublishedContent content,

src/Umbraco.Web.Common/Extensions/PublishedContentExtensions.cs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
using Microsoft.AspNetCore.Html;
55
using Umbraco.Cms.Core;
66
using Umbraco.Cms.Core.Models.PublishedContent;
7+
using Umbraco.Cms.Core.PublishedCache;
78
using Umbraco.Cms.Core.Routing;
89
using Umbraco.Cms.Core.Services;
10+
using Umbraco.Cms.Core.Services.Navigation;
911
using Umbraco.Cms.Core.Web;
1012
using Umbraco.Cms.Infrastructure.Examine;
1113

@@ -20,7 +22,7 @@ public static class PublishedContentExtensions
2022
/// </summary>
2123
/// <param name="content">The document.</param>
2224
/// <param name="umbracoContextAccessor"></param>
23-
/// <param name="siteDomainHelper"></param>
25+
/// <param name="siteDomainHelper">The site domain helper.</param>
2426
/// <param name="current">An optional current Uri.</param>
2527
/// <returns>The culture assigned to the document by domains.</returns>
2628
/// <remarks>
@@ -30,6 +32,7 @@ public static class PublishedContentExtensions
3032
/// a culture to that document.
3133
/// </para>
3234
/// </remarks>
35+
[Obsolete("Please use the method taking all parameters. This overload will be removed in V17.")]
3336
public static string? GetCultureFromDomains(
3437
this IPublishedContent content,
3538
IUmbracoContextAccessor umbracoContextAccessor,
@@ -40,6 +43,37 @@ public static class PublishedContentExtensions
4043
return DomainUtilities.GetCultureFromDomains(content.Id, content.Path, current, umbracoContext, siteDomainHelper);
4144
}
4245

46+
/// <summary>
47+
/// Gets the culture assigned to a document by domains, in the context of a current Uri.
48+
/// </summary>
49+
/// <param name="content">The document.</param>
50+
/// <param name="umbracoContextAccessor"></param>
51+
/// <param name="siteDomainHelper">The site domain helper.</param>
52+
/// <param name="domainCache">The domain cache.</param>
53+
/// <param name="publishedCache">The published content cache.</param>
54+
/// <param name="navigationQueryService">The navigation query service.</param>
55+
/// <param name="current">An optional current Uri.</param>
56+
/// <returns>The culture assigned to the document by domains.</returns>
57+
/// <remarks>
58+
/// <para>
59+
/// In 1:1 multilingual setup, a document contains several cultures (there is not
60+
/// one document per culture), and domains, withing the context of a current Uri, assign
61+
/// a culture to that document.
62+
/// </para>
63+
/// </remarks>
64+
public static string? GetCultureFromDomains(
65+
this IPublishedContent content,
66+
IUmbracoContextAccessor umbracoContextAccessor,
67+
ISiteDomainMapper siteDomainHelper,
68+
IDomainCache domainCache,
69+
IPublishedCache publishedCache,
70+
INavigationQueryService navigationQueryService,
71+
Uri? current = null)
72+
{
73+
IUmbracoContext umbracoContext = umbracoContextAccessor.GetRequiredUmbracoContext();
74+
return DomainUtilities.GetCultureFromDomains(content.Id, content.Path, current, umbracoContext, siteDomainHelper, domainCache, publishedCache, navigationQueryService);
75+
}
76+
4377
#endregion
4478

4579
#region Creator/Writer Names

0 commit comments

Comments
 (0)