Fix to GetCultureFromDomains extensions following changes to routing and published content cache (#17884)

This commit is contained in:
Andy Butland
2025-01-08 10:29:06 +01:00
committed by GitHub
parent 22e993f44c
commit e7ee7c63c3
3 changed files with 107 additions and 17 deletions

View File

@@ -1,6 +1,10 @@
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Services.Navigation;
using Umbraco.Cms.Core.Web;
using Umbraco.Extensions;
@@ -27,7 +31,49 @@ namespace Umbraco.Cms.Core.Routing
/// one document per culture), and domains, withing the context of a current Uri, assign
/// a culture to that document.</para>
/// </remarks>
public static string? GetCultureFromDomains(int contentId, string contentPath, Uri? current, IUmbracoContext umbracoContext, ISiteDomainMapper siteDomainMapper)
[Obsolete("Please use the method taking all parameters. This overload will be removed in V17.")]
public static string? GetCultureFromDomains(
int contentId,
string contentPath,
Uri? current,
IUmbracoContext umbracoContext,
ISiteDomainMapper siteDomainMapper)
=> GetCultureFromDomains(
contentId,
contentPath,
current,
umbracoContext,
siteDomainMapper,
StaticServiceProvider.Instance.GetRequiredService<IDomainCache>(),
StaticServiceProvider.Instance.GetRequiredService<IPublishedCache>(),
StaticServiceProvider.Instance.GetRequiredService<INavigationQueryService>());
/// <summary>
/// Gets the culture assigned to a document by domains, in the context of a current Uri.
/// </summary>
/// <param name="contentId">The document identifier.</param>
/// <param name="contentPath">The document path.</param>
/// <param name="current">An optional current Uri.</param>
/// <param name="umbracoContext">An Umbraco context.</param>
/// <param name="siteDomainMapper">The site domain helper.</param>
/// <param name="domainCache">The domain cache.</param>
/// <param name="publishedCache">The published content cache.</param>
/// <param name="navigationQueryService">The navigation query service.</param>
/// <returns>The culture assigned to the document by domains.</returns>
/// <remarks>
/// <para>In 1:1 multilingual setup, a document contains several cultures (there is not
/// one document per culture), and domains, withing the context of a current Uri, assign
/// a culture to that document.</para>
/// </remarks>
public static string? GetCultureFromDomains(
int contentId,
string contentPath,
Uri? current,
IUmbracoContext umbracoContext,
ISiteDomainMapper siteDomainMapper,
IDomainCache domainCache,
IPublishedCache publishedCache,
INavigationQueryService navigationQueryService)
{
if (umbracoContext == null)
{
@@ -39,20 +85,11 @@ namespace Umbraco.Cms.Core.Routing
current = umbracoContext.CleanedUmbracoUrl;
}
// get the published route, else the preview route
// if both are null then the content does not exist
var route = umbracoContext.Content?.GetRouteById(contentId) ??
umbracoContext.Content?.GetRouteById(true, contentId);
var domainNodeId = GetAncestorNodeWithDomainsAssigned(contentId, umbracoContext, domainCache, publishedCache, navigationQueryService);
if (route == null)
{
return null;
}
var pos = route.IndexOf('/');
DomainAndUri? domain = pos == 0
? null
: DomainForNode(umbracoContext.Domains, siteDomainMapper, int.Parse(route.Substring(0, pos), CultureInfo.InvariantCulture), current);
DomainAndUri? domain = domainNodeId.HasValue
? DomainForNode(umbracoContext.Domains, siteDomainMapper, domainNodeId.Value, current)
: null;
var rootContentId = domain?.ContentId ?? -1;
Domain? wcDomain = FindWildcardDomainInPath(umbracoContext.Domains?.GetAll(true), contentPath, rootContentId);
@@ -70,6 +107,22 @@ namespace Umbraco.Cms.Core.Routing
return umbracoContext.Domains?.DefaultCulture;
}
private static int? GetAncestorNodeWithDomainsAssigned(int contentId, IUmbracoContext umbracoContext, IDomainCache domainCache, IPublishedCache publishedCache, INavigationQueryService navigationQueryService)
{
IPublishedContent? content = umbracoContext.Content.GetById(contentId);
var hasDomains = ContentHasAssignedDomains(content, domainCache);
while (content is not null && !hasDomains)
{
content = content.Parent<IPublishedContent>(publishedCache, navigationQueryService);
hasDomains = content is not null && domainCache.HasAssigned(content.Id, true);
}
return content?.Id;
}
private static bool ContentHasAssignedDomains(IPublishedContent? content, IDomainCache domainCache)
=> content is not null && domainCache.HasAssigned(content.Id, true);
#endregion
#region Domain for Document

View File

@@ -19,6 +19,9 @@ public static class FriendlyPublishedContentExtensions
private static IVariationContextAccessor VariationContextAccessor { get; } =
StaticServiceProvider.Instance.GetRequiredService<IVariationContextAccessor>();
private static IDomainCache DomainCache { get; } =
StaticServiceProvider.Instance.GetRequiredService<IDomainCache>();
private static IPublishedContentCache PublishedContentCache { get; } =
StaticServiceProvider.Instance.GetRequiredService<IPublishedContentCache>();
@@ -731,7 +734,7 @@ public static class FriendlyPublishedContentExtensions
public static string? GetCultureFromDomains(
this IPublishedContent content,
Uri? current = null)
=> content.GetCultureFromDomains(UmbracoContextAccessor, SiteDomainHelper, current);
=> content.GetCultureFromDomains(UmbracoContextAccessor, SiteDomainHelper, DomainCache, PublishedContentCache, DocumentNavigationQueryService, current);
public static IEnumerable<PublishedSearchResult> SearchDescendants(
this IPublishedContent content,

View File

@@ -4,8 +4,10 @@ using Examine.Search;
using Microsoft.AspNetCore.Html;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.Navigation;
using Umbraco.Cms.Core.Web;
using Umbraco.Cms.Infrastructure.Examine;
@@ -20,7 +22,36 @@ public static class PublishedContentExtensions
/// </summary>
/// <param name="content">The document.</param>
/// <param name="umbracoContextAccessor"></param>
/// <param name="siteDomainHelper"></param>
/// <param name="siteDomainHelper">The site domain helper.</param>
/// <param name="current">An optional current Uri.</param>
/// <returns>The culture assigned to the document by domains.</returns>
/// <remarks>
/// <para>
/// In 1:1 multilingual setup, a document contains several cultures (there is not
/// one document per culture), and domains, withing the context of a current Uri, assign
/// a culture to that document.
/// </para>
/// </remarks>
[Obsolete("Please use the method taking all parameters. This overload will be removed in V17.")]
public static string? GetCultureFromDomains(
this IPublishedContent content,
IUmbracoContextAccessor umbracoContextAccessor,
ISiteDomainMapper siteDomainHelper,
Uri? current = null)
{
IUmbracoContext umbracoContext = umbracoContextAccessor.GetRequiredUmbracoContext();
return DomainUtilities.GetCultureFromDomains(content.Id, content.Path, current, umbracoContext, siteDomainHelper);
}
/// <summary>
/// Gets the culture assigned to a document by domains, in the context of a current Uri.
/// </summary>
/// <param name="content">The document.</param>
/// <param name="umbracoContextAccessor"></param>
/// <param name="siteDomainHelper">The site domain helper.</param>
/// <param name="domainCache">The domain cache.</param>
/// <param name="publishedCache">The published content cache.</param>
/// <param name="navigationQueryService">The navigation query service.</param>
/// <param name="current">An optional current Uri.</param>
/// <returns>The culture assigned to the document by domains.</returns>
/// <remarks>
@@ -34,10 +65,13 @@ public static class PublishedContentExtensions
this IPublishedContent content,
IUmbracoContextAccessor umbracoContextAccessor,
ISiteDomainMapper siteDomainHelper,
IDomainCache domainCache,
IPublishedCache publishedCache,
INavigationQueryService navigationQueryService,
Uri? current = null)
{
IUmbracoContext umbracoContext = umbracoContextAccessor.GetRequiredUmbracoContext();
return DomainUtilities.GetCultureFromDomains(content.Id, content.Path, current, umbracoContext, siteDomainHelper);
return DomainUtilities.GetCultureFromDomains(content.Id, content.Path, current, umbracoContext, siteDomainHelper, domainCache, publishedCache, navigationQueryService);
}
#endregion