Files
Umbraco-CMS/src/Umbraco.Core/Routing/AliasUrlProvider.cs

148 lines
6.4 KiB
C#
Raw Normal View History

using System;
2018-06-29 19:52:40 +02:00
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.Web;
using Umbraco.Extensions;
2018-06-29 19:52:40 +02:00
namespace Umbraco.Cms.Core.Routing
2018-06-29 19:52:40 +02:00
{
/// <summary>
2020-10-05 20:48:38 +02:00
/// Provides URLs using the <c>umbracoUrlAlias</c> property.
2018-06-29 19:52:40 +02:00
/// </summary>
public class AliasUrlProvider : IUrlProvider
{
private readonly RequestHandlerSettings _requestConfig;
private readonly ISiteDomainMapper _siteDomainMapper;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly UriUtility _uriUtility;
private readonly IPublishedValueFallback _publishedValueFallback;
public AliasUrlProvider(IOptions<RequestHandlerSettings> requestConfig, ISiteDomainMapper siteDomainMapper, UriUtility uriUtility, IPublishedValueFallback publishedValueFallback, IUmbracoContextAccessor umbracoContextAccessor)
2018-06-29 19:52:40 +02:00
{
_requestConfig = requestConfig.Value;
_siteDomainMapper = siteDomainMapper;
_uriUtility = uriUtility;
_publishedValueFallback = publishedValueFallback;
_umbracoContextAccessor = umbracoContextAccessor;
}
2018-06-29 19:52:40 +02:00
// note - at the moment we seem to accept pretty much anything as an alias
// without any form of validation ... could even prob. kill the XPath ...
// ok, this is somewhat experimental and is NOT enabled by default
#region GetUrl
/// <inheritdoc />
public UrlInfo GetUrl(IPublishedContent content, UrlMode mode, string culture, Uri current)
2018-06-29 19:52:40 +02:00
{
return null; // we have nothing to say
}
#endregion
#region GetOtherUrls
/// <summary>
2020-10-05 20:48:38 +02:00
/// Gets the other URLs of a published content.
2018-06-29 19:52:40 +02:00
/// </summary>
/// <param name="umbracoContext">The Umbraco context.</param>
/// <param name="id">The published content id.</param>
2020-10-05 20:48:38 +02:00
/// <param name="current">The current absolute URL.</param>
/// <returns>The other URLs for the published content.</returns>
2018-06-29 19:52:40 +02:00
/// <remarks>
2020-10-05 20:48:38 +02:00
/// <para>Other URLs are those that <c>GetUrl</c> would not return in the current context, but would be valid
/// URLs for the node in other contexts (different domain for current request, umbracoUrlAlias...).</para>
2018-06-29 19:52:40 +02:00
/// </remarks>
public IEnumerable<UrlInfo> GetOtherUrls(int id, Uri current)
2018-06-29 19:52:40 +02:00
{
var umbracoContext = _umbracoContextAccessor.UmbracoContext;
var node = umbracoContext.Content.GetById(id);
2018-12-18 22:02:39 +11:00
if (node == null)
yield break;
if (!node.HasProperty(Constants.Conventions.Content.UrlAlias))
2018-12-18 22:02:39 +11:00
yield break;
2018-07-30 10:10:01 +02:00
// look for domains, walking up the tree
2018-06-29 19:52:40 +02:00
var n = node;
var domainUris = DomainUtilities.DomainsForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainMapper, n.Id, current, false);
2018-06-29 19:52:40 +02:00
while (domainUris == null && n != null) // n is null at root
{
// move to parent node
n = n.Parent;
domainUris = n == null ? null : DomainUtilities.DomainsForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainMapper, n.Id, current, excludeDefault: false);
2018-06-29 19:52:40 +02:00
}
2018-07-30 10:10:01 +02:00
// determine whether the alias property varies
var varies = node.GetProperty(Constants.Conventions.Content.UrlAlias).PropertyType.VariesByCulture();
if (domainUris == null)
{
2018-07-30 10:10:01 +02:00
// no domain
2020-10-05 20:48:38 +02:00
// if the property is invariant, then URL "/<alias>" is ok
2018-07-30 10:10:01 +02:00
// if the property varies, then what are we supposed to do?
// the content finder may work, depending on the 'current' culture,
// but there's no way we can return something meaningful here
if (varies)
2018-12-18 22:02:39 +11:00
yield break;
2018-07-30 10:10:01 +02:00
var umbracoUrlName = node.Value<string>(_publishedValueFallback, Constants.Conventions.Content.UrlAlias);
var aliases = umbracoUrlName?.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries);
if (aliases == null || aliases.Any() == false)
2018-12-18 22:02:39 +11:00
yield break;
foreach (var alias in aliases.Distinct())
{
var path = "/" + alias;
var uri = new Uri(path, UriKind.Relative);
yield return UrlInfo.Url(_uriUtility.UriFromUmbraco(uri, _requestConfig).ToString());
}
}
else
{
2020-10-05 20:48:38 +02:00
// some domains: one URL per domain, which is "<domain>/<alias>"
foreach (var domainUri in domainUris)
2018-06-29 19:52:40 +02:00
{
2020-10-05 20:48:38 +02:00
// if the property is invariant, get the invariant value, URL is "<domain>/<invariant-alias>"
// if the property varies, get the variant value, URL is "<domain>/<variant-alias>"
2018-07-30 10:10:01 +02:00
// but! only if the culture is published, else ignore
if (varies && !node.HasCulture(domainUri.Culture)) continue;
2018-07-30 10:10:01 +02:00
var umbracoUrlName = varies
? node.Value<string>(_publishedValueFallback,Constants.Conventions.Content.UrlAlias, culture: domainUri.Culture)
: node.Value<string>(_publishedValueFallback, Constants.Conventions.Content.UrlAlias);
2018-07-30 10:10:01 +02:00
var aliases = umbracoUrlName?.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries);
if (aliases == null || aliases.Any() == false)
2018-12-18 22:02:39 +11:00
continue;
foreach(var alias in aliases.Distinct())
{
var path = "/" + alias;
var uri = new Uri(CombinePaths(domainUri.Uri.GetLeftPart(UriPartial.Path), path));
yield return UrlInfo.Url(_uriUtility.UriFromUmbraco(uri, _requestConfig).ToString(), domainUri.Culture);
}
}
}
2018-06-29 19:52:40 +02:00
}
#endregion
#region Utilities
string CombinePaths(string path1, string path2)
{
string path = path1.TrimEnd(Constants.CharArrays.ForwardSlash) + path2;
return path == "/" ? path : path.TrimEnd(Constants.CharArrays.ForwardSlash);
2018-06-29 19:52:40 +02:00
}
#endregion
}
}