Refactor IPublishedContent.GetCultureFromDomains()

This commit is contained in:
Stephan
2019-04-17 14:41:54 +02:00
parent e062ea8d31
commit a996d46b6f
21 changed files with 153 additions and 114 deletions

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
@@ -60,16 +59,14 @@ namespace Umbraco.Web.Routing
if (!node.HasProperty(Constants.Conventions.Content.UrlAlias))
yield break;
var domainHelper = umbracoContext.GetDomainHelper(_siteDomainHelper);
// look for domains, walking up the tree
var n = node;
var domainUris = domainHelper.DomainsForNode(n.Id, current, false);
var domainUris = DomainUtilities.DomainsForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainHelper, n.Id, current, false);
while (domainUris == null && n != null) // n is null at root
{
// move to parent node
n = n.Parent;
domainUris = n == null ? null : domainHelper.DomainsForNode(n.Id, current, excludeDefault: false);
domainUris = n == null ? null : DomainUtilities.DomainsForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainHelper, n.Id, current, excludeDefault: false);
}
// determine whether the alias property varies

View File

@@ -53,7 +53,7 @@ namespace Umbraco.Web.Routing
}
if (node != null)
{
var d = DomainHelper.FindWildcardDomainInPath(frequest.UmbracoContext.PublishedSnapshot.Domains.GetAll(true), node.Path, null);
var d = DomainUtilities.FindWildcardDomainInPath(frequest.UmbracoContext.PublishedSnapshot.Domains.GetAll(true), node.Path, null);
if (d != null)
errorCulture = d.Culture;
}

View File

@@ -33,7 +33,7 @@ namespace Umbraco.Web.Routing
public bool TryFindContent(PublishedRequest frequest)
{
var route = frequest.HasDomain
? frequest.Domain.ContentId + DomainHelper.PathRelativeToDomain(frequest.Domain.Uri, frequest.Uri.GetAbsolutePathDecoded())
? frequest.Domain.ContentId + DomainUtilities.PathRelativeToDomain(frequest.Domain.Uri, frequest.Uri.GetAbsolutePathDecoded())
: frequest.Uri.GetAbsolutePathDecoded();
var redirectUrl = _redirectUrlService.GetMostRecentRedirectUrl(route);

View File

@@ -28,7 +28,7 @@ namespace Umbraco.Web.Routing
{
string route;
if (frequest.HasDomain)
route = frequest.Domain.ContentId + DomainHelper.PathRelativeToDomain(frequest.Domain.Uri, frequest.Uri.GetAbsolutePathDecoded());
route = frequest.Domain.ContentId + DomainUtilities.PathRelativeToDomain(frequest.Domain.Uri, frequest.Uri.GetAbsolutePathDecoded());
else
route = frequest.Uri.GetAbsolutePathDecoded();

View File

@@ -38,7 +38,7 @@ namespace Umbraco.Web.Routing
var path = frequest.Uri.GetAbsolutePathDecoded();
if (frequest.HasDomain)
path = DomainHelper.PathRelativeToDomain(frequest.Domain.Uri, path);
path = DomainUtilities.PathRelativeToDomain(frequest.Domain.Uri, path);
// no template if "/"
if (path == "/")

View File

@@ -47,15 +47,13 @@ namespace Umbraco.Web.Routing
return null;
}
var domainHelper = umbracoContext.GetDomainHelper(_siteDomainHelper);
// extract domainUri and path
// route is /<path> or <domainRootId>/<path>
var pos = route.IndexOf('/');
var path = pos == 0 ? route : route.Substring(pos);
var domainUri = pos == 0
? null
: domainHelper.DomainForNode(int.Parse(route.Substring(0, pos)), current, culture);
: DomainUtilities.DomainForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainHelper, int.Parse(route.Substring(0, pos)), current, culture);
// assemble the url from domainUri (maybe null) and path
var url = AssembleUrl(domainUri, path, current, mode).ToString();
@@ -84,15 +82,13 @@ namespace Umbraco.Web.Routing
if (node == null)
yield break;
var domainHelper = umbracoContext.GetDomainHelper(_siteDomainHelper);
// look for domains, walking up the tree
var n = node;
var domainUris = domainHelper.DomainsForNode(n.Id, current, false);
var domainUris = DomainUtilities.DomainsForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainHelper, n.Id, current, false);
while (domainUris == null && n != null) // n is null at root
{
n = n.Parent; // move to parent node
domainUris = n == null ? null : domainHelper.DomainsForNode(n.Id, current, excludeDefault: true);
domainUris = n == null ? null : DomainUtilities.DomainsForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainHelper, n.Id, current, excludeDefault: true);
}
// no domains = exit

View File

@@ -22,7 +22,7 @@ namespace Umbraco.Web.Routing
{
try
{
Uri = DomainHelper.ParseUriFromDomainName(Name, currentUri);
Uri = DomainUtilities.ParseUriFromDomainName(Name, currentUri);
}
catch (UriFormatException)
{

View File

@@ -2,29 +2,69 @@
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core;
using Umbraco.Web.PublishedCache; // published snapshot
using Umbraco.Web.PublishedCache;
namespace Umbraco.Web.Routing
{
/// <summary>
/// Provides utilities to handle domains.
/// </summary>
public class DomainHelper
public static class DomainUtilities
{
private readonly IDomainCache _domainCache;
private readonly ISiteDomainHelper _siteDomainHelper;
#region Document Culture
public DomainHelper(IDomainCache domainCache, ISiteDomainHelper siteDomainHelper)
/// <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="siteDomainHelper">The site domain helper.</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>
internal static string GetCultureFromDomains(int contentId, string contentPath, Uri current, UmbracoContext umbracoContext, ISiteDomainHelper siteDomainHelper)
{
_domainCache = domainCache;
_siteDomainHelper = siteDomainHelper;
if (umbracoContext == null)
throw new InvalidOperationException("A current UmbracoContext is required.");
if (current == null)
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);
if (route == null)
return null;
var pos = route.IndexOf('/');
var domain = pos == 0
? null
: DomainForNode(umbracoContext.Domains, siteDomainHelper, int.Parse(route.Substring(0, pos)), current);
var rootContentId = domain?.ContentId ?? -1;
var wcDomain = FindWildcardDomainInPath(umbracoContext.Domains.GetAll(true), contentPath, rootContentId);
if (wcDomain != null) return wcDomain.Culture.Name;
if (domain != null) return domain.Culture.Name;
return umbracoContext.Domains.DefaultCulture;
}
#region Domain for Node
#endregion
#region Domain for Document
/// <summary>
/// Finds the domain for the specified node, if any, that best matches a specified uri.
/// </summary>
/// <param name="domainCache">A domain cache.</param>
/// <param name="siteDomainHelper">The site domain helper.</param>
/// <param name="nodeId">The node identifier.</param>
/// <param name="current">The uri, or null.</param>
/// <param name="culture">The culture, or null.</param>
@@ -35,14 +75,14 @@ namespace Umbraco.Web.Routing
/// <para>If culture is null, uses the default culture for the installation instead. Otherwise,
/// will try with the specified culture, else return null.</para>
/// </remarks>
internal DomainAndUri DomainForNode(int nodeId, Uri current, string culture = null)
internal static DomainAndUri DomainForNode(IDomainCache domainCache, ISiteDomainHelper siteDomainHelper, int nodeId, Uri current, string culture = null)
{
// be safe
if (nodeId <= 0)
return null;
// get the domains on that node
var domains = _domainCache.GetAssigned(nodeId, false).ToArray();
var domains = domainCache.GetAssigned(nodeId).ToArray();
// none?
if (domains.Length == 0)
@@ -50,37 +90,28 @@ namespace Umbraco.Web.Routing
// else filter
// it could be that none apply (due to culture)
return SelectDomain(domains, current, culture, _domainCache.DefaultCulture,
(cdomainAndUris, ccurrent, cculture, cdefaultCulture) => _siteDomainHelper.MapDomain(cdomainAndUris, ccurrent, cculture, cdefaultCulture));
}
/// <summary>
/// Gets a value indicating whether a specified node has domains.
/// </summary>
/// <param name="nodeId">The node identifier.</param>
/// <returns>True if the node has domains, else false.</returns>
internal bool NodeHasDomains(int nodeId)
{
return nodeId > 0 && _domainCache.GetAssigned(nodeId, false).Any();
return SelectDomain(domains, current, culture, domainCache.DefaultCulture, siteDomainHelper.MapDomain);
}
/// <summary>
/// Find the domains for the specified node, if any, that match a specified uri.
/// </summary>
/// <param name="domainCache">A domain cache.</param>
/// <param name="siteDomainHelper">The site domain helper.</param>
/// <param name="nodeId">The node identifier.</param>
/// <param name="current">The uri, or null.</param>
/// <param name="excludeDefault">A value indicating whether to exclude the current/default domain. True by default.</param>
/// <returns>The domains and their uris, that match the specified uri, else null.</returns>
/// <remarks>If at least a domain is set on the node then the method returns the domains that
/// best match the specified uri, else it returns null.</remarks>
internal IEnumerable<DomainAndUri> DomainsForNode(int nodeId, Uri current, bool excludeDefault = true)
internal static IEnumerable<DomainAndUri> DomainsForNode(IDomainCache domainCache, ISiteDomainHelper siteDomainHelper, int nodeId, Uri current, bool excludeDefault = true)
{
// be safe
if (nodeId <= 0)
return null;
// get the domains on that node
var domains = _domainCache.GetAssigned(nodeId, false).ToArray();
var domains = domainCache.GetAssigned(nodeId).ToArray();
// none?
if (domains.Length == 0)
@@ -90,7 +121,7 @@ namespace Umbraco.Web.Routing
var domainAndUris = SelectDomains(domains, current).ToArray();
// filter
return _siteDomainHelper.MapDomains(domainAndUris, current, excludeDefault, null, _domainCache.DefaultCulture).ToArray();
return siteDomainHelper.MapDomains(domainAndUris, current, excludeDefault, null, domainCache.DefaultCulture).ToArray();
}
#endregion
@@ -252,7 +283,7 @@ namespace Umbraco.Web.Routing
}
/// <summary>
/// Parses a domain name into a URI.
/// Parses a domain name into a URI.
/// </summary>
/// <param name="domainName">The domain name to parse</param>
/// <param name="currentUri">The currently requested URI. If the domain name is relative, the authority of URI will be used.</param>

View File

@@ -284,7 +284,7 @@ namespace Umbraco.Web.Routing
var defaultCulture = domainsCache.DefaultCulture;
// try to find a domain matching the current request
var domainAndUri = DomainHelper.SelectDomain(domains, request.Uri, defaultCulture: defaultCulture);
var domainAndUri = DomainUtilities.SelectDomain(domains, request.Uri, defaultCulture: defaultCulture);
// handle domain - always has a contentId and a culture
if (domainAndUri != null)
@@ -328,7 +328,7 @@ namespace Umbraco.Web.Routing
var nodePath = request.PublishedContent.Path;
_logger.Debug<PublishedRouter>("{TracePrefix}Path={NodePath}", tracePrefix, nodePath);
var rootNodeId = request.HasDomain ? request.Domain.ContentId : (int?)null;
var domain = DomainHelper.FindWildcardDomainInPath(request.UmbracoContext.PublishedSnapshot.Domains.GetAll(true), nodePath, rootNodeId);
var domain = DomainUtilities.FindWildcardDomainInPath(request.UmbracoContext.PublishedSnapshot.Domains.GetAll(true), nodePath, rootNodeId);
// always has a contentId and a culture
if (domain != null)