* Run code cleanup * Start manual cleanup after dotnet format * Finish up manual pass * Fix up missed warnings * Fix after merge * Update src/Umbraco.Core/Cache/ContentTypeCacheRefresher.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/DataTypeCacheRefresher.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/DeepCloneAppCache.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/DomainCacheRefresher.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/FastDictionaryAppCacheBase.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/FastDictionaryAppCacheBase.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/FastDictionaryAppCacheBase.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/FastDictionaryAppCacheBase.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/FastDictionaryAppCacheBase.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/MacroCacheRefresher.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/MediaCacheRefresher.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/MemberCacheRefresher.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/MemberGroupCacheRefresher.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Composing/SetCollectionBuilderBase.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/ContentApps/ContentAppFactoryCollectionBuilder.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Dashboards/DashboardCollectionBuilder.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/ContentTypeRefreshedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/ContentTypeSavedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/ContentTypeSavingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/DictionaryCacheRefresherNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/DataTypeCacheRefresherNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/ContentUnpublishingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/DictionaryItemDeletingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/DictionaryItemSavedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/DictionaryItemSavingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/DomainCacheRefresherNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/LanguageCacheRefresherNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MacroCacheRefresherNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaCacheRefresherNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaEmptiedRecycleBinNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaEmptyingRecycleBinNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaMovedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaMovedToRecycleBinNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaMovedToRecycleBinNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaMovingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaMovingToRecycleBinNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaTreeChangeNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaTreeChangeNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaTypeChangedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaTypeDeletingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaTypeMovedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaTypeMovingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaTypeMovingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaTypeRefreshedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberCacheRefresherNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberGroupCacheRefresherNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberGroupDeletingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberGroupSavedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberGroupSavingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberTypeChangedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberTypeDeletedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberTypeDeletingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberTypeMovedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberTypeMovedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberTypeMovingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberTypeMovingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberTypeRefreshedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberTypeSavingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/UriExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MovedToRecycleBinNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MovedToRecycleBinNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MovingToRecycleBinNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MovingToRecycleBinNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/PartialViewDeletingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/UriExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/IO/PhysicalFileSystem.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/IO/PhysicalFileSystem.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/IO/ShadowWrapper.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Logging/DisposableTimer.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Install/InstallSteps/UpgradeStep.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Mapping/MapDefinitionCollectionBuilder.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Media/EmbedProviders/EmbedProvidersCollectionBuilder.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/PartialViewSavedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Models/ContentEditing/ContentVariationDisplay.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/PartialViewSavingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/PublicAccessCacheRefresherNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/PublicAccessEntryDeletedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/PublicAccessEntryDeletingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/PublicAccessEntryDeletingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/PublicAccessEntrySavedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/PublicAccessEntrySavingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/PublicAccessEntrySavingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/RelationTypeCacheRefresherNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/RelationTypeDeletingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/RelationTypeSavedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/RelationTypeSavingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/StatefulNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/StylesheetDeletingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/StylesheetSavingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Models/DeepCloneHelper.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Models/File.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Models/PropertyGroupExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Models/PropertyGroupExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Fix based on review * Fix after merge Signed-off-by: Zeegaan <nge@umbraco.dk> Co-authored-by: Nikolaj Geisle <niko737@edu.ucl.dk> Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> Co-authored-by: Zeegaan <nge@umbraco.dk>
262 lines
10 KiB
C#
262 lines
10 KiB
C#
using Microsoft.Extensions.Logging;
|
|
using Umbraco.Cms.Core;
|
|
using Umbraco.Cms.Core.Models;
|
|
using Umbraco.Cms.Core.Models.PublishedContent;
|
|
using Umbraco.Cms.Core.Routing;
|
|
using Umbraco.Cms.Core.Services;
|
|
using Umbraco.Cms.Core.Web;
|
|
|
|
namespace Umbraco.Extensions;
|
|
|
|
public static class UrlProviderExtensions
|
|
{
|
|
/// <summary>
|
|
/// Gets the URLs of the content item.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>Use when displaying URLs. If errors occur when generating the URLs, they will show in the list.</para>
|
|
/// <para>Contains all the URLs that we can figure out (based upon domains, etc).</para>
|
|
/// </remarks>
|
|
public static async Task<IEnumerable<UrlInfo>> GetContentUrlsAsync(
|
|
this IContent content,
|
|
IPublishedRouter publishedRouter,
|
|
IUmbracoContext umbracoContext,
|
|
ILocalizationService localizationService,
|
|
ILocalizedTextService textService,
|
|
IContentService contentService,
|
|
IVariationContextAccessor variationContextAccessor,
|
|
ILogger<IContent> logger,
|
|
UriUtility uriUtility,
|
|
IPublishedUrlProvider publishedUrlProvider)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(content);
|
|
ArgumentNullException.ThrowIfNull(publishedRouter);
|
|
ArgumentNullException.ThrowIfNull(umbracoContext);
|
|
ArgumentNullException.ThrowIfNull(localizationService);
|
|
ArgumentNullException.ThrowIfNull(textService);
|
|
ArgumentNullException.ThrowIfNull(contentService);
|
|
ArgumentNullException.ThrowIfNull(variationContextAccessor);
|
|
ArgumentNullException.ThrowIfNull(logger);
|
|
ArgumentNullException.ThrowIfNull(uriUtility);
|
|
ArgumentNullException.ThrowIfNull(publishedUrlProvider);
|
|
|
|
var result = new List<UrlInfo>();
|
|
|
|
if (content.Published == false)
|
|
{
|
|
result.Add(UrlInfo.Message(textService.Localize("content", "itemNotPublished")));
|
|
return result;
|
|
}
|
|
|
|
// build a list of URLs, for the back-office
|
|
// which will contain
|
|
// - the 'main' URLs, which is what .Url would return, for each culture
|
|
// - the 'other' URLs we know (based upon domains, etc)
|
|
//
|
|
// need to work through each installed culture:
|
|
// on invariant nodes, each culture returns the same URL segment but,
|
|
// we don't know if the branch to this content is invariant, so we need to ask
|
|
// for URLs for all cultures.
|
|
// and, not only for those assigned to domains in the branch, because we want
|
|
// to show what GetUrl() would return, for every culture.
|
|
var urls = new HashSet<UrlInfo>();
|
|
var cultures = localizationService.GetAllLanguages().Select(x => x.IsoCode).ToList();
|
|
|
|
// get all URLs for all cultures
|
|
// in a HashSet, so de-duplicates too
|
|
foreach (UrlInfo cultureUrl in await GetContentUrlsByCultureAsync(content, cultures, publishedRouter, umbracoContext, contentService, textService, variationContextAccessor, logger, uriUtility, publishedUrlProvider))
|
|
{
|
|
urls.Add(cultureUrl);
|
|
}
|
|
|
|
// return the real URLs first, then the messages
|
|
foreach (IGrouping<bool, UrlInfo> urlGroup in urls.GroupBy(x => x.IsUrl).OrderByDescending(x => x.Key))
|
|
{
|
|
// in some cases there will be the same URL for multiple cultures:
|
|
// * The entire branch is invariant
|
|
// * If there are less domain/cultures assigned to the branch than the number of cultures/languages installed
|
|
if (urlGroup.Key)
|
|
{
|
|
result.AddRange(urlGroup.DistinctBy(x => x.Text, StringComparer.OrdinalIgnoreCase).OrderBy(x => x.Text)
|
|
.ThenBy(x => x.Culture));
|
|
}
|
|
else
|
|
{
|
|
result.AddRange(urlGroup);
|
|
}
|
|
}
|
|
|
|
// get the 'other' URLs - ie not what you'd get with GetUrl() but URLs that would route to the document, nevertheless.
|
|
// for these 'other' URLs, we don't check whether they are routable, collide, anything - we just report them.
|
|
foreach (UrlInfo otherUrl in publishedUrlProvider.GetOtherUrls(content.Id).OrderBy(x => x.Text)
|
|
.ThenBy(x => x.Culture))
|
|
{
|
|
// avoid duplicates
|
|
if (urls.Add(otherUrl))
|
|
{
|
|
result.Add(otherUrl);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to return a <see cref="UrlInfo" /> for each culture for the content while detecting collisions/errors
|
|
/// </summary>
|
|
private static async Task<IEnumerable<UrlInfo>> GetContentUrlsByCultureAsync(
|
|
IContent content,
|
|
IEnumerable<string> cultures,
|
|
IPublishedRouter publishedRouter,
|
|
IUmbracoContext umbracoContext,
|
|
IContentService contentService,
|
|
ILocalizedTextService textService,
|
|
IVariationContextAccessor variationContextAccessor,
|
|
ILogger logger,
|
|
UriUtility uriUtility,
|
|
IPublishedUrlProvider publishedUrlProvider)
|
|
{
|
|
var result = new List<UrlInfo>();
|
|
|
|
foreach (var culture in cultures)
|
|
{
|
|
// if content is variant, and culture is not published, skip
|
|
if (content.ContentType.VariesByCulture() && !content.IsCulturePublished(culture))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// if it's variant and culture is published, or if it's invariant, proceed
|
|
string url;
|
|
try
|
|
{
|
|
url = publishedUrlProvider.GetUrl(content.Id, culture: culture);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logger.LogError(ex, "GetUrl exception.");
|
|
url = "#ex";
|
|
}
|
|
|
|
switch (url)
|
|
{
|
|
// deal with 'could not get the URL'
|
|
case "#":
|
|
result.Add(HandleCouldNotGetUrl(content, culture, contentService, textService));
|
|
break;
|
|
|
|
// deal with exceptions
|
|
case "#ex":
|
|
result.Add(UrlInfo.Message(textService.Localize("content", "getUrlException"), culture));
|
|
break;
|
|
|
|
// got a URL, deal with collisions, add URL
|
|
default:
|
|
// detect collisions, etc
|
|
Attempt<UrlInfo?> hasCollision = await DetectCollisionAsync(logger, content, url, culture, umbracoContext, publishedRouter, textService, variationContextAccessor, uriUtility);
|
|
if (hasCollision.Success && hasCollision.Result is not null)
|
|
{
|
|
result.Add(hasCollision.Result);
|
|
}
|
|
else
|
|
{
|
|
result.Add(UrlInfo.Url(url, culture));
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private static UrlInfo HandleCouldNotGetUrl(IContent content, string culture, IContentService contentService, ILocalizedTextService textService)
|
|
{
|
|
// document has a published version yet its URL is "#" => a parent must be
|
|
// unpublished, walk up the tree until we find it, and report.
|
|
IContent? parent = content;
|
|
do
|
|
{
|
|
parent = parent.ParentId > 0 ? contentService.GetParent(parent) : null;
|
|
}
|
|
while (parent != null && parent.Published &&
|
|
(!parent.ContentType.VariesByCulture() || parent.IsCulturePublished(culture)));
|
|
|
|
if (parent == null)
|
|
{
|
|
// oops, internal error
|
|
return UrlInfo.Message(textService.Localize("content", "parentNotPublishedAnomaly"), culture);
|
|
}
|
|
|
|
if (!parent.Published)
|
|
{
|
|
// totally not published
|
|
return UrlInfo.Message(textService.Localize("content", "parentNotPublished", new[] { parent.Name }), culture);
|
|
}
|
|
|
|
// culture not published
|
|
return UrlInfo.Message(
|
|
textService.Localize("content", "parentCultureNotPublished", new[] { parent.Name }),
|
|
culture);
|
|
}
|
|
|
|
private static async Task<Attempt<UrlInfo?>> DetectCollisionAsync(
|
|
ILogger logger,
|
|
IContent content,
|
|
string url,
|
|
string culture,
|
|
IUmbracoContext umbracoContext,
|
|
IPublishedRouter publishedRouter,
|
|
ILocalizedTextService textService,
|
|
IVariationContextAccessor variationContextAccessor,
|
|
UriUtility uriUtility)
|
|
{
|
|
// test for collisions on the 'main' URL
|
|
var uri = new Uri(url.TrimEnd(Constants.CharArrays.ForwardSlash), UriKind.RelativeOrAbsolute);
|
|
if (uri.IsAbsoluteUri == false)
|
|
{
|
|
uri = uri.MakeAbsolute(umbracoContext.CleanedUmbracoUrl);
|
|
}
|
|
|
|
uri = uriUtility.UriToUmbraco(uri);
|
|
IPublishedRequestBuilder builder = await publishedRouter.CreateRequestAsync(uri);
|
|
IPublishedRequest pcr =
|
|
await publishedRouter.RouteRequestAsync(builder, new RouteRequestOptions(RouteDirection.Outbound));
|
|
|
|
if (!pcr.HasPublishedContent())
|
|
{
|
|
const string logMsg = nameof(DetectCollisionAsync) +
|
|
" did not resolve a content item for original url: {Url}, translated to {TranslatedUrl} and culture: {Culture}";
|
|
logger.LogDebug(logMsg, url, uri, culture);
|
|
|
|
var urlInfo = UrlInfo.Message(textService.Localize("content", "routeErrorCannotRoute"), culture);
|
|
return Attempt.Succeed(urlInfo);
|
|
}
|
|
|
|
if (pcr.IgnorePublishedContentCollisions)
|
|
{
|
|
return Attempt<UrlInfo?>.Fail();
|
|
}
|
|
|
|
if (pcr.PublishedContent?.Id != content.Id)
|
|
{
|
|
IPublishedContent? o = pcr.PublishedContent;
|
|
var l = new List<string>();
|
|
while (o != null)
|
|
{
|
|
l.Add(o.Name(variationContextAccessor)!);
|
|
o = o.Parent;
|
|
}
|
|
|
|
l.Reverse();
|
|
var s = "/" + string.Join("/", l) + " (id=" + pcr.PublishedContent?.Id + ")";
|
|
|
|
var urlInfo = UrlInfo.Message(textService.Localize("content", "routeError", new[] { s }), culture);
|
|
return Attempt.Succeed(urlInfo);
|
|
}
|
|
|
|
// no collision
|
|
return Attempt<UrlInfo?>.Fail();
|
|
}
|
|
}
|