From 9044c9328d362e7f2f41cc7c4d92761799fc97e7 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 24 Apr 2018 13:07:18 +1000 Subject: [PATCH] Gets inbound routing working, reduces the amount of non injected dependencies, reduces the amount of DomainHelper instances --- src/Umbraco.Core/Models/DomainExtensions.cs | 19 +++ src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../PublishedContentCacheTests.cs | 7 +- .../Integration/GetCultureTests.cs | 5 + .../PublishedContentMoreTests.cs | 3 +- .../PublishedContentTestElements.cs | 9 +- .../Routing/ContentFinderByIdTests.cs | 4 +- .../ContentFinderByNiceUrlAndTemplateTests.cs | 8 +- .../Routing/ContentFinderByNiceUrlTests.cs | 14 +- .../ContentFinderByNiceUrlWithDomainsTests.cs | 4 +- .../Routing/DomainsAndCulturesTests.cs | 6 +- .../Routing/NiceUrlProviderTests.cs | 10 +- .../NiceUrlsProviderWithDomainsTests.cs | 14 +- .../Routing/SiteDomainHelperTests.cs | 72 ++++----- .../Routing/UrlsWithNestedDomains.cs | 4 +- .../Scoping/ScopedNuCacheTests.cs | 8 +- .../Security/BackOfficeCookieManagerTests.cs | 13 +- .../TestControllerActivatorBase.cs | 4 +- .../TestHelpers/TestObjects-Mocks.cs | 2 +- .../TestHelpers/TestWithDatabaseBase.cs | 5 +- .../Testing/TestingTests/MockTests.cs | 3 +- ...RenderIndexActionSelectorAttributeTests.cs | 12 +- .../Web/Mvc/SurfaceControllerTests.cs | 5 + .../Web/Mvc/UmbracoViewPageTests.cs | 9 +- .../Web/TemplateUtilitiesTests.cs | 4 +- .../Web/WebExtensionMethodTests.cs | 10 +- .../Cache/CacheRefresherComponent.cs | 1 + src/Umbraco.Web/Composing/Current.cs | 5 +- src/Umbraco.Web/Models/ContentExtensions.cs | 45 +++--- .../Models/Mapping/ContentMapperProfile.cs | 5 +- .../Models/Mapping/ContentUrlResolver.cs | 15 +- .../PublishedCache/IPublishedContentCache.cs | 11 +- .../PublishedCache/NuCache/CacheKeys.cs | 9 +- .../PublishedCache/NuCache/ContentCache.cs | 54 +++---- .../NuCache/PublishedSnapshotService.cs | 12 +- .../XmlPublishedCache/DomainCache.cs | 11 +- .../PublishedContentCache.cs | 15 +- .../PublishedSnapshotService.cs | 16 +- .../XmlPublishedCache/XmlCacheComponent.cs | 2 + src/Umbraco.Web/PublishedContentExtensions.cs | 77 ++++++---- src/Umbraco.Web/Routing/AliasUrlProvider.cs | 9 +- .../Routing/ContentFinderByIdPath.cs | 13 +- .../Routing/ContentFinderByLegacy404.cs | 2 +- ...nderByNiceUrl.cs => ContentFinderByUrl.cs} | 126 ++++++++-------- ...te.cs => ContentFinderByUrlAndTemplate.cs} | 139 +++++++++--------- .../Routing/CustomRouteUrlProvider.cs | 3 +- src/Umbraco.Web/Routing/DefaultUrlProvider.cs | 19 ++- src/Umbraco.Web/Routing/Domain.cs | 9 +- src/Umbraco.Web/Routing/DomainHelper.cs | 23 +-- src/Umbraco.Web/Routing/IUrlProvider.cs | 3 +- src/Umbraco.Web/Routing/SiteDomainHelper.cs | 9 +- src/Umbraco.Web/Routing/UrlProvider.cs | 22 +-- .../Routing/UrlProviderExtensions.cs | 33 ++--- .../Runtime/WebRuntimeComponent.cs | 8 +- src/Umbraco.Web/Umbraco.Web.csproj | 4 +- src/Umbraco.Web/UmbracoContext.cs | 42 ++++-- src/Umbraco.Web/UmbracoModule.cs | 8 +- 57 files changed, 582 insertions(+), 423 deletions(-) create mode 100644 src/Umbraco.Core/Models/DomainExtensions.cs rename src/Umbraco.Web/Routing/{ContentFinderByNiceUrl.cs => ContentFinderByUrl.cs} (82%) rename src/Umbraco.Web/Routing/{ContentFinderByNiceUrlAndTemplate.cs => ContentFinderByUrlAndTemplate.cs} (76%) diff --git a/src/Umbraco.Core/Models/DomainExtensions.cs b/src/Umbraco.Core/Models/DomainExtensions.cs new file mode 100644 index 0000000000..47cd34105b --- /dev/null +++ b/src/Umbraco.Core/Models/DomainExtensions.cs @@ -0,0 +1,19 @@ +using Umbraco.Core.Services; + +namespace Umbraco.Core.Models +{ + public static class DomainExtensions + { + /// + /// Returns ture if the has a culture code equal to the default language specified + /// + /// + /// + /// + public static bool IsDefaultDomain(this IDomain domain, ILocalizationService localizationService) + { + var defaultLang = localizationService.GetDefaultVariantLanguage(); + return domain.LanguageIsoCode == defaultLang.CultureName; + } + } +} diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index c8f4ed577d..a8640d4c84 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -348,6 +348,7 @@ + diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs index f330c126d0..304c20c78f 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs @@ -62,9 +62,9 @@ namespace Umbraco.Tests.Cache.PublishedCache _xml.LoadXml(GetXml()); var xmlStore = new XmlStore(() => _xml, null, null, null); var cacheProvider = new StaticCacheProvider(); - var domainCache = new DomainCache(ServiceContext.DomainService); + var domainCache = new DomainCache(ServiceContext.DomainService, ServiceContext.LocalizationService); var publishedShapshot = new Umbraco.Web.PublishedCache.XmlPublishedCache.PublishedShapshot( - new PublishedContentCache(xmlStore, domainCache, cacheProvider, globalSettings, ContentTypesCache, null, null), + new PublishedContentCache(xmlStore, domainCache, cacheProvider, globalSettings, new SiteDomainHelper(), ContentTypesCache, null, null), new PublishedMediaCache(xmlStore, ServiceContext.MediaService, ServiceContext.UserService, cacheProvider, ContentTypesCache), new PublishedMemberCache(null, cacheProvider, Current.Services.MemberService, ContentTypesCache), domainCache); @@ -77,7 +77,8 @@ namespace Umbraco.Tests.Cache.PublishedCache new WebSecurity(_httpContextFactory.HttpContext, Current.Services.UserService, globalSettings), umbracoSettings, Enumerable.Empty(), - globalSettings); + globalSettings, + ServiceContext.EntityService); _cache = _umbracoContext.ContentCache; } diff --git a/src/Umbraco.Tests/Integration/GetCultureTests.cs b/src/Umbraco.Tests/Integration/GetCultureTests.cs index 5441024570..ec3a73b37e 100644 --- a/src/Umbraco.Tests/Integration/GetCultureTests.cs +++ b/src/Umbraco.Tests/Integration/GetCultureTests.cs @@ -54,18 +54,21 @@ namespace Umbraco.Tests.Integration var content = c2; var culture = global::Umbraco.Web.Models.ContentExtensions.GetCulture(null, ServiceContext.DomainService, ServiceContext.LocalizationService, ServiceContext.ContentService, + new SiteDomainHelper(), content.Id, content.Path, new Uri("http://domain1.com/")); Assert.AreEqual("en-US", culture.Name); content = c2; culture = global::Umbraco.Web.Models.ContentExtensions.GetCulture(null, ServiceContext.DomainService, ServiceContext.LocalizationService, ServiceContext.ContentService, + new SiteDomainHelper(), content.Id, content.Path, new Uri("http://domain1.fr/")); Assert.AreEqual("fr-FR", culture.Name); content = c4; culture = global::Umbraco.Web.Models.ContentExtensions.GetCulture(null, ServiceContext.DomainService, ServiceContext.LocalizationService, ServiceContext.ContentService, + new SiteDomainHelper(), content.Id, content.Path, new Uri("http://domain1.fr/")); Assert.AreEqual("de-DE", culture.Name); } @@ -102,12 +105,14 @@ namespace Umbraco.Tests.Integration var content = c2; var culture = Umbraco.Web.Models.ContentExtensions.GetCulture(null, ServiceContext.DomainService, ServiceContext.LocalizationService, ServiceContext.ContentService, + new SiteDomainHelper(), content.Id, content.Path, new Uri("http://domain1.com/")); Assert.AreEqual("de-DE", culture.Name); content = c4; culture = Umbraco.Web.Models.ContentExtensions.GetCulture(null, ServiceContext.DomainService, ServiceContext.LocalizationService, ServiceContext.ContentService, + new SiteDomainHelper(), content.Id, content.Path, new Uri("http://domain1.fr/")); Assert.AreEqual("fr-FR", culture.Name); } diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs index 2713229a5e..3e715792cb 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs @@ -74,7 +74,8 @@ namespace Umbraco.Tests.PublishedContent new WebSecurity(httpContext, Current.Services.UserService, globalSettings), TestObjects.GetUmbracoSettings(), Enumerable.Empty(), - globalSettings); + globalSettings, + ServiceContext.EntityService); return umbracoContext; } diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs index 9241686188..aa6f62cf46 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Moq; using Umbraco.Core; @@ -58,22 +59,22 @@ namespace Umbraco.Tests.PublishedContent _content.Clear(); } - public IPublishedContent GetByRoute(bool preview, string route, bool? hideTopLevelNode = null) + public IPublishedContent GetByRoute(bool preview, string route, bool? hideTopLevelNode = null, CultureInfo culture = null) { throw new NotImplementedException(); } - public IPublishedContent GetByRoute(string route, bool? hideTopLevelNode = null) + public IPublishedContent GetByRoute(string route, bool? hideTopLevelNode = null, CultureInfo culture = null) { throw new NotImplementedException(); } - public string GetRouteById(bool preview, int contentId, string language = null) + public string GetRouteById(bool preview, int contentId, CultureInfo culture = null) { throw new NotImplementedException(); } - public string GetRouteById(int contentId, string language = null) + public string GetRouteById(int contentId, CultureInfo culture = null) { throw new NotImplementedException(); } diff --git a/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs b/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs index 61c5b4aae9..2f2edf3964 100644 --- a/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs +++ b/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs @@ -1,6 +1,8 @@ using NUnit.Framework; +using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Tests.TestHelpers; using Umbraco.Web.Routing; +using LightInject; namespace Umbraco.Tests.Routing { @@ -15,7 +17,7 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext(urlAsString); var publishedRouter = CreatePublishedRouter(); var frequest = publishedRouter.CreateRequest(umbracoContext); - var lookup = new ContentFinderByIdPath(Logger); + var lookup = new ContentFinderByIdPath(Container.GetInstance().WebRouting, Logger); var result = lookup.TryFindContent(frequest); diff --git a/src/Umbraco.Tests/Routing/ContentFinderByNiceUrlAndTemplateTests.cs b/src/Umbraco.Tests/Routing/ContentFinderByNiceUrlAndTemplateTests.cs index c58899d4d1..7a4be24fbf 100644 --- a/src/Umbraco.Tests/Routing/ContentFinderByNiceUrlAndTemplateTests.cs +++ b/src/Umbraco.Tests/Routing/ContentFinderByNiceUrlAndTemplateTests.cs @@ -1,11 +1,13 @@ using Moq; -using NUnit.Framework; +using NUnit.Framework; +using LightInject; using Umbraco.Tests.TestHelpers; using Umbraco.Web.Routing; using Umbraco.Core.Models; using Umbraco.Tests.Testing; using Current = Umbraco.Web.Composing.Current; - +using Umbraco.Core.Configuration.UmbracoSettings; + namespace Umbraco.Tests.Routing { [TestFixture] @@ -37,7 +39,7 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext(urlAsString, template1.Id, globalSettings:globalSettings.Object); var publishedRouter = CreatePublishedRouter(); var frequest = publishedRouter.CreateRequest(umbracoContext); - var lookup = new ContentFinderByNiceUrlAndTemplate(Logger); + var lookup = new ContentFinderByUrlAndTemplate(Logger, ServiceContext.FileService); var result = lookup.TryFindContent(frequest); diff --git a/src/Umbraco.Tests/Routing/ContentFinderByNiceUrlTests.cs b/src/Umbraco.Tests/Routing/ContentFinderByNiceUrlTests.cs index 66f5cc722a..3e8101a212 100644 --- a/src/Umbraco.Tests/Routing/ContentFinderByNiceUrlTests.cs +++ b/src/Umbraco.Tests/Routing/ContentFinderByNiceUrlTests.cs @@ -34,7 +34,7 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext(urlString, globalSettings:globalSettingsMock.Object); var publishedRouter = CreatePublishedRouter(); var frequest = publishedRouter.CreateRequest(umbracoContext); - var lookup = new ContentFinderByNiceUrl(Logger); + var lookup = new ContentFinderByUrl(Logger); Assert.IsTrue(UmbracoConfig.For.GlobalSettings().HideTopLevelNodeFromPath); @@ -70,7 +70,7 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext(urlString, globalSettings:globalSettingsMock.Object); var publishedRouter = CreatePublishedRouter(); var frequest = publishedRouter.CreateRequest(umbracoContext); - var lookup = new ContentFinderByNiceUrl(Logger); + var lookup = new ContentFinderByUrl(Logger); Assert.IsFalse(UmbracoConfig.For.GlobalSettings().HideTopLevelNodeFromPath); @@ -96,7 +96,7 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext(urlString, globalSettings:globalSettingsMock.Object); var publishedRouter = CreatePublishedRouter(); var frequest = publishedRouter.CreateRequest(umbracoContext); - var lookup = new ContentFinderByNiceUrl(Logger); + var lookup = new ContentFinderByUrl(Logger); var result = lookup.TryFindContent(frequest); @@ -124,8 +124,8 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext(urlString, globalSettings:globalSettingsMock.Object); var publishedRouter = CreatePublishedRouter(); var frequest = publishedRouter.CreateRequest(umbracoContext); - frequest.Domain = new DomainAndUri(new Domain(1, "mysite", -1, CultureInfo.CurrentCulture, false), new Uri("http://mysite/")); - var lookup = new ContentFinderByNiceUrl(Logger); + frequest.Domain = new DomainAndUri(new Domain(1, "mysite", -1, CultureInfo.CurrentCulture, false, true), new Uri("http://mysite/")); + var lookup = new ContentFinderByUrl(Logger); var result = lookup.TryFindContent(frequest); @@ -154,8 +154,8 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext(urlString, globalSettings:globalSettingsMock.Object); var publishedRouter = CreatePublishedRouter(); var frequest = publishedRouter.CreateRequest(umbracoContext); - frequest.Domain = new DomainAndUri(new Domain(1, "mysite/æøå", -1, CultureInfo.CurrentCulture, false), new Uri("http://mysite/æøå")); - var lookup = new ContentFinderByNiceUrl(Logger); + frequest.Domain = new DomainAndUri(new Domain(1, "mysite/æøå", -1, CultureInfo.CurrentCulture, false, true), new Uri("http://mysite/æøå")); + var lookup = new ContentFinderByUrl(Logger); var result = lookup.TryFindContent(frequest); diff --git a/src/Umbraco.Tests/Routing/ContentFinderByNiceUrlWithDomainsTests.cs b/src/Umbraco.Tests/Routing/ContentFinderByNiceUrlWithDomainsTests.cs index 396697001d..2e9bccf398 100644 --- a/src/Umbraco.Tests/Routing/ContentFinderByNiceUrlWithDomainsTests.cs +++ b/src/Umbraco.Tests/Routing/ContentFinderByNiceUrlWithDomainsTests.cs @@ -135,7 +135,7 @@ namespace Umbraco.Tests.Routing // must lookup domain else lookup by url fails publishedRouter.FindDomain(frequest); - var lookup = new ContentFinderByNiceUrl(Logger); + var lookup = new ContentFinderByUrl(Logger); var result = lookup.TryFindContent(frequest); Assert.IsTrue(result); Assert.AreEqual(expectedId, frequest.PublishedContent.Id); @@ -179,7 +179,7 @@ namespace Umbraco.Tests.Routing publishedRouter.FindDomain(frequest); Assert.AreEqual(expectedCulture, frequest.Culture.Name); - var lookup = new ContentFinderByNiceUrl(Logger); + var lookup = new ContentFinderByUrl(Logger); var result = lookup.TryFindContent(frequest); Assert.IsTrue(result); Assert.AreEqual(expectedId, frequest.PublishedContent.Id); diff --git a/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs b/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs index b1d024cc8f..1740f1288c 100644 --- a/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs +++ b/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs @@ -277,7 +277,7 @@ namespace Umbraco.Tests.Routing Assert.AreEqual(expectedCulture, frequest.Culture.Name); - var finder = new ContentFinderByNiceUrl(Logger); + var finder = new ContentFinderByUrl(Logger); var result = finder.TryFindContent(frequest); Assert.IsTrue(result); @@ -326,7 +326,7 @@ namespace Umbraco.Tests.Routing publishedRouter.FindDomain(frequest); // find document - var finder = new ContentFinderByNiceUrl(Logger); + var finder = new ContentFinderByUrl(Logger); var result = finder.TryFindContent(frequest); // apply wildcard domain @@ -378,7 +378,7 @@ namespace Umbraco.Tests.Routing var content = umbracoContext.ContentCache.GetById(nodeId); Assert.IsNotNull(content); - var culture = global::Umbraco.Web.Models.ContentExtensions.GetCulture(umbracoContext, domainService, ServiceContext.LocalizationService, null, content.Id, content.Path, new Uri(currentUrl)); + var culture = global::Umbraco.Web.Models.ContentExtensions.GetCulture(umbracoContext, domainService, ServiceContext.LocalizationService, null, new SiteDomainHelper(), content.Id, content.Path, new Uri(currentUrl)); Assert.AreEqual(expectedCulture, culture.Name); } } diff --git a/src/Umbraco.Tests/Routing/NiceUrlProviderTests.cs b/src/Umbraco.Tests/Routing/NiceUrlProviderTests.cs index 246a9beb8a..a4b51bad85 100644 --- a/src/Umbraco.Tests/Routing/NiceUrlProviderTests.cs +++ b/src/Umbraco.Tests/Routing/NiceUrlProviderTests.cs @@ -45,7 +45,7 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext("/test", 1111, urlProviders: new [] { - new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object) + new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper()) }, globalSettings:globalSettings.Object); var requestHandlerMock = Mock.Get(_umbracoSettings.RequestHandler); @@ -108,7 +108,7 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext("/test", 1111, urlProviders: new[] { - new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object) + new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper()) }, globalSettings:globalSettings.Object); var requestMock = Mock.Get(_umbracoSettings.RequestHandler); @@ -138,7 +138,7 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext("/test", 1111, urlProviders: new[] { - new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object) + new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper()) }, globalSettings:globalSettings.Object); var requestMock = Mock.Get(_umbracoSettings.RequestHandler); @@ -162,7 +162,7 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext("http://example.com/test", 1111, umbracoSettings: _umbracoSettings, urlProviders: new[] { - new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object) + new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper()) }, globalSettings:globalSettings.Object); Assert.AreEqual("/home/sub1/custom-sub-1/", umbracoContext.UrlProvider.GetUrl(1177)); @@ -185,7 +185,7 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext("http://example.com/test", 1111, urlProviders: new[] { - new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object) + new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper()) }, globalSettings:globalSettings.Object); //mock the Umbraco settings that we need diff --git a/src/Umbraco.Tests/Routing/NiceUrlsProviderWithDomainsTests.cs b/src/Umbraco.Tests/Routing/NiceUrlsProviderWithDomainsTests.cs index fa223420f2..938f0cbec6 100644 --- a/src/Umbraco.Tests/Routing/NiceUrlsProviderWithDomainsTests.cs +++ b/src/Umbraco.Tests/Routing/NiceUrlsProviderWithDomainsTests.cs @@ -184,7 +184,7 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext("/test", 1111, umbracoSettings: settings, urlProviders: new[] { - new DefaultUrlProvider(settings.RequestHandler, Logger, globalSettings.Object) + new DefaultUrlProvider(settings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper()) }, globalSettings:globalSettings.Object); SetDomains1(); @@ -220,7 +220,7 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext("/test", 1111, umbracoSettings: settings, urlProviders: new[] { - new DefaultUrlProvider(settings.RequestHandler, Logger, globalSettings.Object) + new DefaultUrlProvider(settings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper()) }, globalSettings:globalSettings.Object); SetDomains2(); @@ -248,7 +248,7 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext("/test", 1111, umbracoSettings: settings, urlProviders: new[] { - new DefaultUrlProvider(settings.RequestHandler, Logger, globalSettings.Object) + new DefaultUrlProvider(settings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper()) }, globalSettings:globalSettings.Object); SetDomains3(); @@ -282,7 +282,7 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext("/test", 1111, umbracoSettings: settings, urlProviders: new[] { - new DefaultUrlProvider(settings.RequestHandler, Logger, globalSettings.Object) + new DefaultUrlProvider(settings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper()) }, globalSettings:globalSettings.Object); SetDomains4(); @@ -306,7 +306,7 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext("/test", 1111, umbracoSettings: settings, urlProviders: new[] { - new DefaultUrlProvider(settings.RequestHandler, Logger, globalSettings.Object) + new DefaultUrlProvider(settings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper()) }, globalSettings:globalSettings.Object); SetDomains4(); @@ -373,7 +373,7 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext("http://domain1.com/test", 1111, umbracoSettings: settings, urlProviders: new[] { - new DefaultUrlProvider(settings.RequestHandler, Logger, globalSettings.Object) + new DefaultUrlProvider(settings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper()) }, globalSettings:globalSettings.Object); SetDomains4(); @@ -405,7 +405,7 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext("http://domain1.com/en/test", 1111, umbracoSettings: settings, urlProviders: new[] { - new DefaultUrlProvider(settings.RequestHandler, Logger, globalSettings.Object) + new DefaultUrlProvider(settings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper()) }, globalSettings:globalSettings.Object); SetDomains5(); diff --git a/src/Umbraco.Tests/Routing/SiteDomainHelperTests.cs b/src/Umbraco.Tests/Routing/SiteDomainHelperTests.cs index 3b149280bd..fea8948b8e 100644 --- a/src/Umbraco.Tests/Routing/SiteDomainHelperTests.cs +++ b/src/Umbraco.Tests/Routing/SiteDomainHelperTests.cs @@ -188,8 +188,8 @@ namespace Umbraco.Tests.Routing var current = new Uri("https://www.domain1.com/foo/bar"); var domainAndUris = DomainAndUris(current, new[] { - new Domain(1, "domain2.com", -1, CultureInfo.CurrentCulture, false), - new Domain(1, "domain1.com", -1, CultureInfo.CurrentCulture, false), + new Domain(1, "domain2.com", -1, CultureInfo.CurrentCulture, false, true), + new Domain(1, "domain1.com", -1, CultureInfo.CurrentCulture, false, false), }); var output = helper.MapDomain(current, domainAndUris).Uri.ToString(); Assert.AreEqual("https://domain1.com/", output); @@ -198,8 +198,8 @@ namespace Umbraco.Tests.Routing current = new Uri("https://domain1.com/foo/bar"); domainAndUris = DomainAndUris(current, new[] { - new Domain(1, "https://domain1.com", -1, CultureInfo.CurrentCulture, false), - new Domain(1, "https://domain2.com", -1, CultureInfo.CurrentCulture, false) + new Domain(1, "https://domain1.com", -1, CultureInfo.CurrentCulture, false, true), + new Domain(1, "https://domain2.com", -1, CultureInfo.CurrentCulture, false, false) }); output = helper.MapDomain(current, domainAndUris).Uri.ToString(); Assert.AreEqual("https://domain1.com/", output); @@ -207,8 +207,8 @@ namespace Umbraco.Tests.Routing current = new Uri("https://domain1.com/foo/bar"); domainAndUris = DomainAndUris(current, new[] { - new Domain(1, "https://domain1.com", -1, CultureInfo.CurrentCulture, false), - new Domain(1, "https://domain4.com", -1, CultureInfo.CurrentCulture, false) + new Domain(1, "https://domain1.com", -1, CultureInfo.CurrentCulture, false, true), + new Domain(1, "https://domain4.com", -1, CultureInfo.CurrentCulture, false, false) }); output = helper.MapDomain(current, domainAndUris).Uri.ToString(); Assert.AreEqual("https://domain1.com/", output); @@ -216,8 +216,8 @@ namespace Umbraco.Tests.Routing current = new Uri("https://domain4.com/foo/bar"); domainAndUris = DomainAndUris(current, new[] { - new Domain(1, "https://domain1.com", -1, CultureInfo.CurrentCulture, false), - new Domain(1, "https://domain4.com", -1, CultureInfo.CurrentCulture, false) + new Domain(1, "https://domain1.com", -1, CultureInfo.CurrentCulture, false, true), + new Domain(1, "https://domain4.com", -1, CultureInfo.CurrentCulture, false, false) }); output = helper.MapDomain(current, domainAndUris).Uri.ToString(); Assert.AreEqual("https://domain4.com/", output); @@ -243,8 +243,8 @@ namespace Umbraco.Tests.Routing var current = new Uri("http://domain1.com/foo/bar"); var output = helper.MapDomain(current, new[] { - new DomainAndUri(new Domain(1, "domain1.com", -1, CultureInfo.CurrentCulture, false), current), - new DomainAndUri(new Domain(1, "domain2.com", -1, CultureInfo.CurrentCulture, false), current), + new DomainAndUri(new Domain(1, "domain1.com", -1, CultureInfo.CurrentCulture, false, true), current), + new DomainAndUri(new Domain(1, "domain2.com", -1, CultureInfo.CurrentCulture, false, false), current), }).Uri.ToString(); Assert.AreEqual("http://domain1.com/", output); @@ -254,8 +254,8 @@ namespace Umbraco.Tests.Routing current = new Uri("http://domain1.com/foo/bar"); output = helper.MapDomain(current, new[] { - new DomainAndUri(new Domain(1, "domain1.net", -1, CultureInfo.CurrentCulture, false), current), - new DomainAndUri(new Domain(1, "domain2.net", -1, CultureInfo.CurrentCulture, false), current) + new DomainAndUri(new Domain(1, "domain1.net", -1, CultureInfo.CurrentCulture, false, true), current), + new DomainAndUri(new Domain(1, "domain2.net", -1, CultureInfo.CurrentCulture, false, false), current) }).Uri.ToString(); Assert.AreEqual("http://domain1.net/", output); @@ -266,8 +266,8 @@ namespace Umbraco.Tests.Routing current = new Uri("http://domain1.com/foo/bar"); output = helper.MapDomain(current, new[] { - new DomainAndUri(new Domain(1, "domain2.net", -1, CultureInfo.CurrentCulture, false), current), - new DomainAndUri(new Domain(1, "domain1.net", -1, CultureInfo.CurrentCulture, false), current) + new DomainAndUri(new Domain(1, "domain2.net", -1, CultureInfo.CurrentCulture, false, true), current), + new DomainAndUri(new Domain(1, "domain1.net", -1, CultureInfo.CurrentCulture, false, false), current) }).Uri.ToString(); Assert.AreEqual("http://domain1.net/", output); } @@ -293,11 +293,11 @@ namespace Umbraco.Tests.Routing var current = new Uri("http://domain1.com/foo/bar"); var output = helper.MapDomains(current, new[] { - new DomainAndUri(new Domain(1, "domain1.com", -1, CultureInfo.CurrentCulture, false), current), // no: current + what MapDomain would pick - new DomainAndUri(new Domain(1, "domain2.com", -1, CultureInfo.CurrentCulture, false), current), // no: not same site - new DomainAndUri(new Domain(1, "domain3.com", -1, CultureInfo.CurrentCulture, false), current), // no: not same site - new DomainAndUri(new Domain(1, "domain4.com", -1, CultureInfo.CurrentCulture, false), current), // no: not same site - new DomainAndUri(new Domain(1, "domain1.org", -1, CultureInfo.CurrentCulture, false), current), // yes: same site (though bogus setup) + new DomainAndUri(new Domain(1, "domain1.com", -1, CultureInfo.CurrentCulture, false, true), current), // no: current + what MapDomain would pick + new DomainAndUri(new Domain(1, "domain2.com", -1, CultureInfo.CurrentCulture, false, false), current), // no: not same site + new DomainAndUri(new Domain(1, "domain3.com", -1, CultureInfo.CurrentCulture, false, false), current), // no: not same site + new DomainAndUri(new Domain(1, "domain4.com", -1, CultureInfo.CurrentCulture, false, false), current), // no: not same site + new DomainAndUri(new Domain(1, "domain1.org", -1, CultureInfo.CurrentCulture, false, false), current), // yes: same site (though bogus setup) }, true).ToArray(); Assert.AreEqual(1, output.Count()); @@ -308,11 +308,11 @@ namespace Umbraco.Tests.Routing current = new Uri("http://domain1.com/foo/bar"); output = helper.MapDomains(current, new[] { - new DomainAndUri(new Domain(1, "domain1.net", -1, CultureInfo.CurrentCulture, false), current), // no: what MapDomain would pick - new DomainAndUri(new Domain(1, "domain2.com", -1, CultureInfo.CurrentCulture, false), current), // no: not same site - new DomainAndUri(new Domain(1, "domain3.com", -1, CultureInfo.CurrentCulture, false), current), // no: not same site - new DomainAndUri(new Domain(1, "domain4.com", -1, CultureInfo.CurrentCulture, false), current), // no: not same site - new DomainAndUri(new Domain(1, "domain1.org", -1, CultureInfo.CurrentCulture, false), current), // yes: same site (though bogus setup) + new DomainAndUri(new Domain(1, "domain1.net", -1, CultureInfo.CurrentCulture, false, true), current), // no: what MapDomain would pick + new DomainAndUri(new Domain(1, "domain2.com", -1, CultureInfo.CurrentCulture, false, false), current), // no: not same site + new DomainAndUri(new Domain(1, "domain3.com", -1, CultureInfo.CurrentCulture, false, false), current), // no: not same site + new DomainAndUri(new Domain(1, "domain4.com", -1, CultureInfo.CurrentCulture, false, false), current), // no: not same site + new DomainAndUri(new Domain(1, "domain1.org", -1, CultureInfo.CurrentCulture, false, false), current), // yes: same site (though bogus setup) }, true).ToArray(); Assert.AreEqual(1, output.Count()); @@ -326,12 +326,12 @@ namespace Umbraco.Tests.Routing current = new Uri("http://domain1.com/foo/bar"); output = helper.MapDomains(current, new[] { - new DomainAndUri(new Domain(1, "domain1.com", -1, CultureInfo.CurrentCulture, false), current), // no: current + what MapDomain would pick - new DomainAndUri(new Domain(1, "domain2.com", -1, CultureInfo.CurrentCulture, false), current), // no: not same site - new DomainAndUri(new Domain(1, "domain3.com", -1, CultureInfo.CurrentCulture, false), current), // yes: bound site - new DomainAndUri(new Domain(1, "domain3.org", -1, CultureInfo.CurrentCulture, false), current), // yes: bound site - new DomainAndUri(new Domain(1, "domain4.com", -1, CultureInfo.CurrentCulture, false), current), // no: not same site - new DomainAndUri(new Domain(1, "domain1.org", -1, CultureInfo.CurrentCulture, false), current), // yes: same site (though bogus setup) + new DomainAndUri(new Domain(1, "domain1.com", -1, CultureInfo.CurrentCulture, false, true), current), // no: current + what MapDomain would pick + new DomainAndUri(new Domain(1, "domain2.com", -1, CultureInfo.CurrentCulture, false, false), current), // no: not same site + new DomainAndUri(new Domain(1, "domain3.com", -1, CultureInfo.CurrentCulture, false, false), current), // yes: bound site + new DomainAndUri(new Domain(1, "domain3.org", -1, CultureInfo.CurrentCulture, false, false), current), // yes: bound site + new DomainAndUri(new Domain(1, "domain4.com", -1, CultureInfo.CurrentCulture, false, false), current), // no: not same site + new DomainAndUri(new Domain(1, "domain1.org", -1, CultureInfo.CurrentCulture, false, false), current), // yes: same site (though bogus setup) }, true).ToArray(); Assert.AreEqual(3, output.Count()); @@ -344,12 +344,12 @@ namespace Umbraco.Tests.Routing current = new Uri("http://domain1.com/foo/bar"); output = helper.MapDomains(current, new[] { - new DomainAndUri(new Domain(1, "domain1.net", -1, CultureInfo.CurrentCulture, false), current), // no: what MapDomain would pick - new DomainAndUri(new Domain(1, "domain2.com", -1, CultureInfo.CurrentCulture, false), current), // no: not same site - new DomainAndUri(new Domain(1, "domain3.com", -1, CultureInfo.CurrentCulture, false), current), // yes: bound site - new DomainAndUri(new Domain(1, "domain3.org", -1, CultureInfo.CurrentCulture, false), current), // yes: bound site - new DomainAndUri(new Domain(1, "domain4.com", -1, CultureInfo.CurrentCulture, false), current), // no: not same site - new DomainAndUri(new Domain(1, "domain1.org", -1, CultureInfo.CurrentCulture, false), current), // yes: same site (though bogus setup) + new DomainAndUri(new Domain(1, "domain1.net", -1, CultureInfo.CurrentCulture, false, true), current), // no: what MapDomain would pick + new DomainAndUri(new Domain(1, "domain2.com", -1, CultureInfo.CurrentCulture, false, false), current), // no: not same site + new DomainAndUri(new Domain(1, "domain3.com", -1, CultureInfo.CurrentCulture, false, false), current), // yes: bound site + new DomainAndUri(new Domain(1, "domain3.org", -1, CultureInfo.CurrentCulture, false, false), current), // yes: bound site + new DomainAndUri(new Domain(1, "domain4.com", -1, CultureInfo.CurrentCulture, false, false), current), // no: not same site + new DomainAndUri(new Domain(1, "domain1.org", -1, CultureInfo.CurrentCulture, false, false), current), // yes: same site (though bogus setup) }, true).ToArray(); Assert.AreEqual(3, output.Count()); diff --git a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs index 41a7bf730d..0996aaab03 100644 --- a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs +++ b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs @@ -44,7 +44,7 @@ namespace Umbraco.Tests.Routing // get the nice url for 100111 var umbracoContext = GetUmbracoContext(url, 9999, umbracoSettings: settings, urlProviders: new [] { - new DefaultUrlProvider(settings.RequestHandler, Logger, globalSettings.Object) + new DefaultUrlProvider(settings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper()) }, globalSettings:globalSettings.Object); Assert.AreEqual("http://domain2.com/1001-1-1/", umbracoContext.UrlProvider.GetUrl(100111, true)); @@ -62,7 +62,7 @@ namespace Umbraco.Tests.Routing Assert.IsTrue(frequest.HasDomain); // check that it's been routed - var lookup = new ContentFinderByNiceUrl(Logger); + var lookup = new ContentFinderByUrl(Logger); var result = lookup.TryFindContent(frequest); Assert.IsTrue(result); Assert.AreEqual(100111, frequest.PublishedContent.Id); diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs index 585a943416..bb3b41d128 100644 --- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs @@ -90,7 +90,7 @@ namespace Umbraco.Tests.Scoping publishedSnapshotAccessor, Logger, ScopeProvider, - documentRepository, mediaRepository, memberRepository, Container.GetInstance()); + documentRepository, mediaRepository, memberRepository, Container.GetInstance(), new SiteDomainHelper()); } protected UmbracoContext GetUmbracoContextNu(string url, int templateId = 1234, RouteData routeData = null, bool setSingleton = false, IUmbracoSettingsSection umbracoSettings = null, IEnumerable urlProviders = null) @@ -100,13 +100,15 @@ namespace Umbraco.Tests.Scoping var httpContext = GetHttpContextFactory(url, routeData).HttpContext; + var globalSettings = TestObjects.GetGlobalSettings(); var umbracoContext = new UmbracoContext( httpContext, service, - new WebSecurity(httpContext, Current.Services.UserService, TestObjects.GetGlobalSettings()), + new WebSecurity(httpContext, Current.Services.UserService, globalSettings), umbracoSettings ?? SettingsForTests.GetDefaultUmbracoSettings(), urlProviders ?? Enumerable.Empty(), - TestObjects.GetGlobalSettings()); + globalSettings, + Mock.Of()); if (setSingleton) Umbraco.Web.Composing.Current.UmbracoContextAccessor.UmbracoContext = umbracoContext; diff --git a/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs b/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs index 1b182024c3..51d6a7fa7d 100644 --- a/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs +++ b/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs @@ -7,6 +7,7 @@ using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Composing; +using Umbraco.Core.Services; using Umbraco.Tests.Testing; using Umbraco.Web; using Umbraco.Web.PublishedCache; @@ -26,11 +27,13 @@ namespace Umbraco.Tests.Security //should force app ctx to show not-configured ConfigurationManager.AppSettings.Set("umbracoConfigurationStatus", ""); + var globalSettings = TestObjects.GetGlobalSettings(); var umbracoContext = new UmbracoContext( Mock.Of(), Mock.Of(), - new WebSecurity(Mock.Of(), Current.Services.UserService, TestObjects.GetGlobalSettings()), - TestObjects.GetUmbracoSettings(), new List(),TestObjects.GetGlobalSettings()); + new WebSecurity(Mock.Of(), Current.Services.UserService, globalSettings), + TestObjects.GetUmbracoSettings(), new List(),globalSettings, + Mock.Of()); var runtime = Mock.Of(x => x.Level == RuntimeLevel.Install); var mgr = new BackOfficeCookieManager( @@ -44,11 +47,13 @@ namespace Umbraco.Tests.Security [Test] public void ShouldAuthenticateRequest_When_Configured() { + var globalSettings = TestObjects.GetGlobalSettings(); var umbCtx = new UmbracoContext( Mock.Of(), Mock.Of(), - new WebSecurity(Mock.Of(), Current.Services.UserService, TestObjects.GetGlobalSettings()), - TestObjects.GetUmbracoSettings(), new List(), TestObjects.GetGlobalSettings()); + new WebSecurity(Mock.Of(), Current.Services.UserService, globalSettings), + TestObjects.GetUmbracoSettings(), new List(), globalSettings, + Mock.Of()); var runtime = Mock.Of(x => x.Level == RuntimeLevel.Run); var mgr = new BackOfficeCookieManager(Mock.Of(accessor => accessor.UmbracoContext == umbCtx), runtime, TestObjects.GetGlobalSettings()); diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs index 7a8188cd0b..05e9a39551 100644 --- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs +++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs @@ -28,6 +28,7 @@ using Umbraco.Web.Routing; using Umbraco.Web.Security; using Umbraco.Web.WebApi; using LightInject; +using System.Globalization; namespace Umbraco.Tests.TestHelpers.ControllerTesting { @@ -148,10 +149,11 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting Mock.Of(section => section.WebRouting == Mock.Of(routingSection => routingSection.UrlProviderMode == UrlProviderMode.Auto.ToString())), Enumerable.Empty(), globalSettings, + mockedEntityService, true); //replace it var urlHelper = new Mock(); - urlHelper.Setup(provider => provider.GetUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + urlHelper.Setup(provider => provider.GetUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns("/hello/world/1234"); var membershipHelper = new MembershipHelper(umbCtx, Mock.Of(), Mock.Of()); diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs index 50cb115eae..050c10757a 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs @@ -119,7 +119,7 @@ namespace Umbraco.Tests.TestHelpers var urlProviders = Enumerable.Empty(); if (accessor == null) accessor = new TestUmbracoContextAccessor(); - return UmbracoContext.EnsureContext(accessor, httpContext, publishedSnapshotService, webSecurity, umbracoSettings, urlProviders, globalSettings, true); + return UmbracoContext.EnsureContext(accessor, httpContext, publishedSnapshotService, webSecurity, umbracoSettings, urlProviders, globalSettings, Mock.Of(), true); } public IUmbracoSettingsSection GetUmbracoSettings() diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index 9a2828fd9f..2b6dcffeab 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -265,7 +265,7 @@ namespace Umbraco.Tests.TestHelpers cache, publishedSnapshotAccessor, Container.GetInstance(), Container.GetInstance(), Container.GetInstance(), Logger, - Container.GetInstance(), + Container.GetInstance(), new SiteDomainHelper(), ContentTypesCache, null, true, Options.PublishedRepositoryEvents); @@ -366,7 +366,8 @@ namespace Umbraco.Tests.TestHelpers new WebSecurity(httpContext, Container.GetInstance(), Container.GetInstance()), umbracoSettings ?? Container.GetInstance(), urlProviders ?? Enumerable.Empty(), - globalSettings ?? Container.GetInstance()); + globalSettings ?? Container.GetInstance(), + ServiceContext.EntityService); if (setSingleton) Umbraco.Web.Composing.Current.UmbracoContextAccessor.UmbracoContext = umbracoContext; diff --git a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs index 580defd5ab..7575bb3d1f 100644 --- a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs +++ b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Web.Security; using Moq; using NUnit.Framework; @@ -73,7 +74,7 @@ namespace Umbraco.Tests.Testing.TestingTests var umbracoContext = TestObjects.GetUmbracoContextMock(); var urlProviderMock = new Mock(); - urlProviderMock.Setup(provider => provider.GetUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + urlProviderMock.Setup(provider => provider.GetUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns("/hello/world/1234"); var urlProvider = urlProviderMock.Object; diff --git a/src/Umbraco.Tests/Web/Mvc/RenderIndexActionSelectorAttributeTests.cs b/src/Umbraco.Tests/Web/Mvc/RenderIndexActionSelectorAttributeTests.cs index 1a61882949..1f5fe1a6e3 100644 --- a/src/Umbraco.Tests/Web/Mvc/RenderIndexActionSelectorAttributeTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/RenderIndexActionSelectorAttributeTests.cs @@ -71,7 +71,8 @@ namespace Umbraco.Tests.Web.Mvc new Mock(null, null, globalSettings).Object, TestObjects.GetUmbracoSettings(), Enumerable.Empty(), - globalSettings, + globalSettings, + Mock.Of(), true); var ctrl = new MatchesDefaultIndexController { UmbracoContext = umbCtx }; var controllerCtx = new ControllerContext(req, ctrl); @@ -94,7 +95,8 @@ namespace Umbraco.Tests.Web.Mvc new Mock(null, null, globalSettings).Object, TestObjects.GetUmbracoSettings(), Enumerable.Empty(), - globalSettings, + globalSettings, + Mock.Of(), true); var ctrl = new MatchesOverriddenIndexController { UmbracoContext = umbCtx }; var controllerCtx = new ControllerContext(req, ctrl); @@ -117,7 +119,8 @@ namespace Umbraco.Tests.Web.Mvc new Mock(null, null, globalSettings).Object, TestObjects.GetUmbracoSettings(), Enumerable.Empty(), - globalSettings, + globalSettings, + Mock.Of(), true); var ctrl = new MatchesCustomIndexController { UmbracoContext = umbCtx }; var controllerCtx = new ControllerContext(req, ctrl); @@ -140,7 +143,8 @@ namespace Umbraco.Tests.Web.Mvc new Mock(null, null, globalSettings).Object, TestObjects.GetUmbracoSettings(), Enumerable.Empty(), - globalSettings, + globalSettings, + Mock.Of(), true); var ctrl = new MatchesAsyncIndexController { UmbracoContext = umbCtx }; var controllerCtx = new ControllerContext(req, ctrl); diff --git a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs index d9a12751c0..927b5557bd 100644 --- a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs @@ -45,6 +45,7 @@ namespace Umbraco.Tests.Web.Mvc TestObjects.GetUmbracoSettings(), Enumerable.Empty(), globalSettings, + Mock.Of(), true); var ctrl = new TestSurfaceController { UmbracoContext = umbracoContext }; @@ -66,6 +67,7 @@ namespace Umbraco.Tests.Web.Mvc TestObjects.GetUmbracoSettings(), Enumerable.Empty(), globalSettings, + Mock.Of(), true); var ctrl = new TestSurfaceController { UmbracoContext = umbCtx }; @@ -85,6 +87,7 @@ namespace Umbraco.Tests.Web.Mvc TestObjects.GetUmbracoSettings(), Enumerable.Empty(), globalSettings, + Mock.Of(), true); var controller = new TestSurfaceController { UmbracoContext = umbracoContext }; @@ -111,6 +114,7 @@ namespace Umbraco.Tests.Web.Mvc Mock.Of(section => section.WebRouting == Mock.Of(routingSection => routingSection.UrlProviderMode == "AutoLegacy")), Enumerable.Empty(), globalSettings, + Mock.Of(), true); var helper = new UmbracoHelper( @@ -148,6 +152,7 @@ namespace Umbraco.Tests.Web.Mvc Mock.Of(section => section.WebRouting == webRoutingSettings), Enumerable.Empty(), globalSettings, + Mock.Of(), true); var content = Mock.Of(publishedContent => publishedContent.Id == 12345); diff --git a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs index 053a1f7c5d..9fe3b44264 100644 --- a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs @@ -425,17 +425,20 @@ namespace Umbraco.Tests.Web.Mvc var factory = Mock.Of(); _service = new PublishedSnapshotService(svcCtx, factory, scopeProvider, cache, Enumerable.Empty(), null, null, null, null, - Current.Logger, TestObjects.GetGlobalSettings(), null, true, false); // no events + Current.Logger, TestObjects.GetGlobalSettings(), new SiteDomainHelper(), null, true, false); // no events var http = GetHttpContextFactory(url, routeData).HttpContext; + + var globalSettings = TestObjects.GetGlobalSettings(); var ctx = new UmbracoContext( GetHttpContextFactory(url, routeData).HttpContext, _service, - new WebSecurity(http, Current.Services.UserService, TestObjects.GetGlobalSettings()), + new WebSecurity(http, Current.Services.UserService, globalSettings), TestObjects.GetUmbracoSettings(), Enumerable.Empty(), - TestObjects.GetGlobalSettings()); + globalSettings, + Mock.Of()); //if (setSingleton) //{ diff --git a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs index e6a5dd8438..ed06948e3f 100644 --- a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs +++ b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Web; using LightInject; using Moq; @@ -72,7 +73,7 @@ namespace Umbraco.Tests.Web //setup a mock url provider which we'll use fo rtesting var testUrlProvider = new Mock(); - testUrlProvider.Setup(x => x.GetUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + testUrlProvider.Setup(x => x.GetUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns((UmbracoContext umbCtx, int id, Uri url, UrlProviderMode mode) => { return "/my-test-url"; @@ -90,6 +91,7 @@ namespace Umbraco.Tests.Web //pass in the custom url provider new[]{ testUrlProvider.Object }, globalSettings, + entityService.Object, true)) { var output = TemplateUtilities.ParseInternalLinks(input, umbCtx.UrlProvider); diff --git a/src/Umbraco.Tests/Web/WebExtensionMethodTests.cs b/src/Umbraco.Tests/Web/WebExtensionMethodTests.cs index 86339c309f..cc97633cde 100644 --- a/src/Umbraco.Tests/Web/WebExtensionMethodTests.cs +++ b/src/Umbraco.Tests/Web/WebExtensionMethodTests.cs @@ -5,6 +5,7 @@ using System.Web.Mvc; using System.Web.Routing; using Moq; using NUnit.Framework; +using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Tests.Testing; using Umbraco.Web; @@ -29,7 +30,8 @@ namespace Umbraco.Tests.Web new WebSecurity(Mock.Of(), Current.Services.UserService, TestObjects.GetGlobalSettings()), TestObjects.GetUmbracoSettings(), new List(), - TestObjects.GetGlobalSettings()); + TestObjects.GetGlobalSettings(), + Mock.Of()); var r1 = new RouteData(); r1.DataTokens.Add(Core.Constants.Web.UmbracoContextDataToken, umbCtx); @@ -46,7 +48,8 @@ namespace Umbraco.Tests.Web new WebSecurity(Mock.Of(), Current.Services.UserService, TestObjects.GetGlobalSettings()), TestObjects.GetUmbracoSettings(), new List(), - TestObjects.GetGlobalSettings()); + TestObjects.GetGlobalSettings(), + Mock.Of()); var r1 = new RouteData(); r1.DataTokens.Add(Core.Constants.Web.UmbracoContextDataToken, umbCtx); @@ -73,7 +76,8 @@ namespace Umbraco.Tests.Web new WebSecurity(Mock.Of(), Current.Services.UserService, TestObjects.GetGlobalSettings()), TestObjects.GetUmbracoSettings(), new List(), - TestObjects.GetGlobalSettings()); + TestObjects.GetGlobalSettings(), + Mock.Of()); var httpContext = Mock.Of(); diff --git a/src/Umbraco.Web/Cache/CacheRefresherComponent.cs b/src/Umbraco.Web/Cache/CacheRefresherComponent.cs index 15030db207..07dcebd763 100644 --- a/src/Umbraco.Web/Cache/CacheRefresherComponent.cs +++ b/src/Umbraco.Web/Cache/CacheRefresherComponent.cs @@ -237,6 +237,7 @@ namespace Umbraco.Web.Cache UmbracoConfig.For.UmbracoSettings(), Current.UrlProviders, UmbracoConfig.For.GlobalSettings(), + Current.Services.EntityService, true); } diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index b819046a9a..5ca7b60cf0 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -142,10 +142,7 @@ namespace Umbraco.Web.Composing internal static IPublishedSnapshotService PublishedSnapshotService => Container.GetInstance(); - - public static ISiteDomainHelper SiteDomainHelper - => Container.GetInstance(); - + public static ThumbnailProviderCollection ThumbnailProviders => Container.GetInstance(); diff --git a/src/Umbraco.Web/Models/ContentExtensions.cs b/src/Umbraco.Web/Models/ContentExtensions.cs index 4a016a895b..0712e2503d 100644 --- a/src/Umbraco.Web/Models/ContentExtensions.cs +++ b/src/Umbraco.Web/Models/ContentExtensions.cs @@ -11,23 +11,27 @@ namespace Umbraco.Web.Models { public static class ContentExtensions { - /// - /// Gets the culture that would be selected to render a specified content, - /// within the context of a specified current request. - /// - /// The content. - /// The request Uri. - /// The culture that would be selected to render the content. - public static CultureInfo GetCulture(this IContent content, Uri current = null) - { - return GetCulture(UmbracoContext.Current, - Current.Services.DomainService, - Current.Services.LocalizationService, - Current.Services.ContentService, - content.Id, content.Path, - current); - } + //TODO: Not used + ///// + ///// Gets the culture that would be selected to render a specified content, + ///// within the context of a specified current request. + ///// + ///// The content. + ///// The request Uri. + ///// The culture that would be selected to render the content. + //public static CultureInfo GetCulture(this IContent content, Uri current = null) + //{ + // return GetCulture(UmbracoContext.Current, + // Current.Services.DomainService, + // Current.Services.LocalizationService, + // Current.Services.ContentService, + // content.Id, content.Path, + // current); + //} + + + //TODO: Not used - only in tests /// /// Gets the culture that would be selected to render a specified content, /// within the context of a specified current request. @@ -42,6 +46,7 @@ namespace Umbraco.Web.Models /// The culture that would be selected to render the content. internal static CultureInfo GetCulture(UmbracoContext umbracoContext, IDomainService domainService, ILocalizationService localizationService, IContentService contentService, + ISiteDomainHelper siteDomainHelper, int contentId, string contentPath, Uri current) { var route = umbracoContext == null @@ -49,9 +54,9 @@ namespace Umbraco.Web.Models : umbracoContext.ContentCache.GetRouteById(contentId); // may be cached var domainCache = umbracoContext == null - ? new PublishedCache.XmlPublishedCache.DomainCache(domainService) // for tests only + ? new PublishedCache.XmlPublishedCache.DomainCache(domainService, localizationService) // for tests only : umbracoContext.PublishedShapshot.Domains; // default - var domainHelper = new DomainHelper(domainCache); + var domainHelper = umbracoContext.GetDomainHelper(siteDomainHelper); Domain domain; if (route == null) @@ -59,6 +64,8 @@ namespace Umbraco.Web.Models // if content is not published then route is null and we have to work // on non-published content (note: could optimize by checking routes?) + // fixme - even non-published content is stored in the cache or in the cmsContentNu table which would be faster to lookup + var content = contentService.GetById(contentId); if (content == null) return GetDefaultCulture(localizationService); @@ -93,7 +100,7 @@ namespace Umbraco.Web.Models private static CultureInfo GetDefaultCulture(ILocalizationService localizationService) { - var defaultLanguage = localizationService.GetAllLanguages().FirstOrDefault(); + var defaultLanguage = localizationService.GetDefaultVariantLanguage(); return defaultLanguage == null ? CultureInfo.CurrentUICulture : new CultureInfo(defaultLanguage.IsoCode); } diff --git a/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs index 627f508906..059dd32499 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs @@ -1,6 +1,7 @@ using System.Linq; using AutoMapper; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; @@ -13,7 +14,7 @@ namespace Umbraco.Web.Models.Mapping /// internal class ContentMapperProfile : Profile { - public ContentMapperProfile(IUserService userService, ILocalizedTextService textService, IContentService contentService, IContentTypeService contentTypeService, IDataTypeService dataTypeService, ILocalizationService localizationService) + public ContentMapperProfile(IUserService userService, ILocalizedTextService textService, IContentService contentService, IContentTypeService contentTypeService, IDataTypeService dataTypeService, ILocalizationService localizationService, ILogger logger) { // create, capture, cache var contentOwnerResolver = new OwnerResolver(userService); @@ -24,7 +25,7 @@ namespace Umbraco.Web.Models.Mapping var contentTypeBasicResolver = new ContentTypeBasicResolver(); var contentTreeNodeUrlResolver = new ContentTreeNodeUrlResolver(); var defaultTemplateResolver = new DefaultTemplateResolver(); - var contentUrlResolver = new ContentUrlResolver(); + var contentUrlResolver = new ContentUrlResolver(textService, contentService, logger); var variantResolver = new ContentItemDisplayVariationResolver(localizationService); //FROM IContent TO ContentItemDisplay diff --git a/src/Umbraco.Web/Models/Mapping/ContentUrlResolver.cs b/src/Umbraco.Web/Models/Mapping/ContentUrlResolver.cs index 909ca83985..e311190d67 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentUrlResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentUrlResolver.cs @@ -1,6 +1,8 @@ using System.Linq; using AutoMapper; +using Umbraco.Core.Logging; using Umbraco.Core.Models; +using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Routing; @@ -8,13 +10,24 @@ namespace Umbraco.Web.Models.Mapping { internal class ContentUrlResolver : IValueResolver { + private readonly ILocalizedTextService _textService; + private readonly IContentService _contentService; + private readonly ILogger _logger; + + public ContentUrlResolver(ILocalizedTextService textService, IContentService contentService, ILogger logger) + { + _textService = textService; + _contentService = contentService; + _logger = logger; + } + public string[] Resolve(IContent source, ContentItemDisplay destination, string[] destMember, ResolutionContext context) { var umbracoContext = context.GetUmbracoContext(throwIfMissing: false); var urls = umbracoContext == null ? new[] {"Cannot generate urls without a current Umbraco Context"} - : source.GetContentUrls(umbracoContext).ToArray(); + : source.GetContentUrls(umbracoContext.UrlProvider, _textService, _contentService, _logger).ToArray(); return urls; } diff --git a/src/Umbraco.Web/PublishedCache/IPublishedContentCache.cs b/src/Umbraco.Web/PublishedCache/IPublishedContentCache.cs index 64fa5efde4..2d7c93d93e 100644 --- a/src/Umbraco.Web/PublishedCache/IPublishedContentCache.cs +++ b/src/Umbraco.Web/PublishedCache/IPublishedContentCache.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Models; +using System.Globalization; +using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; namespace Umbraco.Web.PublishedCache @@ -17,7 +18,7 @@ namespace Umbraco.Web.PublishedCache /// If is null then the settings value is used. /// The value of overrides defaults. /// - IPublishedContent GetByRoute(bool preview, string route, bool? hideTopLevelNode = null); + IPublishedContent GetByRoute(bool preview, string route, bool? hideTopLevelNode = null, CultureInfo culture = null); /// /// Gets content identified by a route. @@ -30,7 +31,7 @@ namespace Umbraco.Web.PublishedCache /// If is null then the settings value is used. /// Considers published or unpublished content depending on defaults. /// - IPublishedContent GetByRoute(string route, bool? hideTopLevelNode = null); + IPublishedContent GetByRoute(string route, bool? hideTopLevelNode = null, CultureInfo culture = null); /// /// Gets the route for a content identified by its unique identifier. @@ -39,7 +40,7 @@ namespace Umbraco.Web.PublishedCache /// The content unique identifier. /// The route. /// The value of overrides defaults. - string GetRouteById(bool preview, int contentId, string language = null); + string GetRouteById(bool preview, int contentId, CultureInfo culture = null); /// /// Gets the route for a content identified by its unique identifier. @@ -47,6 +48,6 @@ namespace Umbraco.Web.PublishedCache /// The content unique identifier. /// The route. /// Considers published or unpublished content depending on defaults. - string GetRouteById(int contentId, string language = null); + string GetRouteById(int contentId, CultureInfo culture = null); } } diff --git a/src/Umbraco.Web/PublishedCache/NuCache/CacheKeys.cs b/src/Umbraco.Web/PublishedCache/NuCache/CacheKeys.cs index 6d21fedb6d..9d887f4d40 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/CacheKeys.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/CacheKeys.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Runtime.CompilerServices; namespace Umbraco.Web.PublishedCache.NuCache @@ -12,9 +13,9 @@ namespace Umbraco.Web.PublishedCache.NuCache } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static string LangId(string language) + private static string LangId(CultureInfo culture) { - return language != null ? ("-L:" + language) : string.Empty; + return culture != null ? ("-L:" + culture.Name) : string.Empty; } public static string PublishedContentChildren(Guid contentUid, bool previewing) @@ -56,9 +57,9 @@ namespace Umbraco.Web.PublishedCache.NuCache // a valid ID in the database at that point, whereas content and properties // may be virtual (and not in umbracoNode). - public static string ContentCacheRouteByContent(int id, bool previewing, string language) + public static string ContentCacheRouteByContent(int id, bool previewing, CultureInfo culture) { - return "NuCache.ContentCache.RouteByContent[" + DraftOrPub(previewing) + id + LangId(language) + "]"; + return "NuCache.ContentCache.RouteByContent[" + DraftOrPub(previewing) + id + LangId(culture) + "]"; } public static string ContentCacheContentByRoute(string route, bool previewing) diff --git a/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs b/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs index f27d2c9937..74598186f6 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs @@ -55,21 +55,21 @@ namespace Umbraco.Web.PublishedCache.NuCache // at the moment we try our best to be backward compatible, but really, // should get rid of hideTopLevelNode and other oddities entirely, eventually - public IPublishedContent GetByRoute(string route, bool? hideTopLevelNode = null) + public IPublishedContent GetByRoute(string route, bool? hideTopLevelNode = null, CultureInfo culture = null) { - return GetByRoute(PreviewDefault, route, hideTopLevelNode); + return GetByRoute(PreviewDefault, route, hideTopLevelNode, culture); } - public IPublishedContent GetByRoute(bool preview, string route, bool? hideTopLevelNode = null) + public IPublishedContent GetByRoute(bool preview, string route, bool? hideTopLevelNode = null, CultureInfo culture = null) { if (route == null) throw new ArgumentNullException(nameof(route)); var cache = preview == false || PublishedSnapshotService.FullCacheWhenPreviewing ? _elementsCache : _snapshotCache; var key = CacheKeys.ContentCacheContentByRoute(route, preview); - return cache.GetCacheItem(key, () => GetByRouteInternal(preview, route, hideTopLevelNode)); + return cache.GetCacheItem(key, () => GetByRouteInternal(preview, route, hideTopLevelNode, culture)); } - private IPublishedContent GetByRouteInternal(bool preview, string route, bool? hideTopLevelNode) + private IPublishedContent GetByRouteInternal(bool preview, string route, bool? hideTopLevelNode, CultureInfo culture) { hideTopLevelNode = hideTopLevelNode ?? HideTopLevelNodeFromPath; // default = settings @@ -90,7 +90,7 @@ namespace Umbraco.Web.PublishedCache.NuCache // note: if domain has a path (eg example.com/en) which is not recommended anymore // then then /en part of the domain is basically ignored here... content = GetById(preview, startNodeId); - content = FollowRoute(content, parts, 0); + content = FollowRoute(content, parts, 0, culture); } else if (parts.Length == 0) { @@ -106,7 +106,7 @@ namespace Umbraco.Web.PublishedCache.NuCache content = hideTopLevelNode.Value ? GetAtRoot(preview).SelectMany(x => x.Children).FirstOrDefault(x => x.UrlName == parts[0]) : GetAtRoot(preview).FirstOrDefault(x => x.UrlName == parts[0]); - content = FollowRoute(content, parts, 1); + content = FollowRoute(content, parts, 1, culture); } // if hideTopLevelNodePath is true then for url /foo we looked for /*/foo @@ -120,19 +120,19 @@ namespace Umbraco.Web.PublishedCache.NuCache return content; } - public string GetRouteById(int contentId, string language = null) + public string GetRouteById(int contentId, CultureInfo culture = null) { - return GetRouteById(PreviewDefault, contentId, language); + return GetRouteById(PreviewDefault, contentId, culture); } - public string GetRouteById(bool preview, int contentId, string language = null) + public string GetRouteById(bool preview, int contentId, CultureInfo culture = null) { var cache = (preview == false || PublishedSnapshotService.FullCacheWhenPreviewing) ? _elementsCache : _snapshotCache; - var key = CacheKeys.ContentCacheRouteByContent(contentId, preview, language); - return cache.GetCacheItem(key, () => GetRouteByIdInternal(preview, contentId, null, language)); + var key = CacheKeys.ContentCacheRouteByContent(contentId, preview, culture); + return cache.GetCacheItem(key, () => GetRouteByIdInternal(preview, contentId, null, culture)); } - private string GetRouteByIdInternal(bool preview, int contentId, bool? hideTopLevelNode, string language) + private string GetRouteByIdInternal(bool preview, int contentId, bool? hideTopLevelNode, CultureInfo culture) { var node = GetById(preview, contentId); if (node == null) @@ -147,23 +147,7 @@ namespace Umbraco.Web.PublishedCache.NuCache var hasDomains = _domainHelper.NodeHasDomains(n.Id); while (hasDomains == false && n != null) // n is null at root { - // get the url - string urlName; - if (n.ContentType.Variations.HasFlag(ContentVariation.CultureNeutral)) - { - var cultureCode = language != null - ? language - : _localizationService.GetDefaultVariantLanguage()?.IsoCode; - - if (n.CultureNames.TryGetValue(cultureCode, out var cultureName)) - urlName = cultureName.UrlName; - else - urlName = n.UrlName; //couldn't get the value, fallback to invariant ... not sure what else to do - } - else - { - urlName = n.UrlName; - } + var urlName = n.GetUrlName(_localizationService, culture); pathParts.Add(urlName); @@ -184,13 +168,17 @@ namespace Umbraco.Web.PublishedCache.NuCache return route; } - private static IPublishedContent FollowRoute(IPublishedContent content, IReadOnlyList parts, int start) + private IPublishedContent FollowRoute(IPublishedContent content, IReadOnlyList parts, int start, CultureInfo culture) { var i = start; while (content != null && i < parts.Count) { var part = parts[i++]; - content = content.Children.FirstOrDefault(x => x.UrlName == part); + content = content.Children.FirstOrDefault(x => + { + var urlName = x.GetUrlName(_localizationService, culture); + return urlName == part; + }); } return content; } @@ -266,7 +254,7 @@ namespace Umbraco.Web.PublishedCache.NuCache return GetAtRootNoCache(preview); // note: ToArray is important here, we want to cache the result, not the function! - return (IEnumerable) cache.GetCacheItem( + return (IEnumerable)cache.GetCacheItem( CacheKeys.ContentCacheRoots(preview), () => GetAtRootNoCache(preview).ToArray()); } diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs index a02405c804..eae0fd50b5 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs @@ -43,6 +43,7 @@ namespace Umbraco.Web.PublishedCache.NuCache private readonly IMediaRepository _mediaRepository; private readonly IMemberRepository _memberRepository; private readonly IGlobalSettings _globalSettings; + private readonly ISiteDomainHelper _siteDomainHelper; // volatile because we read it with no lock private volatile bool _isReady; @@ -81,7 +82,8 @@ namespace Umbraco.Web.PublishedCache.NuCache public PublishedSnapshotService(Options options, MainDom mainDom, IRuntimeState runtime, ServiceContext serviceContext, IPublishedContentTypeFactory publishedContentTypeFactory, IdkMap idkMap, IPublishedSnapshotAccessor publishedSnapshotAccessor, ILogger logger, IScopeProvider scopeProvider, - IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IGlobalSettings globalSettings) + IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, + IGlobalSettings globalSettings, ISiteDomainHelper siteDomainHelper) : base(publishedSnapshotAccessor) { //if (Interlocked.Increment(ref _singletonCheck) > 1) @@ -96,6 +98,7 @@ namespace Umbraco.Web.PublishedCache.NuCache _mediaRepository = mediaRepository; _memberRepository = memberRepository; _globalSettings = globalSettings; + _siteDomainHelper = siteDomainHelper; // we always want to handle repository events, configured or not // assuming no repository event will trigger before the whole db is ready @@ -484,7 +487,7 @@ namespace Umbraco.Web.PublishedCache.NuCache var domains = _serviceContext.DomainService.GetAll(true); foreach (var domain in domains .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))) + .Select(x => new Domain(x.Id, x.DomainName, x.RootContentId.Value, CultureInfo.GetCultureInfo(x.LanguageIsoCode), x.IsWildcard, x.IsDefaultDomain(_serviceContext.LocalizationService)))) { _domainStore.Set(domain.Id, domain); } @@ -828,7 +831,7 @@ namespace Umbraco.Web.PublishedCache.NuCache if (domain.RootContentId.HasValue == false) continue; // anomaly if (domain.LanguageIsoCode.IsNullOrWhiteSpace()) continue; // anomaly var culture = CultureInfo.GetCultureInfo(domain.LanguageIsoCode); - _domainStore.Set(domain.Id, new Domain(domain.Id, domain.DomainName, domain.RootContentId.Value, culture, domain.IsWildcard)); + _domainStore.Set(domain.Id, new Domain(domain.Id, domain.DomainName, domain.RootContentId.Value, culture, domain.IsWildcard, domain.IsDefaultDomain(_serviceContext.LocalizationService))); break; } } @@ -1012,10 +1015,11 @@ namespace Umbraco.Web.PublishedCache.NuCache var memberTypeCache = new PublishedContentTypeCache(null, null, _serviceContext.MemberTypeService, _publishedContentTypeFactory, _logger); var domainCache = new DomainCache(domainSnap); + var domainHelper = new DomainHelper(domainCache, _siteDomainHelper); return new PublishedShapshot.PublishedSnapshotElements { - ContentCache = new ContentCache(previewDefault, contentSnap, snapshotCache, elementsCache, new DomainHelper(domainCache), _globalSettings, _serviceContext.LocalizationService), + ContentCache = new ContentCache(previewDefault, contentSnap, snapshotCache, elementsCache, domainHelper, _globalSettings, _serviceContext.LocalizationService), MediaCache = new MediaCache(previewDefault, mediaSnap, snapshotCache, elementsCache), MemberCache = new MemberCache(previewDefault, snapshotCache, _serviceContext.MemberService, _serviceContext.DataTypeService, _serviceContext.LocalizationService, memberTypeCache, PublishedSnapshotAccessor), DomainCache = domainCache, diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DomainCache.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DomainCache.cs index 83651a9986..051c333762 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DomainCache.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/DomainCache.cs @@ -4,30 +4,33 @@ using System.Linq; using Umbraco.Web.Routing; using Umbraco.Core; using Umbraco.Core.Services; +using Umbraco.Core.Models; namespace Umbraco.Web.PublishedCache.XmlPublishedCache { - class DomainCache : IDomainCache + internal class DomainCache : IDomainCache { private readonly IDomainService _domainService; + private readonly ILocalizationService _localizationService; - public DomainCache(IDomainService domainService) + public DomainCache(IDomainService domainService, ILocalizationService localizationService) { _domainService = domainService; + _localizationService = localizationService; } public IEnumerable GetAll(bool includeWildcards) { return _domainService.GetAll(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)); + .Select(x => new Domain(x.Id, x.DomainName, x.RootContentId.Value, CultureInfo.GetCultureInfo(x.LanguageIsoCode), x.IsWildcard, x.IsDefaultDomain(_localizationService))); } public IEnumerable GetAssigned(int contentId, bool includeWildcards) { return _domainService.GetAssignedDomains(contentId, 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)); + .Select(x => new Domain(x.Id, x.DomainName, x.RootContentId.Value, CultureInfo.GetCultureInfo(x.LanguageIsoCode), x.IsWildcard, x.IsDefaultDomain(_localizationService))); } } } diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedContentCache.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedContentCache.cs index 010a220cb2..01ab37554e 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedContentCache.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedContentCache.cs @@ -31,7 +31,8 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache XmlStore xmlStore, // an XmlStore containing the master xml IDomainCache domainCache, // an IDomainCache implementation ICacheProvider cacheProvider, // an ICacheProvider that should be at request-level - IGlobalSettings globalSettings, + IGlobalSettings globalSettings, + ISiteDomainHelper siteDomainHelper, PublishedContentTypeCache contentTypeCache, // a PublishedContentType cache RoutesCache routesCache, // a RoutesCache string previewToken) // a preview token string (or null if not previewing) @@ -42,7 +43,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache _routesCache = routesCache; // may be null for unit-testing _contentTypeCache = contentTypeCache; _domainCache = domainCache; - _domainHelper = new DomainHelper(_domainCache); + _domainHelper = new DomainHelper(_domainCache, siteDomainHelper); _xmlStore = xmlStore; _xml = _xmlStore.Xml; // capture - because the cache has to remain consistent @@ -63,7 +64,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache #region Routes - public virtual IPublishedContent GetByRoute(bool preview, string route, bool? hideTopLevelNode = null) + public virtual IPublishedContent GetByRoute(bool preview, string route, bool? hideTopLevelNode = null, CultureInfo culture = null) { if (route == null) throw new ArgumentNullException(nameof(route)); @@ -107,12 +108,12 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache _routesCache.Store(content.Id, route, true); // trusted route } - public IPublishedContent GetByRoute(string route, bool? hideTopLevelNode = null) + public IPublishedContent GetByRoute(string route, bool? hideTopLevelNode = null, CultureInfo culture = null) { return GetByRoute(PreviewDefault, route, hideTopLevelNode); } - public virtual string GetRouteById(bool preview, int contentId, string language = null) + public virtual string GetRouteById(bool preview, int contentId, CultureInfo culture = null) { // try to get from cache if not previewing var route = preview || _routesCache == null ? null : _routesCache.GetRoute(contentId); @@ -137,9 +138,9 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache return route; } - public string GetRouteById(int contentId, string language = null) + public string GetRouteById(int contentId, CultureInfo culture = null) { - return GetRouteById(PreviewDefault, contentId, language); + return GetRouteById(PreviewDefault, contentId, culture); } IPublishedContent DetermineIdByRoute(bool preview, string route, bool hideTopLevelNode) diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedSnapshotService.cs index fedff54c29..7cde462dbc 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedSnapshotService.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedSnapshotService.cs @@ -13,6 +13,7 @@ using Umbraco.Core.Scoping; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Web.Cache; +using Umbraco.Web.Routing; namespace Umbraco.Web.PublishedCache.XmlPublishedCache { @@ -31,6 +32,8 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache private readonly IUserService _userService; private readonly ICacheProvider _requestCache; private readonly IGlobalSettings _globalSettings; + private readonly ILocalizationService _localizationService; + private readonly ISiteDomainHelper _siteDomainHelper; #region Constructors @@ -44,11 +47,12 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, ILogger logger, IGlobalSettings globalSettings, + ISiteDomainHelper siteDomainHelper, MainDom mainDom, bool testing = false, bool enableRepositoryEvents = true) : this(serviceContext, publishedContentTypeFactory, scopeProvider, requestCache, segmentProviders, publishedSnapshotAccessor, documentRepository, mediaRepository, memberRepository, - logger, globalSettings, null, mainDom, testing, enableRepositoryEvents) + logger, globalSettings, siteDomainHelper, null, mainDom, testing, enableRepositoryEvents) { } // used in some tests @@ -60,12 +64,13 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, ILogger logger, IGlobalSettings globalSettings, + ISiteDomainHelper siteDomainHelper, PublishedContentTypeCache contentTypeCache, MainDom mainDom, bool testing, bool enableRepositoryEvents) : this(serviceContext, publishedContentTypeFactory, scopeProvider, requestCache, Enumerable.Empty(), publishedSnapshotAccessor, documentRepository, mediaRepository, memberRepository, - logger, globalSettings, contentTypeCache, mainDom, testing, enableRepositoryEvents) + logger, globalSettings, siteDomainHelper, contentTypeCache, mainDom, testing, enableRepositoryEvents) { } private PublishedSnapshotService(ServiceContext serviceContext, @@ -77,6 +82,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, ILogger logger, IGlobalSettings globalSettings, + ISiteDomainHelper siteDomainHelper, PublishedContentTypeCache contentTypeCache, MainDom mainDom, bool testing, bool enableRepositoryEvents) @@ -95,9 +101,11 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache _memberService = serviceContext.MemberService; _mediaService = serviceContext.MediaService; _userService = serviceContext.UserService; + _localizationService = serviceContext.LocalizationService; _requestCache = requestCache; _globalSettings = globalSettings; + _siteDomainHelper = siteDomainHelper; } public override void Dispose() @@ -138,10 +146,10 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache // the current caches, but that would mean creating an extra cache (StaticCache // probably) so better use RequestCache. - var domainCache = new DomainCache(_domainService); + var domainCache = new DomainCache(_domainService, _localizationService); return new PublishedShapshot( - new PublishedContentCache(_xmlStore, domainCache, _requestCache, _globalSettings, _contentTypeCache, _routesCache, previewToken), + new PublishedContentCache(_xmlStore, domainCache, _requestCache, _globalSettings, _siteDomainHelper, _contentTypeCache, _routesCache, previewToken), new PublishedMediaCache(_xmlStore, _mediaService, _userService, _requestCache, _contentTypeCache), new PublishedMemberCache(_xmlStore, _requestCache, _memberService, _contentTypeCache), domainCache); diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs index 00bb705c1d..37f29cc1d6 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs @@ -10,6 +10,7 @@ using LightInject; using Umbraco.Core.Configuration; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence.Repositories; +using Umbraco.Web.Routing; namespace Umbraco.Web.PublishedCache.XmlPublishedCache { @@ -33,6 +34,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), + factory.GetInstance(), factory.GetInstance())); // add the Xml cache health check (hidden from type finder) diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index 7bdd196f20..e68365416d 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -272,8 +272,8 @@ namespace Umbraco.Web { //TODO: we should pass in the IExamineManager? - var s = searchProvider ?? Examine.ExamineManager.Instance.GetSearcher(Constants.Examine.ExternalIndexer); - + var s = searchProvider ?? Examine.ExamineManager.Instance.GetSearcher(Constants.Examine.ExternalIndexer); + var results = s.Search(criteria); return results.ToPublishedSearchResults(UmbracoContext.Current.ContentCache); } @@ -1066,7 +1066,7 @@ namespace Umbraco.Web /// The first child of content, of the given content type. public static IPublishedContent FirstChild(this IPublishedContent content, string alias) { - return content.Children( alias ).FirstOrDefault(); + return content.Children(alias).FirstOrDefault(); } public static IPublishedContent FirstChild(this IPublishedContent content, Func predicate) @@ -1116,12 +1116,12 @@ namespace Umbraco.Web return new DataTable(); //no children found //use new utility class to create table so that we don't have to maintain code in many places, just one - var dt = Core.DataTableExtensions.GenerateDataTable( - //pass in the alias of the first child node since this is the node type we're rendering headers for - firstNode.DocumentTypeAlias, - //pass in the callback to extract the Dictionary of all defined aliases to their names - alias => GetPropertyAliasesAndNames(services, alias), - //pass in a callback to populate the datatable, yup its a bit ugly but it's already legacy and we just want to maintain code in one place. + var dt = Core.DataTableExtensions.GenerateDataTable( + //pass in the alias of the first child node since this is the node type we're rendering headers for + firstNode.DocumentTypeAlias, + //pass in the callback to extract the Dictionary of all defined aliases to their names + alias => GetPropertyAliasesAndNames(services, alias), + //pass in a callback to populate the datatable, yup its a bit ugly but it's already legacy and we just want to maintain code in one place. () => { //create all row data @@ -1222,28 +1222,51 @@ namespace Umbraco.Web private static Dictionary GetAliasesAndNames(IContentTypeBase contentType) { return contentType.PropertyTypes.ToDictionary(x => x.Alias, x => x.Name); - } - + } + #endregion - + #region Culture - + + //TODO: Not used + ///// + ///// Gets the culture that would be selected to render a specified content, + ///// within the context of a specified current request. + ///// + ///// The content. + ///// The request Uri. + ///// The culture that would be selected to render the content. + //public static CultureInfo GetCulture(this IPublishedContent content, Uri current = null) + //{ + // return Models.ContentExtensions.GetCulture(UmbracoContext.Current, + // Current.Services.DomainService, + // Current.Services.LocalizationService, + // Current.Services.ContentService, + // content.Id, content.Path, + // current); + //} + /// - /// Gets the culture that would be selected to render a specified content, - /// within the context of a specified current request. + /// Return the URL name for the based on the culture specified or default culture defined /// - /// The content. - /// The request Uri. - /// The culture that would be selected to render the content. - public static CultureInfo GetCulture(this IPublishedContent content, Uri current = null) - { - return Models.ContentExtensions.GetCulture(UmbracoContext.Current, - Current.Services.DomainService, - Current.Services.LocalizationService, - Current.Services.ContentService, - content.Id, content.Path, - current); - } + /// + /// + /// + /// + public static string GetUrlName(this IPublishedContent content, ILocalizationService localizationService, CultureInfo culture = null) + { + if (content.ContentType.Variations.HasFlag(ContentVariation.CultureNeutral)) + { + var cultureCode = culture != null ? culture.Name : localizationService.GetDefaultVariantLanguage()?.IsoCode; + if (cultureCode != null && content.CultureNames.TryGetValue(cultureCode, out var cultureName)) + { + return cultureName.UrlName; + } + } + + //if we get here, the content type is invariant or we don't have access to a usable culture code + return content.UrlName; + } #endregion } diff --git a/src/Umbraco.Web/Routing/AliasUrlProvider.cs b/src/Umbraco.Web/Routing/AliasUrlProvider.cs index 7113ac498c..7c926f04f3 100644 --- a/src/Umbraco.Web/Routing/AliasUrlProvider.cs +++ b/src/Umbraco.Web/Routing/AliasUrlProvider.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Umbraco.Core; using Umbraco.Core.Configuration; @@ -18,12 +19,14 @@ namespace Umbraco.Web.Routing private readonly IGlobalSettings _globalSettings; private readonly IRequestHandlerSection _requestConfig; private readonly ILocalizationService _localizationService; + private readonly ISiteDomainHelper _siteDomainHelper; - public AliasUrlProvider(IGlobalSettings globalSettings, IRequestHandlerSection requestConfig, ILocalizationService localizationService) + public AliasUrlProvider(IGlobalSettings globalSettings, IRequestHandlerSection requestConfig, ILocalizationService localizationService, ISiteDomainHelper siteDomainHelper) { _globalSettings = globalSettings; _requestConfig = requestConfig; _localizationService = localizationService; + _siteDomainHelper = siteDomainHelper; } // note - at the moment we seem to accept pretty much anything as an alias @@ -45,7 +48,7 @@ namespace Umbraco.Web.Routing /// absolute is true, in which case the url is always absolute. /// If the provider is unable to provide a url, it should return null. /// - public string GetUrl(UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode, string language = null) + public string GetUrl(UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode, CultureInfo culture = null) { return null; // we have nothing to say } @@ -77,7 +80,7 @@ namespace Umbraco.Web.Routing if (!node.HasProperty(Constants.Conventions.Content.UrlAlias)) return Enumerable.Empty(); - var domainHelper = new DomainHelper(umbracoContext.PublishedShapshot.Domains); + var domainHelper = umbracoContext.GetDomainHelper(_siteDomainHelper); var n = node; var domainUris = domainHelper.DomainsForNode(n.Id, current, false); diff --git a/src/Umbraco.Web/Routing/ContentFinderByIdPath.cs b/src/Umbraco.Web/Routing/ContentFinderByIdPath.cs index eb3e481a7b..2052a198bf 100644 --- a/src/Umbraco.Web/Routing/ContentFinderByIdPath.cs +++ b/src/Umbraco.Web/Routing/ContentFinderByIdPath.cs @@ -16,16 +16,11 @@ namespace Umbraco.Web.Routing { private readonly ILogger _logger; private readonly IWebRoutingSection _webRoutingSection; - - public ContentFinderByIdPath(ILogger logger) - : this(UmbracoConfig.For.UmbracoSettings().WebRouting) + + public ContentFinderByIdPath(IWebRoutingSection webRoutingSection, ILogger logger) { - _logger = logger; - } - - public ContentFinderByIdPath(IWebRoutingSection webRoutingSection) - { - _webRoutingSection = webRoutingSection; + _webRoutingSection = webRoutingSection ?? throw new System.ArgumentNullException(nameof(webRoutingSection)); + _logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); } /// diff --git a/src/Umbraco.Web/Routing/ContentFinderByLegacy404.cs b/src/Umbraco.Web/Routing/ContentFinderByLegacy404.cs index a687d43dbe..090b7d421d 100644 --- a/src/Umbraco.Web/Routing/ContentFinderByLegacy404.cs +++ b/src/Umbraco.Web/Routing/ContentFinderByLegacy404.cs @@ -48,7 +48,7 @@ namespace Umbraco.Web.Routing while (pos > 1) { route = route.Substring(0, pos); - node = frequest.UmbracoContext.ContentCache.GetByRoute(route); + node = frequest.UmbracoContext.ContentCache.GetByRoute(route, culture: frequest.Culture); if (node != null) break; pos = route.LastIndexOf('/'); } diff --git a/src/Umbraco.Web/Routing/ContentFinderByNiceUrl.cs b/src/Umbraco.Web/Routing/ContentFinderByUrl.cs similarity index 82% rename from src/Umbraco.Web/Routing/ContentFinderByNiceUrl.cs rename to src/Umbraco.Web/Routing/ContentFinderByUrl.cs index 094c0addaf..66b8024c6b 100644 --- a/src/Umbraco.Web/Routing/ContentFinderByNiceUrl.cs +++ b/src/Umbraco.Web/Routing/ContentFinderByUrl.cs @@ -1,63 +1,63 @@ -using Umbraco.Core.Logging; -using Umbraco.Core; -using Umbraco.Core.Models.PublishedContent; - -namespace Umbraco.Web.Routing -{ - /// - /// Provides an implementation of that handles page nice urls. - /// - /// - /// Handles /foo/bar where /foo/bar is the nice url of a document. - /// - public class ContentFinderByNiceUrl : IContentFinder - { - protected ILogger Logger { get; } - - public ContentFinderByNiceUrl(ILogger logger) - { - Logger = logger; - } - - /// - /// Tries to find and assign an Umbraco document to a PublishedContentRequest. - /// - /// The PublishedContentRequest. - /// A value indicating whether an Umbraco document was found and assigned. - public virtual bool TryFindContent(PublishedRequest frequest) - { - string route; - if (frequest.HasDomain) - route = frequest.Domain.ContentId + DomainHelper.PathRelativeToDomain(frequest.Domain.Uri, frequest.Uri.GetAbsolutePathDecoded()); - else - route = frequest.Uri.GetAbsolutePathDecoded(); - - var node = FindContent(frequest, route); - return node != null; - } - - /// - /// Tries to find an Umbraco document for a PublishedContentRequest and a route. - /// - /// The document request. - /// The route. - /// The document node, or null. - protected IPublishedContent FindContent(PublishedRequest docreq, string route) - { - Logger.Debug(() => $"Test route \"{route}\""); - - var node = docreq.UmbracoContext.ContentCache.GetByRoute(route); - if (node != null) - { - docreq.PublishedContent = node; - Logger.Debug(() => $"Got content, id={node.Id}"); - } - else - { - Logger.Debug("No match."); - } - - return node; - } - } -} +using Umbraco.Core.Logging; +using Umbraco.Core; +using Umbraco.Core.Models.PublishedContent; + +namespace Umbraco.Web.Routing +{ + /// + /// Provides an implementation of that handles page nice urls. + /// + /// + /// Handles /foo/bar where /foo/bar is the nice url of a document. + /// + public class ContentFinderByUrl : IContentFinder + { + protected ILogger Logger { get; } + + public ContentFinderByUrl(ILogger logger) + { + Logger = logger; + } + + /// + /// Tries to find and assign an Umbraco document to a PublishedContentRequest. + /// + /// The PublishedContentRequest. + /// A value indicating whether an Umbraco document was found and assigned. + public virtual bool TryFindContent(PublishedRequest frequest) + { + string route; + if (frequest.HasDomain) + route = frequest.Domain.ContentId + DomainHelper.PathRelativeToDomain(frequest.Domain.Uri, frequest.Uri.GetAbsolutePathDecoded()); + else + route = frequest.Uri.GetAbsolutePathDecoded(); + + var node = FindContent(frequest, route); + return node != null; + } + + /// + /// Tries to find an Umbraco document for a PublishedContentRequest and a route. + /// + /// The document request. + /// The route. + /// The document node, or null. + protected IPublishedContent FindContent(PublishedRequest docreq, string route) + { + Logger.Debug(() => $"Test route \"{route}\""); + + var node = docreq.UmbracoContext.ContentCache.GetByRoute(route, culture: docreq.Culture); + if (node != null) + { + docreq.PublishedContent = node; + Logger.Debug(() => $"Got content, id={node.Id}"); + } + else + { + Logger.Debug("No match."); + } + + return node; + } + } +} diff --git a/src/Umbraco.Web/Routing/ContentFinderByNiceUrlAndTemplate.cs b/src/Umbraco.Web/Routing/ContentFinderByUrlAndTemplate.cs similarity index 76% rename from src/Umbraco.Web/Routing/ContentFinderByNiceUrlAndTemplate.cs rename to src/Umbraco.Web/Routing/ContentFinderByUrlAndTemplate.cs index d0eaa55b79..8f507078b3 100644 --- a/src/Umbraco.Web/Routing/ContentFinderByNiceUrlAndTemplate.cs +++ b/src/Umbraco.Web/Routing/ContentFinderByUrlAndTemplate.cs @@ -1,67 +1,72 @@ -using Umbraco.Core.Logging; -using Umbraco.Core.Models; -using Umbraco.Core; -using Umbraco.Core.Configuration; -using Umbraco.Core.Models.PublishedContent; -using Umbraco.Web.Composing; - -namespace Umbraco.Web.Routing -{ - /// - /// Provides an implementation of that handles page nice urls and a template. - /// - /// - /// Handles /foo/bar/template where /foo/bar is the nice url of a document, and template a template alias. - /// If successful, then the template of the document request is also assigned. - /// - public class ContentFinderByNiceUrlAndTemplate : ContentFinderByNiceUrl - { - public ContentFinderByNiceUrlAndTemplate(ILogger logger) - : base(logger) - { } - - /// - /// Tries to find and assign an Umbraco document to a PublishedContentRequest. - /// - /// The PublishedContentRequest. - /// A value indicating whether an Umbraco document was found and assigned. - /// If successful, also assigns the template. - public override bool TryFindContent(PublishedRequest frequest) - { - IPublishedContent node = null; - var path = frequest.Uri.GetAbsolutePathDecoded(); - - if (frequest.HasDomain) - path = DomainHelper.PathRelativeToDomain(frequest.Domain.Uri, path); - - if (path != "/") // no template if "/" - { - var pos = path.LastIndexOf('/'); - var templateAlias = path.Substring(pos + 1); - path = pos == 0 ? "/" : path.Substring(0, pos); - - var template = Current.Services.FileService.GetTemplate(templateAlias); - if (template != null) - { - Logger.Debug(() => $"Valid template: \"{templateAlias}\""); - - var route = frequest.HasDomain ? (frequest.Domain.ContentId.ToString() + path) : path; - node = FindContent(frequest, route); - - if (UmbracoConfig.For.UmbracoSettings().WebRouting.DisableAlternativeTemplates == false && node != null) - frequest.TemplateModel = template; - } - else - { - Logger.Debug(() => $"Not a valid template: \"{templateAlias}\""); - } - } - else - { - Logger.Debug("No template in path \"/\""); - } - - return node != null; - } - } -} +using Umbraco.Core.Logging; +using Umbraco.Core.Models; +using Umbraco.Core; +using Umbraco.Core.Configuration; +using Umbraco.Core.Models.PublishedContent; +using Umbraco.Web.Composing; +using Umbraco.Core.Services; + +namespace Umbraco.Web.Routing +{ + /// + /// Provides an implementation of that handles page nice urls and a template. + /// + /// + /// Handles /foo/bar/template where /foo/bar is the nice url of a document, and template a template alias. + /// If successful, then the template of the document request is also assigned. + /// + public class ContentFinderByUrlAndTemplate : ContentFinderByUrl + { + private readonly IFileService _fileService; + + public ContentFinderByUrlAndTemplate(ILogger logger, IFileService fileService) + : base(logger) + { + _fileService = fileService; + } + + /// + /// Tries to find and assign an Umbraco document to a PublishedContentRequest. + /// + /// The PublishedContentRequest. + /// A value indicating whether an Umbraco document was found and assigned. + /// If successful, also assigns the template. + public override bool TryFindContent(PublishedRequest frequest) + { + IPublishedContent node = null; + var path = frequest.Uri.GetAbsolutePathDecoded(); + + if (frequest.HasDomain) + path = DomainHelper.PathRelativeToDomain(frequest.Domain.Uri, path); + + if (path != "/") // no template if "/" + { + var pos = path.LastIndexOf('/'); + var templateAlias = path.Substring(pos + 1); + path = pos == 0 ? "/" : path.Substring(0, pos); + + var template = _fileService.GetTemplate(templateAlias); + if (template != null) + { + Logger.Debug(() => $"Valid template: \"{templateAlias}\""); + + var route = frequest.HasDomain ? (frequest.Domain.ContentId.ToString() + path) : path; + node = FindContent(frequest, route); + + if (UmbracoConfig.For.UmbracoSettings().WebRouting.DisableAlternativeTemplates == false && node != null) + frequest.TemplateModel = template; + } + else + { + Logger.Debug(() => $"Not a valid template: \"{templateAlias}\""); + } + } + else + { + Logger.Debug("No template in path \"/\""); + } + + return node != null; + } + } +} diff --git a/src/Umbraco.Web/Routing/CustomRouteUrlProvider.cs b/src/Umbraco.Web/Routing/CustomRouteUrlProvider.cs index ea7983d77c..7a3d8fffed 100644 --- a/src/Umbraco.Web/Routing/CustomRouteUrlProvider.cs +++ b/src/Umbraco.Web/Routing/CustomRouteUrlProvider.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; namespace Umbraco.Web.Routing { @@ -18,7 +19,7 @@ namespace Umbraco.Web.Routing /// /// /// - public string GetUrl(UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode, string language = null) + public string GetUrl(UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode, CultureInfo culture = null) { if (umbracoContext == null) return null; if (umbracoContext.PublishedRequest == null) return null; diff --git a/src/Umbraco.Web/Routing/DefaultUrlProvider.cs b/src/Umbraco.Web/Routing/DefaultUrlProvider.cs index 13b75ee623..d2f0c2662b 100644 --- a/src/Umbraco.Web/Routing/DefaultUrlProvider.cs +++ b/src/Umbraco.Web/Routing/DefaultUrlProvider.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; @@ -14,13 +15,15 @@ namespace Umbraco.Web.Routing { private readonly IRequestHandlerSection _requestSettings; private readonly ILogger _logger; - private readonly IGlobalSettings _globalSettings; - - public DefaultUrlProvider(IRequestHandlerSection requestSettings, ILogger logger, IGlobalSettings globalSettings) + private readonly IGlobalSettings _globalSettings; + private readonly ISiteDomainHelper _siteDomainHelper; + + public DefaultUrlProvider(IRequestHandlerSection requestSettings, ILogger logger, IGlobalSettings globalSettings, ISiteDomainHelper siteDomainHelper) { _requestSettings = requestSettings; _logger = logger; - _globalSettings = globalSettings; + _globalSettings = globalSettings; + _siteDomainHelper = siteDomainHelper; } #region GetUrl @@ -37,13 +40,13 @@ namespace Umbraco.Web.Routing /// The url is absolute or relative depending on mode and on current. /// If the provider is unable to provide a url, it should return null. /// - public virtual string GetUrl(UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode, string language = null) + public virtual string GetUrl(UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode, CultureInfo culture = null) { if (!current.IsAbsoluteUri) throw new ArgumentException("Current url must be absolute.", "current"); // will not use cache if previewing - var route = umbracoContext.ContentCache.GetRouteById(id, language); + var route = umbracoContext.ContentCache.GetRouteById(id, culture); return GetUrlFromRoute(route, umbracoContext, id, current, mode); } @@ -57,7 +60,7 @@ namespace Umbraco.Web.Routing return null; } - var domainHelper = new DomainHelper(umbracoContext.PublishedShapshot.Domains); + var domainHelper = umbracoContext.GetDomainHelper(_siteDomainHelper); // extract domainUri and path // route is / or / @@ -98,7 +101,7 @@ namespace Umbraco.Web.Routing return null; } - var domainHelper = new DomainHelper(umbracoContext.PublishedShapshot.Domains); + var domainHelper = umbracoContext.GetDomainHelper(_siteDomainHelper); // extract domainUri and path // route is / or / diff --git a/src/Umbraco.Web/Routing/Domain.cs b/src/Umbraco.Web/Routing/Domain.cs index b9116c6b51..03048f0dd5 100644 --- a/src/Umbraco.Web/Routing/Domain.cs +++ b/src/Umbraco.Web/Routing/Domain.cs @@ -15,13 +15,14 @@ namespace Umbraco.Web.Routing /// The identifier of the content which supports the domain. /// The culture of the domain. /// A value indicating whether the domain is a wildcard domain. - public Domain(int id, string name, int contentId, CultureInfo culture, bool isWildcard) + public Domain(int id, string name, int contentId, CultureInfo culture, bool isWildcard, bool isDefault) { Id = id; Name = name; ContentId = contentId; Culture = culture; IsWildcard = isWildcard; + IsDefault = isDefault; } /// @@ -35,6 +36,7 @@ namespace Umbraco.Web.Routing ContentId = domain.ContentId; Culture = domain.Culture; IsWildcard = domain.IsWildcard; + IsDefault = domain.IsDefault; } /// @@ -61,5 +63,10 @@ namespace Umbraco.Web.Routing /// Gets a value indicating whether the domain is a wildcard domain. /// public bool IsWildcard { get; } + + /// + /// Gets a value indicating if this is the default domain for the website. + /// + public bool IsDefault { get; } } } diff --git a/src/Umbraco.Web/Routing/DomainHelper.cs b/src/Umbraco.Web/Routing/DomainHelper.cs index 79ccb9fbd4..d56473f530 100644 --- a/src/Umbraco.Web/Routing/DomainHelper.cs +++ b/src/Umbraco.Web/Routing/DomainHelper.cs @@ -12,11 +12,13 @@ namespace Umbraco.Web.Routing /// public class DomainHelper { - private readonly IDomainCache _domainCache; - - public DomainHelper(IDomainCache domainCache) + private readonly IDomainCache _domainCache; + private readonly ISiteDomainHelper _siteDomainHelper; + + public DomainHelper(IDomainCache domainCache, ISiteDomainHelper siteDomainHelper) { - _domainCache = domainCache; + _domainCache = domainCache; + _siteDomainHelper = siteDomainHelper; } #region Domain for Node @@ -43,8 +45,7 @@ namespace Umbraco.Web.Routing return null; // else filter - var helper = Current.SiteDomainHelper; - var domainAndUri = DomainForUri(domains, current, domainAndUris => helper.MapDomain(current, domainAndUris)); + var domainAndUri = DomainForUri(domains, current, domainAndUris => _siteDomainHelper.MapDomain(current, domainAndUris)); if (domainAndUri == null) throw new Exception("DomainForUri returned null."); @@ -88,8 +89,7 @@ namespace Umbraco.Web.Routing var domainAndUris = DomainsForUri(domains, current).ToArray(); // filter - var helper = Current.SiteDomainHelper; - return helper.MapDomains(current, domainAndUris, excludeDefault).ToArray(); + return _siteDomainHelper.MapDomains(current, domainAndUris, excludeDefault).ToArray(); } #endregion @@ -125,9 +125,10 @@ namespace Umbraco.Web.Routing DomainAndUri domainAndUri; if (current == null) - { - // take the first one by default (what else can we do?) - domainAndUri = domainsAndUris.First(); // .First() protected by .Any() above + { + //get the default domain (there should be one) + domainAndUri = domainsAndUris.FirstOrDefault(x => x.IsDefault); + if (domainAndUri == null) domainsAndUris.First(); // take the first one by default (what else can we do?) } else { diff --git a/src/Umbraco.Web/Routing/IUrlProvider.cs b/src/Umbraco.Web/Routing/IUrlProvider.cs index 3f6ee4dcc0..086f9c4767 100644 --- a/src/Umbraco.Web/Routing/IUrlProvider.cs +++ b/src/Umbraco.Web/Routing/IUrlProvider.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using Umbraco.Web.PublishedCache; namespace Umbraco.Web.Routing @@ -21,7 +22,7 @@ namespace Umbraco.Web.Routing /// The url is absolute or relative depending on mode and on current. /// If the provider is unable to provide a url, it should return null. /// - string GetUrl(UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode, string language = null); + string GetUrl(UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode, CultureInfo culture = null); /// /// Gets the other urls of a published content. diff --git a/src/Umbraco.Web/Routing/SiteDomainHelper.cs b/src/Umbraco.Web/Routing/SiteDomainHelper.cs index 1ceab6293a..deaa84b0e1 100644 --- a/src/Umbraco.Web/Routing/SiteDomainHelper.cs +++ b/src/Umbraco.Web/Routing/SiteDomainHelper.cs @@ -302,8 +302,13 @@ namespace Umbraco.Web.Routing throw new ArgumentException("Cannot be empty.", "domainAndUris"); // we do our best, but can't do the impossible - if (qualifiedSites == null) - return domainAndUris.First(); + if (qualifiedSites == null) + { + //fixme take the default + var defaultDomain = domainAndUris.FirstOrDefault(x => x.IsDefault); + if (defaultDomain == null) defaultDomain = domainAndUris.First(); //this shouldn't occur but just in case + return defaultDomain; + } // find a site that contains the current authority var currentSite = qualifiedSites.FirstOrDefault(site => site.Value.Contains(currentAuthority)); diff --git a/src/Umbraco.Web/Routing/UrlProvider.cs b/src/Umbraco.Web/Routing/UrlProvider.cs index 3375ac1be2..58f1689cb0 100644 --- a/src/Umbraco.Web/Routing/UrlProvider.cs +++ b/src/Umbraco.Web/Routing/UrlProvider.cs @@ -7,7 +7,8 @@ using Umbraco.Web.PublishedCache; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Web.Composing; - +using Umbraco.Core.Services; + namespace Umbraco.Web.Routing { /// @@ -23,13 +24,13 @@ namespace Umbraco.Web.Routing /// The Umbraco context. /// /// The list of url providers. - public UrlProvider(UmbracoContext umbracoContext, IWebRoutingSection routingSettings, IEnumerable urlProviders) + public UrlProvider(UmbracoContext umbracoContext, IWebRoutingSection routingSettings, IEnumerable urlProviders, IEntityService entityService) { if (routingSettings == null) throw new ArgumentNullException(nameof(routingSettings)); _umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext)); - _urlProviders = urlProviders; - + _urlProviders = urlProviders; + _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); var provider = UrlProviderMode.Auto; Mode = provider; @@ -54,8 +55,9 @@ namespace Umbraco.Web.Routing } private readonly UmbracoContext _umbracoContext; - private readonly IEnumerable _urlProviders; - + private readonly IEnumerable _urlProviders; + private readonly IEntityService _entityService; + /// /// Gets or sets the provider url mode. /// @@ -76,7 +78,7 @@ namespace Umbraco.Web.Routing /// public string GetUrl(Guid id) { - var intId = Current.Services.EntityService.GetId(id, UmbracoObjectTypes.Document); + var intId = _entityService.GetId(id, UmbracoObjectTypes.Document); return GetUrl(intId.Success ? intId.Result : -1); } @@ -93,7 +95,7 @@ namespace Umbraco.Web.Routing /// public string GetUrl(Guid id, bool absolute) { - var intId = Current.Services.EntityService.GetId(id, UmbracoObjectTypes.Document); + var intId = _entityService.GetId(id, UmbracoObjectTypes.Document); return GetUrl(intId.Success ? intId.Result : -1, absolute); } @@ -111,7 +113,7 @@ namespace Umbraco.Web.Routing /// public string GetUrl(Guid id, Uri current, bool absolute) { - var intId = Current.Services.EntityService.GetId(id, UmbracoObjectTypes.Document); + var intId = _entityService.GetId(id, UmbracoObjectTypes.Document); return GetUrl(intId.Success ? intId.Result : -1, current, absolute); } @@ -127,7 +129,7 @@ namespace Umbraco.Web.Routing /// public string GetUrl(Guid id, UrlProviderMode mode) { - var intId = Current.Services.EntityService.GetId(id, UmbracoObjectTypes.Document); + var intId = _entityService.GetId(id, UmbracoObjectTypes.Document); return GetUrl(intId.Success ? intId.Result : -1, mode); } diff --git a/src/Umbraco.Web/Routing/UrlProviderExtensions.cs b/src/Umbraco.Web/Routing/UrlProviderExtensions.cs index 1d9a4a4236..a71bb51ddc 100644 --- a/src/Umbraco.Web/Routing/UrlProviderExtensions.cs +++ b/src/Umbraco.Web/Routing/UrlProviderExtensions.cs @@ -11,11 +11,6 @@ namespace Umbraco.Web.Routing { internal static class UrlProviderExtensions { - // fixme inject - private static ILocalizedTextService TextService => Current.Services.TextService; - private static IContentService ContentService => Current.Services.ContentService; - private static ILogger Logger => Current.Logger; - /// /// Gets the URLs for the content item /// @@ -26,28 +21,30 @@ namespace Umbraco.Web.Routing /// Use this when displaying URLs, if there are errors genertaing the urls the urls themselves will /// contain the errors. /// - public static IEnumerable GetContentUrls(this IContent content, UmbracoContext umbracoContext) + public static IEnumerable GetContentUrls(this IContent content, UrlProvider urlProvider, ILocalizedTextService textService, IContentService contentService, ILogger logger) { - if (content == null) throw new ArgumentNullException(nameof(content)); - if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); - + if (content == null) throw new ArgumentNullException(nameof(content)); + if (urlProvider == null) throw new ArgumentNullException(nameof(urlProvider)); + if (textService == null) throw new ArgumentNullException(nameof(textService)); + if (contentService == null) throw new ArgumentNullException(nameof(contentService)); + if (logger == null) throw new ArgumentNullException(nameof(logger)); + var urls = new List(); if (content.Published == false) { - urls.Add(TextService.Localize("content/itemNotPublished")); + urls.Add(textService.Localize("content/itemNotPublished")); return urls; } string url; - var urlProvider = umbracoContext.UrlProvider; try { url = urlProvider.GetUrl(content.Id); } catch (Exception e) { - Logger.Error("GetUrl exception.", e); + logger.Error("GetUrl exception.", e); url = "#ex"; } if (url == "#") @@ -57,17 +54,17 @@ namespace Umbraco.Web.Routing var parent = content; do { - parent = parent.ParentId > 0 ? parent.Parent(ContentService) : null; + parent = parent.ParentId > 0 ? parent.Parent(contentService) : null; } while (parent != null && parent.Published); urls.Add(parent == null - ? TextService.Localize("content/parentNotPublishedAnomaly") // oops - internal error - : TextService.Localize("content/parentNotPublished", new[] { parent.Name })); + ? textService.Localize("content/parentNotPublishedAnomaly") // oops - internal error + : textService.Localize("content/parentNotPublished", new[] { parent.Name })); } else if (url == "#ex") { - urls.Add(TextService.Localize("content/getUrlException")); + urls.Add(textService.Localize("content/getUrlException")); } else { @@ -81,7 +78,7 @@ namespace Umbraco.Web.Routing if (pcr.HasPublishedContent == false) { - urls.Add(TextService.Localize("content/routeError", new[] { "(error)" })); + urls.Add(textService.Localize("content/routeError", new[] { "(error)" })); } else if (pcr.PublishedContent.Id != content.Id) { @@ -103,7 +100,7 @@ namespace Umbraco.Web.Routing s = "/" + string.Join("/", l) + " (id=" + pcr.PublishedContent.Id + ")"; } - urls.Add(TextService.Localize("content/routeError", s)); + urls.Add(textService.Localize("content/routeError", s)); } else { diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index d67bf50797..820d846d9f 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -169,9 +169,9 @@ namespace Umbraco.Web.Runtime // all built-in finders in the correct order, // devs can then modify this list on application startup .Append() - .Append() + .Append() .Append() - .Append() + .Append() .Append() .Append(); @@ -212,6 +212,7 @@ namespace Umbraco.Web.Runtime IUserService userService, IUmbracoSettingsSection umbracoSettings, IGlobalSettings globalSettings, + IEntityService entityService, UrlProviderCollection urlProviders) { // setup mvc and webapi services @@ -248,7 +249,8 @@ namespace Umbraco.Web.Runtime new WebSecurity(httpContext, userService, globalSettings), umbracoSettings, urlProviders, - globalSettings); + globalSettings, + entityService); // ensure WebAPI is initialized, after everything GlobalConfiguration.Configuration.EnsureInitialized(); diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 907eac0bde..67ce954045 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -394,6 +394,8 @@ + + @@ -1231,8 +1233,6 @@ - - diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs index cb7a29f608..ef684a21ba 100644 --- a/src/Umbraco.Web/UmbracoContext.cs +++ b/src/Umbraco.Web/UmbracoContext.cs @@ -4,6 +4,7 @@ using System.Web; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Services; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Runtime; @@ -17,7 +18,8 @@ namespace Umbraco.Web public class UmbracoContext : DisposableObject, IDisposeOnRequestEnd { private readonly IGlobalSettings _globalSettings; - private readonly Lazy _publishedSnapshot; + private readonly Lazy _publishedSnapshot; + private DomainHelper _domainHelper; private string _previewToken; private bool? _previewing; @@ -28,10 +30,10 @@ namespace Umbraco.Web /// /// /// An http context. - /// A published snapshot service. - /// A security helper. - /// The umbraco settings. - /// Some url providers. + /// A published snapshot service. + /// A security helper. + /// The umbraco settings. + /// Some url providers. /// /// A value indicating whether to replace the existing context. /// The "current" UmbracoContext. @@ -66,7 +68,8 @@ namespace Umbraco.Web WebSecurity webSecurity, IUmbracoSettingsSection umbracoSettings, IEnumerable urlProviders, - IGlobalSettings globalSettings, + IGlobalSettings globalSettings, + IEntityService entityService, bool replace = false) { if (umbracoContextAccessor == null) throw new ArgumentNullException(nameof(umbracoContextAccessor)); @@ -84,7 +87,7 @@ namespace Umbraco.Web // create & assign to accessor, dispose existing if any umbracoContextAccessor.UmbracoContext?.Dispose(); - return umbracoContextAccessor.UmbracoContext = new UmbracoContext(httpContext, publishedSnapshotService, webSecurity, umbracoSettings, urlProviders, globalSettings); + return umbracoContextAccessor.UmbracoContext = new UmbracoContext(httpContext, publishedSnapshotService, webSecurity, umbracoSettings, urlProviders, globalSettings, entityService); } // initializes a new instance of the UmbracoContext class @@ -96,7 +99,8 @@ namespace Umbraco.Web WebSecurity webSecurity, IUmbracoSettingsSection umbracoSettings, IEnumerable urlProviders, - IGlobalSettings globalSettings) + IGlobalSettings globalSettings, + IEntityService entityService) { if (httpContext == null) throw new ArgumentNullException(nameof(httpContext)); if (publishedSnapshotService == null) throw new ArgumentNullException(nameof(publishedSnapshotService)); @@ -132,7 +136,7 @@ namespace Umbraco.Web // OriginalRequestUrl = GetRequestFromContext()?.Url ?? new Uri("http://localhost"); CleanedUmbracoUrl = UriUtility.UriToUmbraco(OriginalRequestUrl); - UrlProvider = new UrlProvider(this, umbracoSettings.WebRouting, urlProviders); + UrlProvider = new UrlProvider(this, umbracoSettings.WebRouting, urlProviders, entityService); } #endregion @@ -207,7 +211,25 @@ namespace Umbraco.Web /// /// Exposes the HttpContext for the current request /// - public HttpContextBase HttpContext { get; } + public HttpContextBase HttpContext { 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) + { + if (_domainHelper == null) + _domainHelper = new DomainHelper(PublishedShapshot.Domains, siteDomainHelper); + return _domainHelper; + } /// /// Gets a value indicating whether the request has debugging enabled diff --git a/src/Umbraco.Web/UmbracoModule.cs b/src/Umbraco.Web/UmbracoModule.cs index 746c23a325..1578f5dc53 100644 --- a/src/Umbraco.Web/UmbracoModule.cs +++ b/src/Umbraco.Web/UmbracoModule.cs @@ -53,7 +53,10 @@ namespace Umbraco.Web public IPublishedSnapshotService PublishedSnapshotService { get; set; } [Inject] - public IUserService UserService { get; set; } + public IUserService UserService { get; set; } + + [Inject] + public IEntityService EntityService { get; set; } [Inject] public UrlProviderCollection UrlProviders { get; set; } @@ -111,7 +114,8 @@ namespace Umbraco.Web new WebSecurity(httpContext, UserService, GlobalSettings), UmbracoConfig.For.UmbracoSettings(), UrlProviders, - GlobalSettings, + GlobalSettings, + EntityService, true); }