diff --git a/src/Umbraco.Tests/LegacyXmlPublishedCache/DomainCache.cs b/src/Umbraco.Tests/LegacyXmlPublishedCache/DomainCache.cs
index cde2077551..abaa239598 100644
--- a/src/Umbraco.Tests/LegacyXmlPublishedCache/DomainCache.cs
+++ b/src/Umbraco.Tests/LegacyXmlPublishedCache/DomainCache.cs
@@ -27,13 +27,18 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
}
///
- public IEnumerable GetAssigned(int contentId, bool includeWildcards)
+ public IEnumerable GetAssigned(int documentId, bool includeWildcards = false)
{
- return _domainService.GetAssignedDomains(contentId, includeWildcards)
+ return _domainService.GetAssignedDomains(documentId, includeWildcards)
.Where(x => x.RootContentId.HasValue && x.LanguageIsoCode.IsNullOrWhiteSpace() == false)
.Select(x => new Domain(x.Id, x.DomainName, x.RootContentId.Value, CultureInfo.GetCultureInfo(x.LanguageIsoCode), x.IsWildcard));
}
+ ///
+ public bool HasAssigned(int documentId, bool includeWildcards = false)
+ => documentId > 0 && GetAssigned(documentId, includeWildcards).Any();
+
+ ///
public string DefaultCulture { get; }
}
}
diff --git a/src/Umbraco.Tests/LegacyXmlPublishedCache/PublishedContentCache.cs b/src/Umbraco.Tests/LegacyXmlPublishedCache/PublishedContentCache.cs
index 1ad6e045c6..1ccbbf950b 100644
--- a/src/Umbraco.Tests/LegacyXmlPublishedCache/PublishedContentCache.cs
+++ b/src/Umbraco.Tests/LegacyXmlPublishedCache/PublishedContentCache.cs
@@ -22,7 +22,6 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly RoutesCache _routesCache;
private readonly IDomainCache _domainCache;
- private readonly DomainHelper _domainHelper;
private readonly PublishedContentTypeCache _contentTypeCache;
// initialize a PublishedContentCache instance with
@@ -48,7 +47,6 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
_routesCache = routesCache; // may be null for unit-testing
_contentTypeCache = contentTypeCache;
_domainCache = domainCache;
- _domainHelper = new DomainHelper(_domainCache, siteDomainHelper);
_xmlStore = xmlStore;
_xml = _xmlStore.Xml; // capture - because the cache has to remain consistent
@@ -107,7 +105,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
// that would be returned - the "deepest" route - and that is the route we want to cache, *not* the
// longer one - so make sure we don't cache the wrong route
- var deepest = DomainHelper.ExistsDomainInPath(_domainCache.GetAll(false), content.Path, domainRootNodeId) == false;
+ var deepest = DomainUtilities.ExistsDomainInPath(_domainCache.GetAll(false), content.Path, domainRootNodeId) == false;
if (deepest)
_routesCache.Store(content.Id, route, true); // trusted route
@@ -267,7 +265,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
// or we reach the content root, collecting urls in the way
var pathParts = new List();
var n = node;
- var hasDomains = _domainHelper.NodeHasDomains(n.Id);
+ var hasDomains = _domainCache.HasAssigned(n.Id);
while (hasDomains == false && n != null) // n is null at root
{
// get the url
@@ -276,7 +274,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
// move to parent node
n = n.Parent;
- hasDomains = n != null && _domainHelper.NodeHasDomains(n.Id);
+ hasDomains = n != null && _domainCache.HasAssigned(n.Id);
}
// no domain, respect HideTopLevelNodeFromPath for legacy purposes
diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs
index 4b23e46a6c..a8824d416f 100644
--- a/src/Umbraco.Web/Editors/ContentController.cs
+++ b/src/Umbraco.Web/Editors/ContentController.cs
@@ -1656,7 +1656,7 @@ namespace Umbraco.Web.Editors
{
try
{
- var uri = DomainHelper.ParseUriFromDomainName(domain.Name, Request.RequestUri);
+ var uri = DomainUtilities.ParseUriFromDomainName(domain.Name, Request.RequestUri);
}
catch (UriFormatException)
{
diff --git a/src/Umbraco.Web/Editors/MacroRenderingController.cs b/src/Umbraco.Web/Editors/MacroRenderingController.cs
index 64706a7f04..0c3b1626d0 100644
--- a/src/Umbraco.Web/Editors/MacroRenderingController.cs
+++ b/src/Umbraco.Web/Editors/MacroRenderingController.cs
@@ -123,23 +123,17 @@ namespace Umbraco.Web.Editors
// Since a Macro might contain thing thats related to the culture of the "IPublishedContent" (ie Dictionary keys) we want
// to set the current culture to the culture related to the content item. This is hacky but it works.
- // fixme I don't even know how this ever worked?!
+ // fixme
+ // in a 1:1 situation we do not handle the language being edited
+ // so the macro renders in the wrong language
- // assume this was some sort of "the culture of the item"
- // but... with multilingual it does not make any sense?!
- //var culture = publishedContent.GetCulture();
-
- string culture = ""; // needs to be eg fr-FR
+ var culture = publishedContent.GetCultureFromDomains();
if (culture != null)
- {
Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(culture);
- _variationContextAccessor.VariationContext = new VariationContext(culture);
- }
- else
- {
- _variationContextAccessor.VariationContext = new VariationContext(); //must have an active variation context!
- }
+
+ // must have an active variation context!
+ _variationContextAccessor.VariationContext = new VariationContext(culture);
var result = Request.CreateResponse();
//need to create a specific content result formatted as HTML since this controller has been configured
diff --git a/src/Umbraco.Web/PublishedCache/IDomainCache.cs b/src/Umbraco.Web/PublishedCache/IDomainCache.cs
index dbee8908a0..3ec84c9d48 100644
--- a/src/Umbraco.Web/PublishedCache/IDomainCache.cs
+++ b/src/Umbraco.Web/PublishedCache/IDomainCache.cs
@@ -1,4 +1,6 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
+using Umbraco.Core.Models.PublishedContent;
using Umbraco.Web.Routing;
namespace Umbraco.Web.PublishedCache
@@ -6,20 +8,29 @@ namespace Umbraco.Web.PublishedCache
public interface IDomainCache
{
///
- /// Returns all in the current domain cache including any domains that may be referenced by content items that are no longer published
+ /// Gets all in the current domain cache, including any domains that may be referenced by documents that are no longer published.
///
///
///
IEnumerable GetAll(bool includeWildcards);
///
- /// Returns all assigned for the content id specified even if the content item is not published
+ /// Gets all assigned for specified document, even if it is not published.
///
- ///
- ///
- ///
- IEnumerable GetAssigned(int contentId, bool includeWildcards);
+ /// The document identifier.
+ /// A value indicating whether to consider wildcard domains.
+ IEnumerable GetAssigned(int documentId, bool includeWildcards = false);
+ ///
+ /// Determines whether a document has domains.
+ ///
+ /// The document identifier.
+ /// A value indicating whether to consider wildcard domains.
+ bool HasAssigned(int documentId, bool includeWildcards = false);
+
+ ///
+ /// Gets the system default culture.
+ ///
string DefaultCulture { get; }
}
}
diff --git a/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs b/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs
index 08664f0a7a..705ce17595 100644
--- a/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs
+++ b/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs
@@ -23,9 +23,8 @@ namespace Umbraco.Web.PublishedCache.NuCache
private readonly ContentStore.Snapshot _snapshot;
private readonly IAppCache _snapshotCache;
private readonly IAppCache _elementsCache;
- private readonly DomainHelper _domainHelper;
+ private readonly IDomainCache _domainCache;
private readonly IGlobalSettings _globalSettings;
- private readonly ILocalizationService _localizationService;
#region Constructor
@@ -34,15 +33,14 @@ namespace Umbraco.Web.PublishedCache.NuCache
// it's too late for UmbracoContext which has captured previewDefault and stuff into these ctor vars
// but, no, UmbracoContext returns snapshot.Content which comes from elements SO a resync should create a new cache
- public ContentCache(bool previewDefault, ContentStore.Snapshot snapshot, IAppCache snapshotCache, IAppCache elementsCache, DomainHelper domainHelper, IGlobalSettings globalSettings, ILocalizationService localizationService)
+ public ContentCache(bool previewDefault, ContentStore.Snapshot snapshot, IAppCache snapshotCache, IAppCache elementsCache, IDomainCache domainCache, IGlobalSettings globalSettings)
: base(previewDefault)
{
_snapshot = snapshot;
_snapshotCache = snapshotCache;
_elementsCache = elementsCache;
- _domainHelper = domainHelper;
+ _domainCache = domainCache;
_globalSettings = globalSettings;
- _localizationService = localizationService;
}
private bool HideTopLevelNodeFromPath => _globalSettings.HideTopLevelNodeFromPath;
@@ -150,7 +148,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
var pathParts = new List();
var n = node;
var urlSegment = n.UrlSegment(culture);
- var hasDomains = _domainHelper.NodeHasDomains(n.Id);
+ var hasDomains = _domainCache.HasAssigned(n.Id);
while (hasDomains == false && n != null) // n is null at root
{
// no segment indicates this is not published when this is a variant
@@ -163,7 +161,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
if (n != null)
urlSegment = n.UrlSegment(culture);
- hasDomains = n != null && _domainHelper.NodeHasDomains(n.Id);
+ hasDomains = n != null && _domainCache.HasAssigned(n.Id);
}
// at this point this will be the urlSegment of the root, no segment indicates this is not published when this is a variant
diff --git a/src/Umbraco.Web/PublishedCache/NuCache/DomainCache.cs b/src/Umbraco.Web/PublishedCache/NuCache/DomainCache.cs
index 896a04a0b3..6bc0de7268 100644
--- a/src/Umbraco.Web/PublishedCache/NuCache/DomainCache.cs
+++ b/src/Umbraco.Web/PublishedCache/NuCache/DomainCache.cs
@@ -4,16 +4,23 @@ using Umbraco.Web.Routing;
namespace Umbraco.Web.PublishedCache.NuCache
{
+ ///
+ /// Implements for NuCache.
+ ///
internal class DomainCache : IDomainCache
{
private readonly SnapDictionary.Snapshot _snapshot;
+ ///
+ /// Initializes a new instance of the class.
+ ///
public DomainCache(SnapDictionary.Snapshot snapshot, string defaultCulture)
{
_snapshot = snapshot;
- DefaultCulture = defaultCulture; // capture - fast
+ DefaultCulture = defaultCulture;
}
+ ///
public IEnumerable GetAll(bool includeWildcards)
{
var list = _snapshot.GetAll();
@@ -21,17 +28,23 @@ namespace Umbraco.Web.PublishedCache.NuCache
return list;
}
- public IEnumerable GetAssigned(int contentId, bool includeWildcards)
+ ///
+ public IEnumerable GetAssigned(int documentId, bool includeWildcards = false)
{
// probably this could be optimized with an index
// but then we'd need a custom DomainStore of some sort
var list = _snapshot.GetAll();
- list = list.Where(x => x.ContentId == contentId);
+ list = list.Where(x => x.ContentId == documentId);
if (includeWildcards == false) list = list.Where(x => x.IsWildcard == false);
return list;
}
+ ///
+ public bool HasAssigned(int documentId, bool includeWildcards = false)
+ => documentId > 0 && GetAssigned(documentId, includeWildcards).Any();
+
+ ///
public string DefaultCulture { get; }
}
}
diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs
index 3b683cdd4e..ce19764fb6 100755
--- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs
+++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs
@@ -4,13 +4,11 @@ using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
-using System.Web;
using CSharpTest.Net.Collections;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration;
-using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
@@ -1074,11 +1072,10 @@ namespace Umbraco.Web.PublishedCache.NuCache
var defaultCulture = _defaultCultureAccessor.DefaultCulture;
var domainCache = new DomainCache(domainSnap, defaultCulture);
- var domainHelper = new DomainHelper(domainCache, _siteDomainHelper);
return new PublishedSnapshot.PublishedSnapshotElements
{
- ContentCache = new ContentCache(previewDefault, contentSnap, snapshotCache, elementsCache, domainHelper, _globalSettings, _serviceContext.LocalizationService),
+ ContentCache = new ContentCache(previewDefault, contentSnap, snapshotCache, elementsCache, domainCache, _globalSettings),
MediaCache = new MediaCache(previewDefault, mediaSnap, snapshotCache, elementsCache),
MemberCache = new MemberCache(previewDefault, snapshotCache, _serviceContext.MemberService, memberTypeCache, PublishedSnapshotAccessor, VariationContextAccessor, _umbracoContextAccessor, _entitySerializer),
DomainCache = domainCache,
diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs
index d7996034a8..a243d6e77a 100644
--- a/src/Umbraco.Web/PublishedContentExtensions.cs
+++ b/src/Umbraco.Web/PublishedContentExtensions.cs
@@ -11,6 +11,7 @@ using Umbraco.Core.Services;
using Umbraco.Examine;
using Umbraco.Web.Composing;
using Umbraco.Web.PublishedCache;
+using Umbraco.Web.Routing;
namespace Umbraco.Web
{
@@ -20,9 +21,12 @@ namespace Umbraco.Web
public static class PublishedContentExtensions
{
// see notes in PublishedElementExtensions
+ // (yes, this is not pretty, but works for now)
//
private static IPublishedValueFallback PublishedValueFallback => Current.PublishedValueFallback;
private static IPublishedSnapshot PublishedSnapshot => Current.PublishedSnapshot;
+ private static UmbracoContext UmbracoContext => Current.UmbracoContext;
+ private static ISiteDomainHelper SiteDomainHelper => Current.Factory.GetInstance();
#region IsComposedOf
@@ -186,6 +190,27 @@ namespace Umbraco.Web
return contents.Where(x => !x.ContentType.VariesByCulture() || x.HasCulture(culture));
}
+ ///
+ /// Gets the culture assigned to a document by domains, in the context of a current Uri.
+ ///
+ /// The document.
+ /// An optional current Uri.
+ /// The culture assigned to the document by domains.
+ ///
+ /// 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.
+ ///
+ public static string GetCultureFromDomains(this IPublishedContent content, Uri current = null)
+ {
+ var umbracoContext = UmbracoContext;
+
+ if (umbracoContext == null)
+ throw new InvalidOperationException("A current UmbracoContext is required.");
+
+ return DomainUtilities.GetCultureFromDomains(content.Id, content.Path, current, umbracoContext, SiteDomainHelper);
+ }
+
#endregion
#region Search
diff --git a/src/Umbraco.Web/Routing/AliasUrlProvider.cs b/src/Umbraco.Web/Routing/AliasUrlProvider.cs
index bbe3a9db8c..411fabbf35 100644
--- a/src/Umbraco.Web/Routing/AliasUrlProvider.cs
+++ b/src/Umbraco.Web/Routing/AliasUrlProvider.cs
@@ -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
diff --git a/src/Umbraco.Web/Routing/ContentFinderByConfigured404.cs b/src/Umbraco.Web/Routing/ContentFinderByConfigured404.cs
index e3cad25c6f..e5bb23bfce 100644
--- a/src/Umbraco.Web/Routing/ContentFinderByConfigured404.cs
+++ b/src/Umbraco.Web/Routing/ContentFinderByConfigured404.cs
@@ -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;
}
diff --git a/src/Umbraco.Web/Routing/ContentFinderByRedirectUrl.cs b/src/Umbraco.Web/Routing/ContentFinderByRedirectUrl.cs
index eae2b57378..d7b4c9925c 100644
--- a/src/Umbraco.Web/Routing/ContentFinderByRedirectUrl.cs
+++ b/src/Umbraco.Web/Routing/ContentFinderByRedirectUrl.cs
@@ -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);
diff --git a/src/Umbraco.Web/Routing/ContentFinderByUrl.cs b/src/Umbraco.Web/Routing/ContentFinderByUrl.cs
index 94b2b9dbf2..9aa52782d1 100644
--- a/src/Umbraco.Web/Routing/ContentFinderByUrl.cs
+++ b/src/Umbraco.Web/Routing/ContentFinderByUrl.cs
@@ -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();
diff --git a/src/Umbraco.Web/Routing/ContentFinderByUrlAndTemplate.cs b/src/Umbraco.Web/Routing/ContentFinderByUrlAndTemplate.cs
index 1e86b40a79..39c80afd56 100644
--- a/src/Umbraco.Web/Routing/ContentFinderByUrlAndTemplate.cs
+++ b/src/Umbraco.Web/Routing/ContentFinderByUrlAndTemplate.cs
@@ -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 == "/")
diff --git a/src/Umbraco.Web/Routing/DefaultUrlProvider.cs b/src/Umbraco.Web/Routing/DefaultUrlProvider.cs
index 98ba743fe5..06f275a685 100644
--- a/src/Umbraco.Web/Routing/DefaultUrlProvider.cs
+++ b/src/Umbraco.Web/Routing/DefaultUrlProvider.cs
@@ -47,15 +47,13 @@ namespace Umbraco.Web.Routing
return null;
}
- var domainHelper = umbracoContext.GetDomainHelper(_siteDomainHelper);
-
// extract domainUri and path
// route is / or /
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
diff --git a/src/Umbraco.Web/Routing/DomainAndUri.cs b/src/Umbraco.Web/Routing/DomainAndUri.cs
index 1151055621..46dc085998 100644
--- a/src/Umbraco.Web/Routing/DomainAndUri.cs
+++ b/src/Umbraco.Web/Routing/DomainAndUri.cs
@@ -22,7 +22,7 @@ namespace Umbraco.Web.Routing
{
try
{
- Uri = DomainHelper.ParseUriFromDomainName(Name, currentUri);
+ Uri = DomainUtilities.ParseUriFromDomainName(Name, currentUri);
}
catch (UriFormatException)
{
diff --git a/src/Umbraco.Web/Routing/DomainHelper.cs b/src/Umbraco.Web/Routing/DomainUtilities.cs
similarity index 81%
rename from src/Umbraco.Web/Routing/DomainHelper.cs
rename to src/Umbraco.Web/Routing/DomainUtilities.cs
index 95d97653a0..fb0c56b28d 100644
--- a/src/Umbraco.Web/Routing/DomainHelper.cs
+++ b/src/Umbraco.Web/Routing/DomainUtilities.cs
@@ -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
{
///
/// Provides utilities to handle domains.
///
- public class DomainHelper
+ public static class DomainUtilities
{
- private readonly IDomainCache _domainCache;
- private readonly ISiteDomainHelper _siteDomainHelper;
+ #region Document Culture
- public DomainHelper(IDomainCache domainCache, ISiteDomainHelper siteDomainHelper)
+ ///
+ /// Gets the culture assigned to a document by domains, in the context of a current Uri.
+ ///
+ /// The document identifier.
+ /// The document path.
+ /// An optional current Uri.
+ /// An Umbraco context.
+ /// The site domain helper.
+ /// The culture assigned to the document by domains.
+ ///
+ /// 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.
+ ///
+ 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
///
/// Finds the domain for the specified node, if any, that best matches a specified uri.
///
+ /// A domain cache.
+ /// The site domain helper.
/// The node identifier.
/// The uri, or null.
/// The culture, or null.
@@ -35,14 +75,14 @@ namespace Umbraco.Web.Routing
/// If culture is null, uses the default culture for the installation instead. Otherwise,
/// will try with the specified culture, else return null.
///
- 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));
- }
-
- ///
- /// Gets a value indicating whether a specified node has domains.
- ///
- /// The node identifier.
- /// True if the node has domains, else false.
- internal bool NodeHasDomains(int nodeId)
- {
- return nodeId > 0 && _domainCache.GetAssigned(nodeId, false).Any();
+ return SelectDomain(domains, current, culture, domainCache.DefaultCulture, siteDomainHelper.MapDomain);
}
///
/// Find the domains for the specified node, if any, that match a specified uri.
///
+ /// A domain cache.
+ /// The site domain helper.
/// The node identifier.
/// The uri, or null.
/// A value indicating whether to exclude the current/default domain. True by default.
/// The domains and their uris, that match the specified uri, else null.
/// 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.
- internal IEnumerable DomainsForNode(int nodeId, Uri current, bool excludeDefault = true)
+ internal static IEnumerable 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
}
///
- /// Parses a domain name into a URI.
+ /// Parses a domain name into a URI.
///
/// The domain name to parse
/// The currently requested URI. If the domain name is relative, the authority of URI will be used.
diff --git a/src/Umbraco.Web/Routing/PublishedRouter.cs b/src/Umbraco.Web/Routing/PublishedRouter.cs
index aeb329a9e9..2e772cb175 100644
--- a/src/Umbraco.Web/Routing/PublishedRouter.cs
+++ b/src/Umbraco.Web/Routing/PublishedRouter.cs
@@ -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("{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)
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index 42a1a766e5..28337e6d2c 100755
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -1137,7 +1137,7 @@
-
+
diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs
index a39535ba6e..04052e8be3 100644
--- a/src/Umbraco.Web/UmbracoContext.cs
+++ b/src/Umbraco.Web/UmbracoContext.cs
@@ -3,12 +3,10 @@ using System.Collections.Generic;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Configuration;
-using Umbraco.Core.Composing;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Routing;
-using Umbraco.Web.Runtime;
using Umbraco.Web.Security;
namespace Umbraco.Web
@@ -20,7 +18,6 @@ namespace Umbraco.Web
{
private readonly IGlobalSettings _globalSettings;
private readonly Lazy _publishedSnapshot;
- private DomainHelper _domainHelper;
private string _previewToken;
private bool? _previewing;
@@ -107,9 +104,6 @@ namespace Umbraco.Web
///
public IPublishedSnapshot PublishedSnapshot => _publishedSnapshot.Value;
- // for unit tests
- internal bool HasPublishedSnapshot => _publishedSnapshot.IsValueCreated;
-
///
/// Gets the published content cache.
///
@@ -162,20 +156,6 @@ namespace Umbraco.Web
///
public IVariationContextAccessor VariationContextAccessor { get; }
- ///
- /// Creates and caches an instance of a DomainHelper
- ///
- ///
- /// We keep creating new instances of DomainHelper, it would be better if we didn't have to do that so instead we can
- /// have one attached to the UmbracoContext. This method accepts an external ISiteDomainHelper otherwise the UmbracoContext
- /// ctor will have to have another parameter added only for this one method which is annoying and doesn't make a ton of sense
- /// since the UmbracoContext itself doesn't use this.
- ///
- /// TODO: The alternative is to have a IDomainHelperAccessor singleton which is cached per UmbracoContext
- ///
- internal DomainHelper GetDomainHelper(ISiteDomainHelper siteDomainHelper)
- => _domainHelper ?? (_domainHelper = new DomainHelper(PublishedSnapshot.Domains, siteDomainHelper));
-
///
/// Gets a value indicating whether the request has debugging enabled
///
diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs
index 1c6eb28b92..6e7b05691e 100644
--- a/src/Umbraco.Web/UmbracoHelper.cs
+++ b/src/Umbraco.Web/UmbracoHelper.cs
@@ -809,11 +809,5 @@ namespace Umbraco.Web
}
#endregion
-
-
-
-
-
-
}
}