diff --git a/src/Umbraco.Tests/Integration/GetCultureTests.cs b/src/Umbraco.Tests/Integration/GetCultureTests.cs new file mode 100644 index 0000000000..d4d1ea565b --- /dev/null +++ b/src/Umbraco.Tests/Integration/GetCultureTests.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using NUnit.Framework; +using umbraco.cms.businesslogic.language; +using umbraco.cms.businesslogic.web; +using Umbraco.Tests.Services; +using Umbraco.Tests.TestHelpers; +using Umbraco.Tests.TestHelpers.Entities; +using Umbraco.Web.Routing; + +namespace Umbraco.Tests.Integration +{ + [DatabaseTestBehavior(DatabaseBehavior.NewDbFileAndSchemaPerTest)] + [TestFixture, RequiresSTA] + public class GetCultureTests : BaseServiceTest + { + protected override void FreezeResolution() + { + SiteDomainHelperResolver.Current = new SiteDomainHelperResolver(new SiteDomainHelper()); + + base.FreezeResolution(); + } + + [Test] + public void GetCulture() + { + var contentTypeService = ServiceContext.ContentTypeService; + var contentType = MockedContentTypes.CreateSimpleContentType("umbBlah", "test Doc Type"); + contentTypeService.Save(contentType); + var contentService = ServiceContext.ContentService; + + var c1 = contentService.CreateContentWithIdentity("content", -1, "umbBlah"); + var c2 = contentService.CreateContentWithIdentity("content", c1, "umbBlah"); + var c3 = contentService.CreateContentWithIdentity("content", c1, "umbBlah"); + var c4 = contentService.CreateContentWithIdentity("content", c3, "umbBlah"); + + var langs = Language.GetAllAsList(); + foreach (var l in langs.Skip(1)) + l.Delete(); + + Language.MakeNew("fr-FR"); + Language.MakeNew("de-DE"); + + var langEn = Language.GetByCultureCode("en-US"); + var langFr = Language.GetByCultureCode("fr-FR"); + var langDe = Language.GetByCultureCode("de-DE"); + + var domains = Domain.GetDomains(true); // we want wildcards too here + foreach (var d in domains) + d.Delete(); + + Domain.MakeNew("domain1.com/", c1.Id, langEn.id); + Domain.MakeNew("domain1.fr/", c1.Id, langFr.id); + Domain.MakeNew("*100112", c3.Id, langDe.id); + + var content = c2; + var culture = Web.Models.ContentExtensions.GetCulture(null, ServiceContext.LocalizationService, ServiceContext.ContentService, content.Id, content.Path, + new Uri("http://domain1.com/")); + Assert.AreEqual("en-US", culture.Name); + + content = c2; + culture = Web.Models.ContentExtensions.GetCulture(null, ServiceContext.LocalizationService, ServiceContext.ContentService, content.Id, content.Path, + new Uri("http://domain1.fr/")); + Assert.AreEqual("fr-FR", culture.Name); + + content = c4; + culture = Web.Models.ContentExtensions.GetCulture(null, ServiceContext.LocalizationService, ServiceContext.ContentService, content.Id, content.Path, + new Uri("http://domain1.fr/")); + Assert.AreEqual("de-DE", culture.Name); + } + } +} diff --git a/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs b/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs index 27b00cf676..600830607c 100644 --- a/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs +++ b/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs @@ -3,10 +3,12 @@ using System.Collections.Generic; using System.Linq; using System.Text; using NUnit.Framework; +using Umbraco.Core.Models; using Umbraco.Tests.TestHelpers; +using Umbraco.Web; using Umbraco.Web.Routing; using umbraco.cms.businesslogic.web; -using umbraco.cms.businesslogic.language; +using Language = umbraco.cms.businesslogic.language.Language; namespace Umbraco.Tests.Routing { @@ -14,6 +16,13 @@ namespace Umbraco.Tests.Routing [TestFixture] class DomainsAndCulturesTests : BaseRoutingTest { + protected override void FreezeResolution() + { + SiteDomainHelperResolver.Current = new SiteDomainHelperResolver(new SiteDomainHelper()); + + base.FreezeResolution(); + } + public override void Initialize() { base.Initialize(); @@ -235,5 +244,32 @@ namespace Umbraco.Tests.Routing Assert.AreEqual(expectedCulture, pcr.Culture.Name); Assert.AreEqual(pcr.PublishedContent.Id, expectedNode); } + + #region Cases + [TestCase(10011, "http://domain1.com/", "en-US")] + [TestCase(100111, "http://domain1.com/", "en-US")] + [TestCase(10011, "http://domain1.fr/", "fr-FR")] + [TestCase(100111, "http://domain1.fr/", "fr-FR")] + [TestCase(1001121, "http://domain1.fr/", "de-DE")] + #endregion + public void GetCulture(int nodeId, string currentUrl, string expectedCulture) + { + var langEn = Language.GetByCultureCode("en-US"); + var langFr = Language.GetByCultureCode("fr-FR"); + var langDe = Language.GetByCultureCode("de-DE"); + + Domain.MakeNew("domain1.com/", 1001, langEn.id); + Domain.MakeNew("domain1.fr/", 1001, langFr.id); + Domain.MakeNew("*100112", 100112, langDe.id); + + var routingContext = GetRoutingContext("http://anything/"); + var umbracoContext = routingContext.UmbracoContext; + + var content = umbracoContext.ContentCache.GetById(nodeId); + Assert.IsNotNull(content); + + var culture = Web.Models.ContentExtensions.GetCulture(umbracoContext, null, null, content.Id, content.Path, new Uri(currentUrl)); + Assert.AreEqual(expectedCulture, culture.Name); + } } } diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index ef316f9e1a..4ad0fc29d1 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -170,6 +170,7 @@ + diff --git a/src/Umbraco.Web/Models/ContentExtensions.cs b/src/Umbraco.Web/Models/ContentExtensions.cs index ae93f13c7b..088f5b7646 100644 --- a/src/Umbraco.Web/Models/ContentExtensions.cs +++ b/src/Umbraco.Web/Models/ContentExtensions.cs @@ -1,6 +1,7 @@ using System; using System.Globalization; using System.Linq; +using umbraco.cms.businesslogic.web; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Services; @@ -21,6 +22,7 @@ namespace Umbraco.Web.Models { return GetCulture(UmbracoContext.Current, ApplicationContext.Current.Services.LocalizationService, + ApplicationContext.Current.Services.ContentService, content.Id, content.Path, current); } @@ -31,30 +33,62 @@ namespace Umbraco.Web.Models /// /// An instance. /// An implementation. + /// An implementation. /// The content identifier. /// The content path. /// The request Uri. /// The culture that would be selected to render the content. - internal static CultureInfo GetCulture(UmbracoContext umbracoContext, ILocalizationService localizationService, + internal static CultureInfo GetCulture(UmbracoContext umbracoContext, ILocalizationService localizationService, IContentService contentService, int contentId, string contentPath, Uri current) { - var route = umbracoContext.ContentCache.GetRouteById(contentId); // cached - var pos = route.IndexOf('/'); + var route = umbracoContext == null + ? null // for tests only + : umbracoContext.ContentCache.GetRouteById(contentId); // cached - var domain = pos == 0 - ? null - : DomainHelper.DomainForNode(int.Parse(route.Substring(0, pos)), current).Domain; + Domain domain; + + if (route == null) + { + // if content is not published then route is null and we have to work + // on non-published content (note: could optimize by checking routes?) + + var content = contentService.GetById(contentId); + if (content == null) + return GetDefaultCulture(localizationService); + + var hasDomain = DomainHelper.NodeHasDomains(content.Id); + while (hasDomain == false && content != null) + { + content = content.Parent(); + hasDomain = content != null && DomainHelper.NodeHasDomains(content.Id); + } + + domain = hasDomain ? DomainHelper.DomainForNode(content.Id, current).Domain : null; + } + else + { + // if content is published then we have a (cached) route + // from which we can figure out the domain + + var pos = route.IndexOf('/'); + domain = pos == 0 + ? null + : DomainHelper.DomainForNode(int.Parse(route.Substring(0, pos)), current).Domain; + } if (domain == null) - { - var defaultLanguage = localizationService.GetAllLanguages().FirstOrDefault(); - return defaultLanguage == null ? CultureInfo.CurrentUICulture : new CultureInfo(defaultLanguage.IsoCode); - } + return GetDefaultCulture(localizationService); var wcDomain = DomainHelper.FindWildcardDomainInPath(DomainHelper.GetAllDomains(true), contentPath, domain.RootNodeId); return wcDomain == null ? new CultureInfo(domain.Language.CultureAlias) : new CultureInfo(wcDomain.Language.CultureAlias); } + + private static CultureInfo GetDefaultCulture(ILocalizationService localizationService) + { + var defaultLanguage = localizationService.GetAllLanguages().FirstOrDefault(); + return defaultLanguage == null ? CultureInfo.CurrentUICulture : new CultureInfo(defaultLanguage.IsoCode); + } } } diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index 5e750e3f2b..b855139a3c 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -1899,6 +1899,7 @@ namespace Umbraco.Web { return Models.ContentExtensions.GetCulture(UmbracoContext.Current, ApplicationContext.Current.Services.LocalizationService, + ApplicationContext.Current.Services.ContentService, content.Id, content.Path, current); }