11using System . Diagnostics . CodeAnalysis ;
22using System . Globalization ;
3+ using Microsoft . Extensions . DependencyInjection ;
4+ using Umbraco . Cms . Core . DependencyInjection ;
5+ using Umbraco . Cms . Core . Models . PublishedContent ;
36using Umbraco . Cms . Core . PublishedCache ;
7+ using Umbraco . Cms . Core . Services . Navigation ;
48using Umbraco . Cms . Core . Web ;
59using 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
0 commit comments