Adds a couple of tests which yielded some other issues with getting urls by culture, those are now fixed
This commit is contained in:
@@ -11,6 +11,7 @@ using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.TestHelpers.Stubs;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
|
||||
@@ -99,7 +100,7 @@ namespace Umbraco.Tests.Published
|
||||
var element1 = new PublishedElement(elementType1, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "1234" } }, false);
|
||||
|
||||
var cntType1 = contentTypeFactory.CreateContentType(1001, "cnt1", Array.Empty<PublishedPropertyType>());
|
||||
var cnt1 = new PublishedSnapshotTestObjects.TestPublishedContent(cntType1, 1234, Guid.NewGuid(), new Dictionary<string, object>(), false);
|
||||
var cnt1 = new TestPublishedContent(cntType1, 1234, Guid.NewGuid(), new Dictionary<string, object>(), false);
|
||||
cacheContent[cnt1.Id] = cnt1;
|
||||
|
||||
Assert.AreSame(cnt1, element1.Value("prop1"));
|
||||
@@ -200,8 +201,8 @@ namespace Umbraco.Tests.Published
|
||||
|
||||
var element1 = new PublishedElement(elementType1, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "val1" } }, false);
|
||||
var element2 = new PublishedElement(elementType2, Guid.NewGuid(), new Dictionary<string, object> { { "prop2", "1003" } }, false);
|
||||
var cnt1 = new PublishedSnapshotTestObjects.TestPublishedContent(contentType1, 1003, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "val1" } }, false);
|
||||
var cnt2 = new PublishedSnapshotTestObjects.TestPublishedContent(contentType2, 1004, Guid.NewGuid(), new Dictionary<string, object> { { "prop2", "1003" } }, false);
|
||||
var cnt1 = new TestPublishedContent(contentType1, 1003, Guid.NewGuid(), new Dictionary<string, object> { { "prop1", "val1" } }, false);
|
||||
var cnt2 = new TestPublishedContent(contentType2, 1004, Guid.NewGuid(), new Dictionary<string, object> { { "prop2", "1003" } }, false);
|
||||
|
||||
cacheContent[cnt1.Id] = cnt1.CreateModel();
|
||||
cacheContent[cnt2.Id] = cnt2.CreateModel();
|
||||
|
||||
@@ -8,8 +8,6 @@ namespace Umbraco.Tests.Published
|
||||
{
|
||||
public class PublishedSnapshotTestObjects
|
||||
{
|
||||
#region Published models
|
||||
|
||||
[PublishedModel("element1")]
|
||||
public class TestElementModel1 : PublishedElementModel
|
||||
{
|
||||
@@ -49,66 +47,6 @@ namespace Umbraco.Tests.Published
|
||||
|
||||
public IEnumerable<TestContentModel1> Prop2 => this.Value<IEnumerable<TestContentModel1>>("prop2");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Support classes
|
||||
|
||||
internal class TestPublishedContent : PublishedElement, IPublishedContent
|
||||
{
|
||||
public TestPublishedContent(PublishedContentType contentType, int id, Guid key, Dictionary<string, object> values, bool previewing)
|
||||
: base(contentType, key, values, previewing)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
|
||||
public int Id { get; }
|
||||
public int TemplateId { get; set; }
|
||||
public int SortOrder { get; set; }
|
||||
public string Name { get; set; }
|
||||
public IReadOnlyDictionary<string, PublishedCultureName> CultureNames => throw new NotSupportedException();
|
||||
public string UrlName { get; set; }
|
||||
public string DocumentTypeAlias => ContentType.Alias;
|
||||
public int DocumentTypeId { get; set; }
|
||||
public string WriterName { get; set; }
|
||||
public string CreatorName { get; set; }
|
||||
public int WriterId { get; set; }
|
||||
public int CreatorId { get; set; }
|
||||
public string Path { get; set; }
|
||||
public DateTime CreateDate { get; set; }
|
||||
public DateTime UpdateDate { get; set; }
|
||||
public Guid Version { get; set; }
|
||||
public int Level { get; set; }
|
||||
public string Url { get; set; }
|
||||
public PublishedItemType ItemType => ContentType.ItemType;
|
||||
public bool IsDraft { get; set; }
|
||||
public IPublishedContent Parent { get; set; }
|
||||
public IEnumerable<IPublishedContent> Children { get; set; }
|
||||
|
||||
// copied from PublishedContentBase
|
||||
public IPublishedProperty GetProperty(string alias, bool recurse)
|
||||
{
|
||||
var property = GetProperty(alias);
|
||||
if (recurse == false) return property;
|
||||
|
||||
IPublishedContent content = this;
|
||||
var firstNonNullProperty = property;
|
||||
while (content != null && (property == null || property.HasValue() == false))
|
||||
{
|
||||
content = content.Parent;
|
||||
property = content?.GetProperty(alias);
|
||||
if (firstNonNullProperty == null && property != null) firstNonNullProperty = property;
|
||||
}
|
||||
|
||||
// if we find a content with the property with a value, return that property
|
||||
// if we find no content with the property, return null
|
||||
// if we find a content with the property without a value, return that property
|
||||
// have to save that first property while we look further up, hence firstNonNullProperty
|
||||
|
||||
return property != null && property.HasValue() ? property : firstNonNullProperty;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.TestHelpers.Stubs;
|
||||
using Umbraco.Tests.Testing;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
using Umbraco.Web.PublishedCache.XmlPublishedCache;
|
||||
@@ -44,11 +48,11 @@ namespace Umbraco.Tests.Routing
|
||||
globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false);
|
||||
SettingsForTests.ConfigureSettings(globalSettings.Object);
|
||||
|
||||
var umbracoContext = GetUmbracoContext("/test", 1111, urlProviders: new []
|
||||
var umbracoContext = GetUmbracoContext("/test", 1111, urlProviders: new[]
|
||||
{
|
||||
new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper())
|
||||
}, globalSettings:globalSettings.Object);
|
||||
|
||||
}, globalSettings: globalSettings.Object);
|
||||
|
||||
var requestHandlerMock = Mock.Get(_umbracoSettings.RequestHandler);
|
||||
requestHandlerMock.Setup(x => x.AddTrailingSlash).Returns(false);// (cached routes have none)
|
||||
|
||||
@@ -110,7 +114,7 @@ namespace Umbraco.Tests.Routing
|
||||
var umbracoContext = GetUmbracoContext("/test", 1111, urlProviders: new[]
|
||||
{
|
||||
new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper())
|
||||
}, globalSettings:globalSettings.Object);
|
||||
}, globalSettings: globalSettings.Object);
|
||||
|
||||
var requestMock = Mock.Get(_umbracoSettings.RequestHandler);
|
||||
requestMock.Setup(x => x.UseDomainPrefixes).Returns(false);
|
||||
@@ -140,7 +144,7 @@ namespace Umbraco.Tests.Routing
|
||||
var umbracoContext = GetUmbracoContext("/test", 1111, urlProviders: new[]
|
||||
{
|
||||
new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper())
|
||||
}, globalSettings:globalSettings.Object);
|
||||
}, globalSettings: globalSettings.Object);
|
||||
|
||||
var requestMock = Mock.Get(_umbracoSettings.RequestHandler);
|
||||
requestMock.Setup(x => x.UseDomainPrefixes).Returns(false);
|
||||
@@ -149,14 +153,118 @@ namespace Umbraco.Tests.Routing
|
||||
Assert.AreEqual(niceUrlMatch, result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This tests DefaultUrlProvider.GetUrl with a specific culture when the current URL is the culture specific domain
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Get_Nice_Url_Relative_Or_Absolute()
|
||||
public void Get_Url_For_Culture_Variant_With_Current_Url()
|
||||
{
|
||||
const string currentUri = "http://example.com/fr/test";
|
||||
|
||||
var globalSettings = Mock.Get(TestObjects.GetGlobalSettings()); //this will modify the IGlobalSettings instance stored in the container
|
||||
globalSettings.Setup(x => x.UseDirectoryUrls).Returns(true);
|
||||
globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false);
|
||||
SettingsForTests.ConfigureSettings(globalSettings.Object);
|
||||
|
||||
var requestMock = Mock.Get(_umbracoSettings.RequestHandler);
|
||||
requestMock.Setup(x => x.UseDomainPrefixes).Returns(false);
|
||||
|
||||
var publishedContentCache = new Mock<IPublishedContentCache>();
|
||||
publishedContentCache.Setup(x => x.GetRouteById(1234, "fr-FR"))
|
||||
.Returns("9876/home/test-fr"); //prefix with the root id node with the domain assigned as per the umbraco standard
|
||||
|
||||
var domainCache = new Mock<IDomainCache>();
|
||||
domainCache.Setup(x => x.GetAssigned(It.IsAny<int>(), false))
|
||||
.Returns((int contentId, bool includeWildcards) =>
|
||||
{
|
||||
if (contentId != 9876) return Enumerable.Empty<Domain>();
|
||||
return new[]
|
||||
{
|
||||
new Domain(2, "example.com/en", 9876, CultureInfo.GetCultureInfo("en-US"), false, true), //default
|
||||
new Domain(3, "example.com/fr", 9876, CultureInfo.GetCultureInfo("fr-FR"), false, true)
|
||||
};
|
||||
});
|
||||
|
||||
var snapshot = Mock.Of<IPublishedSnapshot>(x => x.Content == publishedContentCache.Object && x.Domains == domainCache.Object);
|
||||
|
||||
var snapshotService = new Mock<IPublishedSnapshotService>();
|
||||
snapshotService.Setup(x => x.CreatePublishedSnapshot(It.IsAny<string>()))
|
||||
.Returns(snapshot);
|
||||
|
||||
var umbracoContext = GetUmbracoContext(currentUri, umbracoSettings: _umbracoSettings,
|
||||
urlProviders: new[] {
|
||||
new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper())
|
||||
},
|
||||
globalSettings: globalSettings.Object,
|
||||
snapshotService: snapshotService.Object);
|
||||
|
||||
|
||||
var url = umbracoContext.UrlProvider.GetUrl(1234, "fr-FR");
|
||||
|
||||
//the current uri is the culture specific domain we want, so the result is a relative path since we are on the culture specific domain
|
||||
Assert.AreEqual("/fr/home/test-fr/", url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This tests DefaultUrlProvider.GetUrl with a specific culture when the current URL is not the culture specific domain
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Get_Url_For_Culture_Variant_Non_Current_Url()
|
||||
{
|
||||
const string currentUri = "http://example.com/en/test";
|
||||
|
||||
var globalSettings = Mock.Get(TestObjects.GetGlobalSettings()); //this will modify the IGlobalSettings instance stored in the container
|
||||
globalSettings.Setup(x => x.UseDirectoryUrls).Returns(true);
|
||||
globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false);
|
||||
SettingsForTests.ConfigureSettings(globalSettings.Object);
|
||||
|
||||
var requestMock = Mock.Get(_umbracoSettings.RequestHandler);
|
||||
requestMock.Setup(x => x.UseDomainPrefixes).Returns(false);
|
||||
|
||||
var publishedContentCache = new Mock<IPublishedContentCache>();
|
||||
publishedContentCache.Setup(x => x.GetRouteById(1234, "fr-FR"))
|
||||
.Returns("9876/home/test-fr"); //prefix with the root id node with the domain assigned as per the umbraco standard
|
||||
|
||||
var domainCache = new Mock<IDomainCache>();
|
||||
domainCache.Setup(x => x.GetAssigned(It.IsAny<int>(), false))
|
||||
.Returns((int contentId, bool includeWildcards) =>
|
||||
{
|
||||
if (contentId != 9876) return Enumerable.Empty<Domain>();
|
||||
return new[]
|
||||
{
|
||||
new Domain(2, "example.com/en", 9876, CultureInfo.GetCultureInfo("en-US"), false, true), //default
|
||||
new Domain(3, "example.com/fr", 9876, CultureInfo.GetCultureInfo("fr-FR"), false, true)
|
||||
};
|
||||
});
|
||||
|
||||
var snapshot = Mock.Of<IPublishedSnapshot>(x => x.Content == publishedContentCache.Object && x.Domains == domainCache.Object);
|
||||
|
||||
var snapshotService = new Mock<IPublishedSnapshotService>();
|
||||
snapshotService.Setup(x => x.CreatePublishedSnapshot(It.IsAny<string>()))
|
||||
.Returns(snapshot);
|
||||
|
||||
var umbracoContext = GetUmbracoContext(currentUri, umbracoSettings: _umbracoSettings,
|
||||
urlProviders: new[] {
|
||||
new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper())
|
||||
},
|
||||
globalSettings: globalSettings.Object,
|
||||
snapshotService: snapshotService.Object);
|
||||
|
||||
|
||||
var url = umbracoContext.UrlProvider.GetUrl(1234, "fr-FR");
|
||||
|
||||
//the current uri is not the culture specific domain we want, so the result is an absolute path to the culture specific domain
|
||||
Assert.AreEqual("http://example.com/fr/home/test-fr/", url);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Url_Relative_Or_Absolute()
|
||||
{
|
||||
var globalSettings = Mock.Get(TestObjects.GetGlobalSettings()); //this will modify the IGlobalSettings instance stored in the container
|
||||
globalSettings.Setup(x => x.UseDirectoryUrls).Returns(true);
|
||||
globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false);
|
||||
SettingsForTests.ConfigureSettings(globalSettings.Object);
|
||||
|
||||
|
||||
|
||||
var requestMock = Mock.Get(_umbracoSettings.RequestHandler);
|
||||
requestMock.Setup(x => x.UseDomainPrefixes).Returns(false);
|
||||
@@ -164,7 +272,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 SiteDomainHelper())
|
||||
}, globalSettings:globalSettings.Object);
|
||||
}, globalSettings: globalSettings.Object);
|
||||
|
||||
Assert.AreEqual("/home/sub1/custom-sub-1/", umbracoContext.UrlProvider.GetUrl(1177));
|
||||
|
||||
@@ -187,7 +295,7 @@ namespace Umbraco.Tests.Routing
|
||||
var umbracoContext = GetUmbracoContext("http://example.com/test", 1111, urlProviders: new[]
|
||||
{
|
||||
new DefaultUrlProvider(_umbracoSettings.RequestHandler, Logger, globalSettings.Object, new SiteDomainHelper())
|
||||
}, globalSettings:globalSettings.Object);
|
||||
}, globalSettings: globalSettings.Object);
|
||||
|
||||
//mock the Umbraco settings that we need
|
||||
var requestMock = Mock.Get(_umbracoSettings.RequestHandler);
|
||||
|
||||
66
src/Umbraco.Tests/TestHelpers/Stubs/TestPublishedContent.cs
Normal file
66
src/Umbraco.Tests/TestHelpers/Stubs/TestPublishedContent.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
|
||||
namespace Umbraco.Tests.TestHelpers.Stubs
|
||||
{
|
||||
internal class TestPublishedContent : PublishedElement, IPublishedContent
|
||||
{
|
||||
public TestPublishedContent(PublishedContentType contentType, int id, Guid key, Dictionary<string, object> values, bool previewing, Dictionary<string, PublishedCultureName> cultureNames = null)
|
||||
: base(contentType, key, values, previewing)
|
||||
{
|
||||
Id = id;
|
||||
CultureNames = cultureNames;
|
||||
}
|
||||
|
||||
public int Id { get; }
|
||||
public int TemplateId { get; set; }
|
||||
public int SortOrder { get; set; }
|
||||
public string Name { get; set; }
|
||||
public IReadOnlyDictionary<string, PublishedCultureName> CultureNames { get; set; }
|
||||
public string UrlName { get; set; }
|
||||
public string DocumentTypeAlias => ContentType.Alias;
|
||||
public int DocumentTypeId { get; set; }
|
||||
public string WriterName { get; set; }
|
||||
public string CreatorName { get; set; }
|
||||
public int WriterId { get; set; }
|
||||
public int CreatorId { get; set; }
|
||||
public string Path { get; set; }
|
||||
public DateTime CreateDate { get; set; }
|
||||
public DateTime UpdateDate { get; set; }
|
||||
public Guid Version { get; set; }
|
||||
public int Level { get; set; }
|
||||
public string Url { get; set; }
|
||||
public PublishedItemType ItemType => ContentType.ItemType;
|
||||
public bool IsDraft { get; set; }
|
||||
public IPublishedContent Parent { get; set; }
|
||||
public IEnumerable<IPublishedContent> Children { get; set; }
|
||||
|
||||
// copied from PublishedContentBase
|
||||
public IPublishedProperty GetProperty(string alias, bool recurse)
|
||||
{
|
||||
var property = GetProperty(alias);
|
||||
if (recurse == false) return property;
|
||||
|
||||
IPublishedContent content = this;
|
||||
var firstNonNullProperty = property;
|
||||
while (content != null && (property == null || property.HasValue() == false))
|
||||
{
|
||||
content = content.Parent;
|
||||
property = content?.GetProperty(alias);
|
||||
if (firstNonNullProperty == null && property != null) firstNonNullProperty = property;
|
||||
}
|
||||
|
||||
// if we find a content with the property with a value, return that property
|
||||
// if we find no content with the property, return null
|
||||
// if we find a content with the property without a value, return that property
|
||||
// have to save that first property while we look further up, hence firstNonNullProperty
|
||||
|
||||
return property != null && property.HasValue() ? property : firstNonNullProperty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -366,7 +366,8 @@ namespace Umbraco.Tests.TestHelpers
|
||||
var umbracoContext = new UmbracoContext(
|
||||
httpContext,
|
||||
service,
|
||||
new WebSecurity(httpContext, Container.GetInstance<IUserService>(), Container.GetInstance<IGlobalSettings>()),
|
||||
new WebSecurity(httpContext, Container.GetInstance<IUserService>(),
|
||||
Container.GetInstance<IGlobalSettings>()),
|
||||
umbracoSettings ?? Container.GetInstance<IUmbracoSettingsSection>(),
|
||||
urlProviders ?? Enumerable.Empty<IUrlProvider>(),
|
||||
globalSettings ?? Container.GetInstance<IGlobalSettings>(),
|
||||
|
||||
@@ -178,6 +178,7 @@
|
||||
<Compile Include="TestHelpers\Entities\MockedUserGroup.cs" />
|
||||
<Compile Include="TestHelpers\NoHttpContextAccessor.cs" />
|
||||
<Compile Include="TestHelpers\Stubs\TestExamineManager.cs" />
|
||||
<Compile Include="TestHelpers\Stubs\TestPublishedContent.cs" />
|
||||
<Compile Include="Testing\ContentBaseExtensions.cs" />
|
||||
<Compile Include="Testing\TestDatabase.cs" />
|
||||
<Compile Include="Testing\TestingTests\NUnitTests.cs" />
|
||||
|
||||
@@ -2,15 +2,23 @@
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Web.Composing;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Routing;
|
||||
|
||||
namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
internal class RedirectUrlMapperProfile : Profile
|
||||
{
|
||||
private readonly UrlProvider _urlProvider;
|
||||
|
||||
public RedirectUrlMapperProfile(UrlProvider urlProvider)
|
||||
{
|
||||
_urlProvider = urlProvider;
|
||||
}
|
||||
|
||||
public RedirectUrlMapperProfile()
|
||||
{
|
||||
CreateMap<IRedirectUrl, ContentRedirectUrl>()
|
||||
.ForMember(x => x.OriginalUrl, expression => expression.MapFrom(item => Current.UmbracoContext.UrlProvider.GetUrlFromRoute(item.ContentId, item.Url)))
|
||||
.ForMember(x => x.OriginalUrl, expression => expression.MapFrom(item => _urlProvider.GetUrlFromRoute(item.ContentId, item.Url, null)))
|
||||
.ForMember(x => x.DestinationUrl, expression => expression.Ignore())
|
||||
.ForMember(x => x.RedirectId, expression => expression.MapFrom(item => item.Key));
|
||||
}
|
||||
|
||||
@@ -163,7 +163,9 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// assemble the route
|
||||
pathParts.Reverse();
|
||||
var path = "/" + string.Join("/", pathParts); // will be "/" or "/foo" or "/foo/bar" etc
|
||||
var route = (n?.Id.ToString(CultureInfo.InvariantCulture) ?? "") + path;
|
||||
//prefix the root node id containing the domain if it exists (this is a standard way of creating route paths)
|
||||
//and is done so that we know the ID of the domain node for the path
|
||||
var route = (n?.Id.ToString(CultureInfo.InvariantCulture) ?? "") + path;
|
||||
|
||||
return route;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Umbraco.Web.Routing
|
||||
#region GetUrl
|
||||
|
||||
/// <summary>
|
||||
/// Gets the nice url of a published content.
|
||||
/// Gets the url of a published content.
|
||||
/// </summary>
|
||||
/// <param name="umbracoContext">The Umbraco context.</param>
|
||||
/// <param name="id">The published content id.</param>
|
||||
@@ -51,10 +51,10 @@ namespace Umbraco.Web.Routing
|
||||
// will not use cache if previewing
|
||||
var route = umbracoContext.ContentCache.GetRouteById(id, culture);
|
||||
|
||||
return GetUrlFromRoute(route, umbracoContext, id, current, mode);
|
||||
return GetUrlFromRoute(route, umbracoContext, id, current, mode, culture);
|
||||
}
|
||||
|
||||
internal string GetUrlFromRoute(string route, UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode)
|
||||
internal string GetUrlFromRoute(string route, UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode, string culture)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(route))
|
||||
{
|
||||
@@ -71,7 +71,7 @@ namespace Umbraco.Web.Routing
|
||||
var path = pos == 0 ? route : route.Substring(pos);
|
||||
var domainUri = pos == 0
|
||||
? null
|
||||
: domainHelper.DomainForNode(int.Parse(route.Substring(0, pos)), current);
|
||||
: domainHelper.DomainForNode(int.Parse(route.Substring(0, pos)), current, culture);
|
||||
|
||||
// assemble the url from domainUri (maybe null) and path
|
||||
return AssembleUrl(domainUri, path, current, mode).ToString();
|
||||
@@ -119,8 +119,7 @@ namespace Umbraco.Web.Routing
|
||||
var route = umbracoContext.ContentCache.GetRouteById(id, d?.Culture?.Name);
|
||||
if (route == null) continue;
|
||||
|
||||
//need to strip off the leading ID for the route
|
||||
//TODO: Is there a nicer way to deal with this?
|
||||
//need to strip off the leading ID for the route if it exists (occurs if the route is for a node with a domain assigned)
|
||||
var pos = route.IndexOf('/');
|
||||
var path = pos == 0 ? route : route.Substring(pos);
|
||||
|
||||
@@ -170,7 +169,7 @@ namespace Umbraco.Web.Routing
|
||||
{
|
||||
if (mode == UrlProviderMode.Auto)
|
||||
{
|
||||
if (current != null && domainUri.Uri.GetLeftPart(UriPartial.Authority) == current.GetLeftPart(UriPartial.Authority))
|
||||
if (current != null && current.GetLeftPart(UriPartial.Path).InvariantStartsWith(domainUri.Uri.GetLeftPart(UriPartial.Path)))
|
||||
mode = UrlProviderMode.Relative;
|
||||
else
|
||||
mode = UrlProviderMode.Absolute;
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Umbraco.Web.Routing
|
||||
/// <returns>The domain and its uri, if any, that best matches the specified uri, else null.</returns>
|
||||
/// <remarks>If at least a domain is set on the node then the method returns the domain that
|
||||
/// best matches the specified uri, else it returns null.</remarks>
|
||||
internal DomainAndUri DomainForNode(int nodeId, Uri current)
|
||||
internal DomainAndUri DomainForNode(int nodeId, Uri current, string culture = null)
|
||||
{
|
||||
// be safe
|
||||
if (nodeId <= 0)
|
||||
@@ -45,7 +45,7 @@ namespace Umbraco.Web.Routing
|
||||
return null;
|
||||
|
||||
// else filter
|
||||
var domainAndUri = DomainForUri(domains, current, domainAndUris => _siteDomainHelper.MapDomain(current, domainAndUris));
|
||||
var domainAndUri = DomainForUri(domains, current, culture, domainAndUris => _siteDomainHelper.MapDomain(current, domainAndUris));
|
||||
|
||||
if (domainAndUri == null)
|
||||
throw new Exception("DomainForUri returned null.");
|
||||
@@ -108,14 +108,13 @@ namespace Umbraco.Web.Routing
|
||||
/// the right one, unless it is <c>null</c>, in which case the method returns <c>null</c>.</para>
|
||||
/// <para>The filter, if any, will be called only with a non-empty argument, and _must_ return something.</para>
|
||||
/// </remarks>
|
||||
internal static DomainAndUri DomainForUri(IEnumerable<Domain> domains, Uri current, Func<DomainAndUri[], DomainAndUri> filter = null)
|
||||
internal static DomainAndUri DomainForUri(IEnumerable<Domain> domains, Uri current, string culture = null, Func<DomainAndUri[], DomainAndUri> filter = null)
|
||||
{
|
||||
// sanitize the list to have proper uris for comparison (scheme, path end with /)
|
||||
// we need to end with / because example.com/foo cannot match example.com/foobar
|
||||
// we need to order so example.com/foo matches before example.com/
|
||||
var domainsAndUris = domains
|
||||
.Where(d => d.IsWildcard == false)
|
||||
//.Select(SanitizeForBackwardCompatibility)
|
||||
.Select(d => new DomainAndUri(d, current))
|
||||
.OrderByDescending(d => d.Uri.ToString())
|
||||
.ToArray();
|
||||
@@ -126,8 +125,12 @@ namespace Umbraco.Web.Routing
|
||||
DomainAndUri domainAndUri;
|
||||
if (current == null)
|
||||
{
|
||||
//get the default domain (there should be one)
|
||||
domainAndUri = domainsAndUris.FirstOrDefault(x => x.IsDefault);
|
||||
//get the default domain or the one matching the culture if specified
|
||||
domainAndUri = domainsAndUris.FirstOrDefault(x => culture.IsNullOrWhiteSpace() ? x.IsDefault : x.Culture.Name.InvariantEquals(culture));
|
||||
|
||||
if (domainAndUri == null && !culture.IsNullOrWhiteSpace())
|
||||
throw new InvalidOperationException($"No domain was found by the specified culture '{culture}'");
|
||||
|
||||
if (domainAndUri == null)
|
||||
domainAndUri = domainsAndUris.First(); // take the first one by default (what else can we do?)
|
||||
}
|
||||
@@ -138,13 +141,17 @@ namespace Umbraco.Web.Routing
|
||||
var currentWithSlash = current.EndPathWithSlash();
|
||||
domainAndUri = domainsAndUris
|
||||
.FirstOrDefault(d => d.Uri.EndPathWithSlash().IsBaseOf(currentWithSlash));
|
||||
if (domainAndUri != null) return domainAndUri;
|
||||
//is culture specified? if so this will need to match too
|
||||
if (domainAndUri != null && (culture.IsNullOrWhiteSpace() || domainAndUri.Culture.Name.InvariantEquals(culture)))
|
||||
return domainAndUri;
|
||||
|
||||
// if none matches, try again without the port
|
||||
// ie current is www.example.com:1234/foo/bar, look for domain www.example.com
|
||||
domainAndUri = domainsAndUris
|
||||
.FirstOrDefault(d => d.Uri.EndPathWithSlash().IsBaseOf(currentWithSlash.WithoutPort()));
|
||||
if (domainAndUri != null) return domainAndUri;
|
||||
//is culture specified? if so this will need to match too
|
||||
if (domainAndUri != null && (culture.IsNullOrWhiteSpace() || domainAndUri.Culture.Name.InvariantEquals(culture)))
|
||||
return domainAndUri;
|
||||
|
||||
// if none matches, then try to run the filter to pick a domain
|
||||
if (filter != null)
|
||||
@@ -170,7 +177,6 @@ namespace Umbraco.Web.Routing
|
||||
{
|
||||
return domains
|
||||
.Where(d => d.IsWildcard == false)
|
||||
//.Select(SanitizeForBackwardCompatibility)
|
||||
.Select(d => new DomainAndUri(d, current))
|
||||
.OrderByDescending(d => d.Uri.ToString());
|
||||
}
|
||||
|
||||
@@ -216,12 +216,12 @@ namespace Umbraco.Web.Routing
|
||||
return url ?? "#"; // legacy wants this
|
||||
}
|
||||
|
||||
internal string GetUrlFromRoute(int id, string route)
|
||||
internal string GetUrlFromRoute(int id, string route, string culture)
|
||||
{
|
||||
var provider = _urlProviders.OfType<DefaultUrlProvider>().FirstOrDefault();
|
||||
var url = provider == null
|
||||
? route // what else?
|
||||
: provider.GetUrlFromRoute(route, UmbracoContext.Current, id, _umbracoContext.CleanedUmbracoUrl, Mode);
|
||||
: provider.GetUrlFromRoute(route, UmbracoContext.Current, id, _umbracoContext.CleanedUmbracoUrl, Mode, culture);
|
||||
return url ?? "#";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user