V17 - Properties and validators, removing obsoleted code (#19961)

* Removing obsoleted code from ApiMediaQueryService.cs

* Removing obsoleted code from ApiRichTextMarkupParserTests.cs

* Removing obsoleted code from ContentCacheRefresher.cs

* Removing obsoleted code from ContentFinderByUrlAlias.cs and adjusting its tests to use the new logic

* Removing obsoleted code from ContentFinderByUrl.cs & its dependencies

* Removing obsoleted code from ApiRichTextMarkupParserTests.cs

* Removing obsoleted code from DocumentCache.cs & its dependencies

* Removing obsoleted code from MediaCache.cs & its dependencies

* Removing obsoleted code from PublishedCacheBase.cs & its dependencies

* Removing obsoleted code from RenderNoContentController.cs and its tests

* Removing obsoleted code from UmbracoRouteValueTransformer.cs

* Removing obsoleted constructors from DefaultUrlProvider.cs

* Removing the RadioValueEditor.cs & RadioValueValidator.cs obsoleted classes.

* Removing obsolete constructor from MultipleValueValidator.cs

* Removing obsolete constructor from EmailValidator.cs

* Removing obsoleted code from DataValueReferenceFactoryCollection.cs

* Removing obsoleted code from ApiContentBuilderBase.cs

* Fixing constructor missing attribute

* Making use of the TryGet result

* Fixing use of obsoleted constructor

* Removing silly bookmark comment

* Fixing deleted code and restructuring to use new cache

* Making use of TryGetRootKeys bool, to return null if false.

* Extending code to use new constructor

* Updated PublishedContentQuery.cs to return empty array

Co-authored-by: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com>

---------

Co-authored-by: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com>
This commit is contained in:
Nicklas Kramer
2025-08-26 13:31:27 +02:00
committed by GitHub
parent 156bcdc98a
commit 2a6bb64c78
30 changed files with 177 additions and 595 deletions

View File

@@ -66,7 +66,12 @@ internal sealed class ApiMediaQueryService : IApiMediaQueryService
private IPublishedContent? TryGetByPath(string path, IPublishedMediaCache mediaCache)
{
var segments = path.Split(Constants.CharArrays.ForwardSlash, StringSplitOptions.RemoveEmptyEntries);
IEnumerable<IPublishedContent> currentChildren = mediaCache.GetAtRoot();
if (_mediaNavigationQueryService.TryGetRootKeys(out IEnumerable<Guid> rootKeys) is false)
{
return null;
}
IEnumerable<IPublishedContent> currentChildren = rootKeys.Select(x => mediaCache.GetById(false, x)).WhereNotNull();
IPublishedContent? resolvedMedia = null;
foreach (var segment in segments)
@@ -101,9 +106,9 @@ internal sealed class ApiMediaQueryService : IApiMediaQueryService
}
IPublishedMediaCache mediaCache = GetRequiredPublishedMediaCache();
if (childrenOf.Trim(Constants.CharArrays.ForwardSlash).Length == 0)
if (childrenOf.Trim(Constants.CharArrays.ForwardSlash).Length == 0 && _mediaNavigationQueryService.TryGetRootKeys(out IEnumerable<Guid> rootKeys))
{
return mediaCache.GetAtRoot();
return rootKeys.Select(x => mediaCache.GetById(false, x)).WhereNotNull();
}
IPublishedContent? parent = Guid.TryParse(childrenOf, out Guid parentKey)

View File

@@ -27,39 +27,6 @@ public sealed class ContentCacheRefresher : PayloadCacheRefresherBase<ContentCac
private readonly IPublishStatusManagementService _publishStatusManagementService;
private readonly IIdKeyMap _idKeyMap;
[Obsolete("Use the constructor with ICacheManager instead, scheduled for removal in V17.")]
public ContentCacheRefresher(
AppCaches appCaches,
IJsonSerializer serializer,
IIdKeyMap idKeyMap,
IDomainService domainService,
IEventAggregator eventAggregator,
ICacheRefresherNotificationFactory factory,
IDocumentUrlService documentUrlService,
IDomainCacheService domainCacheService,
IDocumentNavigationQueryService documentNavigationQueryService,
IDocumentNavigationManagementService documentNavigationManagementService,
IContentService contentService,
IPublishStatusManagementService publishStatusManagementService,
IDocumentCacheService documentCacheService)
: this(
appCaches,
serializer,
idKeyMap,
domainService,
eventAggregator,
factory,
documentUrlService,
domainCacheService,
documentNavigationQueryService,
documentNavigationManagementService,
contentService,
publishStatusManagementService,
documentCacheService,
StaticServiceProvider.Instance.GetRequiredService<ICacheManager>())
{
}
public ContentCacheRefresher(
AppCaches appCaches,
IJsonSerializer serializer,

View File

@@ -22,31 +22,6 @@ public sealed class MediaCacheRefresher : PayloadCacheRefresherBase<MediaCacheRe
private readonly IMediaCacheService _mediaCacheService;
private readonly ICacheManager _cacheManager;
[Obsolete("Use the constructor with ICacheManager instead, scheduled for removal in V17.")]
public MediaCacheRefresher(
AppCaches appCaches,
IJsonSerializer serializer,
IIdKeyMap idKeyMap,
IEventAggregator eventAggregator,
ICacheRefresherNotificationFactory factory,
IMediaNavigationQueryService mediaNavigationQueryService,
IMediaNavigationManagementService mediaNavigationManagementService,
IMediaService mediaService,
IMediaCacheService mediaCacheService)
: this(
appCaches,
serializer,
idKeyMap,
eventAggregator,
factory,
mediaNavigationQueryService,
mediaNavigationManagementService,
mediaService,
mediaCacheService,
StaticServiceProvider.Instance.GetRequiredService<ICacheManager>())
{
}
public MediaCacheRefresher(
AppCaches appCaches,
IJsonSerializer serializer,

View File

@@ -1,6 +1,4 @@
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Models.DeliveryApi;
using Umbraco.Cms.Core.Models.DeliveryApi;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Extensions;
@@ -12,19 +10,6 @@ public abstract class ApiContentBuilderBase<T>
private readonly IApiContentNameProvider _apiContentNameProvider;
private readonly IOutputExpansionStrategyAccessor _outputExpansionStrategyAccessor;
[Obsolete("Please use the constructor that takes all parameters. Scheduled for removal in Umbraco 17.")]
protected ApiContentBuilderBase(
IApiContentNameProvider apiContentNameProvider,
IApiContentRouteBuilder apiContentRouteBuilder,
IOutputExpansionStrategyAccessor outputExpansionStrategyAccessor)
: this(
apiContentNameProvider,
apiContentRouteBuilder,
outputExpansionStrategyAccessor,
StaticServiceProvider.Instance.GetRequiredService<IVariationContextAccessor>())
{
}
protected ApiContentBuilderBase(
IApiContentNameProvider apiContentNameProvider,
IApiContentRouteBuilder apiContentRouteBuilder,

View File

@@ -1,7 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Editors;
@@ -17,17 +15,6 @@ public class DataValueReferenceFactoryCollection : BuilderCollectionBase<IDataVa
private readonly ILogger<DataValueReferenceFactoryCollection> _logger;
/// <summary>
/// Initializes a new instance of the <see cref="DataValueReferenceFactoryCollection" /> class.
/// </summary>
/// <param name="items">The items.</param>
[Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 17.")]
public DataValueReferenceFactoryCollection(Func<IEnumerable<IDataValueReferenceFactory>> items)
: this(
items,
StaticServiceProvider.Instance.GetRequiredService<ILogger<DataValueReferenceFactoryCollection>>())
{ }
/// <summary>
/// Initializes a new instance of the <see cref="DataValueReferenceFactoryCollection" /> class.
/// </summary>
@@ -159,17 +146,6 @@ public class DataValueReferenceFactoryCollection : BuilderCollectionBase<IDataVa
return result;
}
/// <summary>
/// Gets all relation type aliases that are automatically tracked.
/// </summary>
/// <param name="propertyEditors">The property editors.</param>
/// <returns>
/// All relation type aliases that are automatically tracked.
/// </returns>
[Obsolete("Use GetAllAutomaticRelationTypesAliases. This will be removed in Umbraco 15.")]
public ISet<string> GetAutomaticRelationTypesAliases(PropertyEditorCollection propertyEditors) =>
GetAllAutomaticRelationTypesAliases(propertyEditors);
public ISet<string> GetAllAutomaticRelationTypesAliases(PropertyEditorCollection propertyEditors)
{
// Always add default automatic relation types

View File

@@ -1,18 +0,0 @@
using Umbraco.Cms.Core.IO;
using Umbraco.Cms.Core.PropertyEditors.Validators;
using Umbraco.Cms.Core.Serialization;
using Umbraco.Cms.Core.Strings;
namespace Umbraco.Cms.Core.PropertyEditors;
[Obsolete("This is no longer used and has been migrated to an internal class within RadioButtonsPropertyEditor. Scheduled for removal in Umbraco 17.")]
public class RadioValueEditor : DataValueEditor
{
public RadioValueEditor(
IShortStringHelper shortStringHelper,
IJsonSerializer jsonSerializer,
IIOHelper ioHelper,
DataEditorAttribute attribute)
: base(shortStringHelper, jsonSerializer, ioHelper, attribute) =>
Validators.Add(new RadioValueValidator());
}

View File

@@ -14,15 +14,6 @@ public sealed class EmailValidator : IValueValidator
{
private readonly ILocalizedTextService _localizedTextService;
/// <summary>
/// Initializes a new instance of the <see cref="EmailValidator"/> class.
/// </summary>
[Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 17.")]
public EmailValidator()
: this(StaticServiceProvider.Instance.GetRequiredService<ILocalizedTextService>())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="EmailValidator"/> class.
/// </summary>

View File

@@ -14,15 +14,6 @@ public class MultipleValueValidator : IValueValidator
{
private readonly ILocalizedTextService _localizedTextService;
/// <summary>
/// Initializes a new instance of the <see cref="MultipleValueValidator"/> class.
/// </summary>
[Obsolete("Please use the constructor that takes all parameters. Scheduled for removal in Umbraco 17.")]
public MultipleValueValidator()
: this(StaticServiceProvider.Instance.GetRequiredService<ILocalizedTextService>())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="MultipleValueValidator"/> class.
/// </summary>

View File

@@ -1,35 +0,0 @@
using System.ComponentModel.DataAnnotations;
using Umbraco.Cms.Core.Models.Validation;
using Umbraco.Extensions;
namespace Umbraco.Cms.Core.PropertyEditors.Validators;
[Obsolete("This is no longer used and has been migrated to an internal class within RadioButtonsPropertyEditor. Scheduled for removal in Umbraco 17.")]
public class RadioValueValidator : IValueValidator
{
public IEnumerable<ValidationResult> Validate(object? value, string? valueType, object? dataTypeConfiguration,
PropertyValidationContext validationContext)
{
// don't validate if empty
if (value == null || value.ToString().IsNullOrWhiteSpace())
{
yield break;
}
if (dataTypeConfiguration is not ValueListConfiguration valueListConfiguration)
{
yield break;
}
if (value is not string valueAsString)
{
yield break;
}
if (valueListConfiguration.Items.Contains(valueAsString) is false)
{
yield return new ValidationResult(
$"The value {valueAsString} is not a part of the pre-values", ["items"]);
}
}
}

View File

@@ -25,16 +25,6 @@ public interface IPublishedCache
/// <remarks>The value of <paramref name="preview" /> overrides defaults.</remarks>
IPublishedContent? GetById(bool preview, Guid contentId);
/// <summary>
/// Gets a content identified by its Udi identifier.
/// </summary>
/// <param name="preview">A value indicating whether to consider unpublished content.</param>
/// <param name="contentId">The content Udi identifier.</param>
/// <returns>The content, or null.</returns>
/// <remarks>The value of <paramref name="preview" /> overrides defaults.</remarks>
[Obsolete] // FIXME: Remove when replacing nucache
IPublishedContent? GetById(bool preview, Udi contentId);
/// <summary>
/// Gets a content identified by its unique identifier.
/// </summary>
@@ -50,49 +40,4 @@ public interface IPublishedCache
/// <returns>The content, or null.</returns>
/// <remarks>Considers published or unpublished content depending on defaults.</remarks>
IPublishedContent? GetById(Guid contentId);
/// <summary>
/// Gets a content identified by its unique identifier.
/// </summary>
/// <param name="contentId">The content unique identifier.</param>
/// <returns>The content, or null.</returns>
/// <remarks>Considers published or unpublished content depending on defaults.</remarks>
[Obsolete] // FIXME: Remove when replacing nucache
IPublishedContent? GetById(Udi contentId);
/// <summary>
/// Gets contents at root.
/// </summary>
/// <param name="preview">A value indicating whether to consider unpublished content.</param>
/// <param name="culture">A culture.</param>
/// <returns>The contents.</returns>
/// <remarks>The value of <paramref name="preview" /> overrides defaults.</remarks>
[Obsolete("Scheduled for removal, use IDocumentNavigationQueryService instead in v17")]
IEnumerable<IPublishedContent> GetAtRoot(bool preview, string? culture = null);
/// <summary>
/// Gets contents at root.
/// </summary>
/// <param name="culture">A culture.</param>
/// <returns>The contents.</returns>
/// <remarks>Considers published or unpublished content depending on defaults.</remarks>
[Obsolete("Scheduled for removal, use IDocumentNavigationQueryService instead in v17")]
IEnumerable<IPublishedContent> GetAtRoot(string? culture = null);
/// <summary>
/// Gets a value indicating whether the cache contains published content.
/// </summary>
/// <param name="preview">A value indicating whether to consider unpublished content.</param>
/// <returns>A value indicating whether the cache contains published content.</returns>
/// <remarks>The value of <paramref name="preview" /> overrides defaults.</remarks>
[Obsolete("Scheduled for removal in v17")]
bool HasContent(bool preview);
/// <summary>
/// Gets a value indicating whether the cache contains published content.
/// </summary>
/// <returns>A value indicating whether the cache contains published content.</returns>
/// <remarks>Considers published or unpublished content depending on defaults.</remarks>
[Obsolete("Scheduled for removal in v17")]
bool HasContent();
}

View File

@@ -44,46 +44,6 @@ public interface IPublishedContentCache : IPublishedCache
/// <para>The value of <paramref name="preview" /> overrides defaults.</para>
/// </remarks>
[Obsolete]
IPublishedContent? GetByRoute(bool preview, string route, bool? hideTopLevelNode = null, string? culture = null);
/// <summary>
/// Gets content identified by a route.
/// </summary>
/// <param name="route">The route</param>
/// <param name="hideTopLevelNode">A value forcing the HideTopLevelNode setting.</param>
/// <param name="culture">The culture</param>
/// <returns>The content, or null.</returns>
/// <remarks>
/// <para>
/// A valid route is either a simple path eg <c>/foo/bar/nil</c> or a root node id and a path, eg
/// <c>123/foo/bar/nil</c>.
/// </para>
/// <para>
/// If
/// <paramref name="hideTopLevelNode" />
/// is <c>null</c> then the settings value is used.
/// </para>
/// <para>Considers published or unpublished content depending on defaults.</para>
/// </remarks>
[Obsolete]
IPublishedContent? GetByRoute(string route, bool? hideTopLevelNode = null, string? culture = null);
/// <summary>
/// Gets the route for a content identified by its unique identifier.
/// </summary>
/// <param name="preview">A value indicating whether to consider unpublished content.</param>
/// <param name="contentId">The content unique identifier.</param>
/// <param name="culture">The culture</param>
/// <returns>A special string formatted route path.</returns>
/// <remarks>
/// <para>
/// The resulting string is a special encoded route string that may contain the domain ID
/// for the current route. If a domain is present the string will be prefixed with the domain ID integer, example:
/// {domainId}/route-path-of-item
/// </para>
/// <para>The value of <paramref name="preview" /> overrides defaults.</para>
/// </remarks>
[Obsolete]
string? GetRouteById(bool preview, int contentId, string? culture = null);
/// <summary>

View File

@@ -24,21 +24,10 @@ public abstract class PublishedCacheBase : IPublishedCache
public IPublishedContent? GetById(Guid contentId)
=> GetById(PreviewDefault, contentId);
public abstract IPublishedContent? GetById(bool preview, Udi contentId);
public IPublishedContent? GetById(Udi contentId)
=> GetById(PreviewDefault, contentId);
public abstract bool HasById(bool preview, int contentId);
public bool HasById(int contentId)
=> HasById(PreviewDefault, contentId);
public abstract IEnumerable<IPublishedContent> GetAtRoot(bool preview, string? culture = null);
public IEnumerable<IPublishedContent> GetAtRoot(string? culture = null) => GetAtRoot(PreviewDefault, culture);
public abstract bool HasContent(bool preview);
public bool HasContent() => HasContent(PreviewDefault);
}

View File

@@ -15,28 +15,8 @@ namespace Umbraco.Cms.Core.PublishedCache;
//
public class PublishedElement : IPublishedElement
{
private readonly IPublishedProperty[] _propertiesArray;
[Obsolete("Please use the non-obsolete constructor. Will be removed in V17.")]
public PublishedElement(IPublishedContentType contentType, Guid key, Dictionary<string, object?> values, bool previewing)
: this(contentType, key, values, previewing, PropertyCacheLevel.None, null)
{
}
[Obsolete("Please use the non-obsolete constructor. Will be removed in V17.")]
public PublishedElement(IPublishedContentType contentType, Guid key, Dictionary<string, object?>? values, bool previewing, PropertyCacheLevel referenceCacheLevel, ICacheManager? cacheManager)
: this(
contentType,
key,
values,
previewing,
referenceCacheLevel,
StaticServiceProvider.Instance.GetRequiredService<IVariationContextAccessor>().VariationContext ?? new VariationContext(),
cacheManager)
{
}
// initializes a new instance of the PublishedElement class
// within the context of a published snapshot service (eg a published content property value)
public PublishedElement(IPublishedContentType contentType, Guid key, Dictionary<string, object?>? values, bool previewing, PropertyCacheLevel referenceCacheLevel, VariationContext variationContext, ICacheManager? cacheManager)

View File

@@ -10,6 +10,7 @@ namespace Umbraco.Cms.Core.Routing;
/// <remarks>
/// <para>Handles <c>/foo/bar</c> where <c>/foo/bar</c> is the nice URL of a document.</para>
/// </remarks>
[Obsolete("Scheduled for removal in Umbraco 18")]
public class ContentFinderByUrl : IContentFinder
{
private readonly ILogger<ContentFinderByUrl> _logger;
@@ -60,41 +61,5 @@ public class ContentFinderByUrl : IContentFinder
/// Tries to find an Umbraco document for a <c>PublishedRequest</c> and a route.
/// </summary>
/// <returns>The document node, or null.</returns>
protected IPublishedContent? FindContent(IPublishedRequestBuilder docreq, string route)
{
if (!UmbracoContextAccessor.TryGetUmbracoContext(out IUmbracoContext? umbracoContext))
{
return null;
}
if (docreq == null)
{
throw new ArgumentNullException(nameof(docreq));
}
if (_logger.IsEnabled(LogLevel.Debug))
{
_logger.LogDebug("Test route {Route}", route);
}
IPublishedContent? node =
umbracoContext.Content?.GetByRoute(umbracoContext.InPreviewMode, route, culture: docreq.Culture);
if (node != null)
{
docreq.SetPublishedContent(node);
if (_logger.IsEnabled(LogLevel.Debug))
{
_logger.LogDebug("Got content, id={NodeId}", node.Id);
}
}
else
{
if (_logger.IsEnabled(LogLevel.Debug))
{
_logger.LogDebug("No match.");
}
}
return node;
}
protected IPublishedContent? FindContent(IPublishedRequestBuilder docreq, string route) => null;
}

View File

@@ -3,6 +3,7 @@ using Microsoft.Extensions.Logging;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.Navigation;
using Umbraco.Cms.Core.Web;
using Umbraco.Extensions;
@@ -26,7 +27,6 @@ public class ContentFinderByUrlAlias : IContentFinder
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly IDocumentNavigationQueryService _documentNavigationQueryService;
private readonly IPublishedContentStatusFilteringService _publishedContentStatusFilteringService;
/// <summary>
/// Initializes a new instance of the <see cref="ContentFinderByUrlAlias" /> class.
/// </summary>
@@ -44,61 +44,6 @@ public class ContentFinderByUrlAlias : IContentFinder
_logger = logger;
}
[Obsolete("Please use tne non-obsolete constructor instead. Scheduled removal in v17")]
public ContentFinderByUrlAlias(
ILogger<ContentFinderByUrlAlias> logger,
IPublishedValueFallback publishedValueFallback,
IVariationContextAccessor variationContextAccessor,
IUmbracoContextAccessor umbracoContextAccessor,
IPublishedContentCache contentCache,
IDocumentNavigationQueryService documentNavigationQueryService,
IPublishStatusQueryService publishStatusQueryService,
IPublishedContentStatusFilteringService publishedContentStatusFilteringService)
: this(
logger,
publishedValueFallback,
umbracoContextAccessor,
documentNavigationQueryService,
publishedContentStatusFilteringService)
{
}
[Obsolete("Please use tne non-obsolete constructor instead. Scheduled removal in v17")]
public ContentFinderByUrlAlias(
ILogger<ContentFinderByUrlAlias> logger,
IPublishedValueFallback publishedValueFallback,
IVariationContextAccessor variationContextAccessor,
IUmbracoContextAccessor umbracoContextAccessor,
IPublishedContentCache contentCache,
IDocumentNavigationQueryService documentNavigationQueryService,
IPublishStatusQueryService publishStatusQueryService)
: this(
logger,
publishedValueFallback,
umbracoContextAccessor,
documentNavigationQueryService,
StaticServiceProvider.Instance.GetRequiredService<IPublishedContentStatusFilteringService>())
{
}
[Obsolete("Please use tne non-obsolete constructor instead. Scheduled removal in v17")]
public ContentFinderByUrlAlias(
ILogger<ContentFinderByUrlAlias> logger,
IPublishedValueFallback publishedValueFallback,
IVariationContextAccessor variationContextAccessor,
IUmbracoContextAccessor umbracoContextAccessor,
IPublishedContentCache contentCache,
IDocumentNavigationQueryService documentNavigationQueryService)
: this(
logger,
publishedValueFallback,
umbracoContextAccessor,
documentNavigationQueryService,
StaticServiceProvider.Instance.GetRequiredService<IPublishedContentStatusFilteringService>())
{
}
/// <summary>
/// Tries to find and assign an Umbraco document to a <c>PublishedRequest</c>.
/// </summary>
@@ -204,7 +149,12 @@ public class ContentFinderByUrlAlias : IContentFinder
if (cache is not null)
{
foreach (IPublishedContent rootContent in cache.GetAtRoot())
if (_documentNavigationQueryService.TryGetRootKeys(out IEnumerable<Guid> rootKeys) is false)
{
return null;
}
foreach (IPublishedContent rootContent in rootKeys.Select(x => cache.GetById(false, x)).WhereNotNull())
{
IPublishedContent? c = rootContent.DescendantsOrSelf(_documentNavigationQueryService, _publishedContentStatusFilteringService)
.FirstOrDefault(x => IsMatch(x, test1, test2));

View File

@@ -24,6 +24,7 @@ namespace Umbraco.Cms.Core.Routing;
/// </para>
/// <para>If successful, then the template of the document request is also assigned.</para>
/// </remarks>
[Obsolete("Scheduled for removal in Umbraco 18")]
public class ContentFinderByUrlAndTemplate : ContentFinderByUrl
{
private readonly IContentTypeService _contentTypeService;

View File

@@ -50,71 +50,6 @@ public class DefaultUrlProvider : IUrlProvider
requestSettings.OnChange(x => _requestSettings = x);
}
[Obsolete("Use the non-obsolete constructor. Scheduled for removal in V17.")]
public DefaultUrlProvider(
IOptionsMonitor<RequestHandlerSettings> requestSettings,
ILogger<DefaultUrlProvider> logger,
ISiteDomainMapper siteDomainMapper,
IUmbracoContextAccessor umbracoContextAccessor,
UriUtility uriUtility,
ILocalizationService localizationService,
IPublishedContentCache contentCache,
IDocumentNavigationQueryService navigationQueryService,
IPublishedContentStatusFilteringService publishedContentStatusFilteringService)
: this(
requestSettings,
logger,
siteDomainMapper,
umbracoContextAccessor,
uriUtility,
localizationService,
navigationQueryService,
publishedContentStatusFilteringService)
{
}
[Obsolete("Use the non-obsolete constructor. Scheduled for removal in V17.")]
public DefaultUrlProvider(
IOptionsMonitor<RequestHandlerSettings> requestSettings,
ILogger<DefaultUrlProvider> logger,
ISiteDomainMapper siteDomainMapper,
IUmbracoContextAccessor umbracoContextAccessor,
UriUtility uriUtility,
ILocalizationService localizationService,
IPublishedContentCache contentCache,
IDocumentNavigationQueryService navigationQueryService)
: this(
requestSettings,
logger,
siteDomainMapper,
umbracoContextAccessor,
uriUtility,
localizationService,
navigationQueryService,
StaticServiceProvider.Instance.GetRequiredService<IPublishedContentStatusFilteringService>())
{
}
[Obsolete("Use the non-obsolete constructor. Scheduled for removal in V17.")]
public DefaultUrlProvider(
IOptionsMonitor<RequestHandlerSettings> requestSettings,
ILogger<DefaultUrlProvider> logger,
ISiteDomainMapper siteDomainMapper,
IUmbracoContextAccessor umbracoContextAccessor,
UriUtility uriUtility,
ILocalizationService localizationService)
: this(
requestSettings,
logger,
siteDomainMapper,
umbracoContextAccessor,
uriUtility,
localizationService,
StaticServiceProvider.Instance.GetRequiredService<IDocumentNavigationQueryService>(),
StaticServiceProvider.Instance.GetRequiredService<IPublishedContentStatusFilteringService>())
{
}
#region GetOtherUrls
/// <summary>

View File

@@ -36,6 +36,7 @@ using Umbraco.Cms.Core.Scoping;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Serialization;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.Navigation;
using Umbraco.Cms.Core.Strings;
using Umbraco.Cms.Core.Templates;
using Umbraco.Cms.Core.Web;
@@ -206,7 +207,8 @@ public static partial class UmbracoBuilderExtensions
factory.GetRequiredService<IVariationContextAccessor>(),
factory.GetRequiredService<IExamineManager>(),
factory.GetRequiredService<IPublishedContentCache>(),
factory.GetRequiredService<IPublishedMediaCache>());
factory.GetRequiredService<IPublishedMediaCache>(),
factory.GetRequiredService<IDocumentNavigationQueryService>());
});
// register accessors for cultures

View File

@@ -2,9 +2,12 @@ using System.Collections;
using System.Globalization;
using Examine;
using Examine.Search;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Services.Navigation;
using Umbraco.Cms.Infrastructure.Examine;
using Umbraco.Extensions;
@@ -20,6 +23,7 @@ public class PublishedContentQuery : IPublishedContentQuery
private readonly IPublishedContentCache _publishedContent;
private readonly IPublishedMediaCache _publishedMediaCache;
private readonly IVariationContextAccessor _variationContextAccessor;
private readonly IDocumentNavigationQueryService _documentNavigationQueryService;
private static readonly HashSet<string> _returnedQueryFields =
new() { ExamineFieldNames.ItemIdFieldName, ExamineFieldNames.CategoryFieldName };
@@ -30,13 +34,33 @@ public class PublishedContentQuery : IPublishedContentQuery
IVariationContextAccessor variationContextAccessor,
IExamineManager examineManager,
IPublishedContentCache publishedContent,
IPublishedMediaCache publishedMediaCache)
IPublishedMediaCache publishedMediaCache,
IDocumentNavigationQueryService documentNavigationQueryService)
{
_variationContextAccessor = variationContextAccessor ??
throw new ArgumentNullException(nameof(variationContextAccessor));
_examineManager = examineManager ?? throw new ArgumentNullException(nameof(examineManager));
_publishedContent = publishedContent;
_publishedMediaCache = publishedMediaCache;
_documentNavigationQueryService = documentNavigationQueryService;
}
/// <summary>
/// Initializes a new instance of the <see cref="PublishedContentQuery" /> class.
/// </summary>
[Obsolete("Scheduled for removal in Umbraco 18")]
public PublishedContentQuery(
IVariationContextAccessor variationContextAccessor,
IExamineManager examineManager,
IPublishedContentCache publishedContent,
IPublishedMediaCache publishedMediaCache)
: this(
variationContextAccessor,
examineManager,
publishedContent,
publishedMediaCache,
StaticServiceProvider.Instance.GetRequiredService<IDocumentNavigationQueryService>())
{
}
#region Convert Helpers
@@ -212,8 +236,9 @@ public class PublishedContentQuery : IPublishedContentQuery
private IEnumerable<IPublishedContent> ItemsByIds(IPublishedCache? cache, IEnumerable<Guid> ids)
=> ids.Select(eachId => ItemById(eachId, cache)).WhereNotNull();
private static IEnumerable<IPublishedContent> ItemsAtRoot(IPublishedCache? cache)
=> cache?.GetAtRoot() ?? Array.Empty<IPublishedContent>();
private IEnumerable<IPublishedContent> ItemsAtRoot(IPublishedCache? cache)
=> _documentNavigationQueryService.TryGetRootKeys(out IEnumerable<Guid> rootKeys) is false ? []
: rootKeys.Select(x => cache?.GetById(false, x)).WhereNotNull();
#endregion

View File

@@ -1,10 +1,14 @@
using System.Globalization;
using Examine;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.Navigation;
using Umbraco.Cms.Core.Web;
using Umbraco.Cms.Infrastructure;
@@ -19,7 +23,10 @@ public class ContentFinderByConfigured404 : IContentLastChanceFinder
private readonly IExamineManager _examineManager;
private readonly ILogger<ContentFinderByConfigured404> _logger;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly IDocumentUrlService _documentUrlService;
private readonly IPublishedContentCache _publishedContentCache;
private readonly IVariationContextAccessor _variationContextAccessor;
private readonly IDocumentNavigationQueryService _documentNavigationQueryService;
private ContentSettings _contentSettings;
/// <summary>
@@ -31,7 +38,10 @@ public class ContentFinderByConfigured404 : IContentLastChanceFinder
IOptionsMonitor<ContentSettings> contentSettings,
IExamineManager examineManager,
IVariationContextAccessor variationContextAccessor,
IUmbracoContextAccessor umbracoContextAccessor)
IUmbracoContextAccessor umbracoContextAccessor,
IDocumentUrlService documentUrlService,
IPublishedContentCache publishedContentCache,
IDocumentNavigationQueryService documentNavigationQueryService)
{
_logger = logger;
_entityService = entityService;
@@ -39,10 +49,34 @@ public class ContentFinderByConfigured404 : IContentLastChanceFinder
_examineManager = examineManager;
_variationContextAccessor = variationContextAccessor;
_umbracoContextAccessor = umbracoContextAccessor;
_documentUrlService = documentUrlService;
_publishedContentCache = publishedContentCache;
_documentNavigationQueryService = documentNavigationQueryService;
contentSettings.OnChange(x => _contentSettings = x);
}
[Obsolete("Scheduled for removal in Umbraco 18")]
public ContentFinderByConfigured404(
ILogger<ContentFinderByConfigured404> logger,
IEntityService entityService,
IOptionsMonitor<ContentSettings> contentSettings,
IExamineManager examineManager,
IVariationContextAccessor variationContextAccessor,
IUmbracoContextAccessor umbracoContextAccessor)
: this(
logger,
entityService,
contentSettings,
examineManager,
variationContextAccessor,
umbracoContextAccessor,
StaticServiceProvider.Instance.GetRequiredService<IDocumentUrlService>(),
StaticServiceProvider.Instance.GetRequiredService<IPublishedContentCache>(),
StaticServiceProvider.Instance.GetRequiredService<IDocumentNavigationQueryService>())
{
}
/// <summary>
/// Tries to find and assign an Umbraco document to a <c>PublishedRequest</c>.
/// </summary>
@@ -77,8 +111,13 @@ public class ContentFinderByConfigured404 : IContentLastChanceFinder
while (pos > 1)
{
route = route.Substring(0, pos);
node = umbracoContext.Content?.GetByRoute(route, culture: frequest?.Culture);
if (node != null)
Guid? keyByRoute = _documentUrlService.GetDocumentKeyByRoute(route, frequest.Culture, null, false);
if (keyByRoute is not null)
{
node = _publishedContentCache.GetById(keyByRoute.Value);
}
if (node is not null)
{
break;
}
@@ -100,7 +139,7 @@ public class ContentFinderByConfigured404 : IContentLastChanceFinder
var error404 = NotFoundHandlerHelper.GetCurrentNotFoundPageId(
_contentSettings.Error404Collection.ToArray(),
_entityService,
new PublishedContentQuery(_variationContextAccessor, _examineManager, umbracoContext.Content!, umbracoContext.Media),
new PublishedContentQuery(_variationContextAccessor, _examineManager, umbracoContext.Content!, umbracoContext.Media, _documentNavigationQueryService),
errorCulture,
domainContentId);

View File

@@ -43,30 +43,6 @@ public sealed class DocumentCache : IPublishedContentCache
public IPublishedContent? GetById(Guid contentId) => GetByIdAsync(contentId).GetAwaiter().GetResult();
// TODO: These are all obsolete and should be removed
[Obsolete("Scheduled for removal in v17")]
public IPublishedContent? GetById(bool preview, Udi contentId)
{
if(contentId is not GuidUdi guidUdi)
{
throw new NotSupportedException("Only GuidUdi is supported");
}
return GetById(preview, guidUdi.Guid);
}
[Obsolete("Scheduled for removal in v17")]
public IPublishedContent? GetById(Udi contentId)
{
if(contentId is not GuidUdi guidUdi)
{
throw new NotSupportedException("Only GuidUdi is supported");
}
return GetById(guidUdi.Guid);
}
public IEnumerable<IPublishedContent> GetAtRoot(bool preview, string? culture = null)
{
_documentNavigationQueryService.TryGetRootKeys(out IEnumerable<Guid> rootKeys);
@@ -75,34 +51,6 @@ public sealed class DocumentCache : IPublishedContentCache
return culture is null ? rootContent : rootContent.Where(x => x.IsInvariantOrHasCulture(culture));
}
public IEnumerable<IPublishedContent> GetAtRoot(string? culture = null)
{
_documentNavigationQueryService.TryGetRootKeys(out IEnumerable<Guid> rootKeys);
IEnumerable<IPublishedContent> rootContent = rootKeys.Select(key => GetById(key)).WhereNotNull();
return culture is null ? rootContent : rootContent.Where(x => x.IsInvariantOrHasCulture(culture));
}
[Obsolete("Scheduled for removal in v17")]
public bool HasContent(bool preview) => HasContent();
[Obsolete("Scheduled for removal in v17")]
public bool HasContent() => _documentUrlService.HasAny();
[Obsolete("Use IPublishedUrlProvider.GetUrl instead, scheduled for removal in v17")]
public IPublishedContent? GetByRoute(bool preview, string route, bool? hideTopLevelNode = null, string? culture = null)
{
Guid? key = _documentUrlService.GetDocumentKeyByRoute(route, culture, null, preview);
return key is not null ? GetById(preview, key.Value) : null;
}
[Obsolete("Use IPublishedUrlProvider.GetUrl instead, scheduled for removal in v17")]
public IPublishedContent? GetByRoute(string route, bool? hideTopLevelNode = null, string? culture = null)
{
Guid? key = _documentUrlService.GetDocumentKeyByRoute(route, culture, null, false);
return key is not null ? GetById(key.Value) : null;
}
[Obsolete("Use IPublishedUrlProvider.GetUrl instead, scheduled for removal in v17")]
public string? GetRouteById(bool preview, int contentId, string? culture = null)
{

View File

@@ -33,29 +33,6 @@ public sealed class MediaCache : IPublishedMediaCache
public IPublishedContent? GetById(Guid contentId) => GetByIdAsync(contentId).GetAwaiter().GetResult();
[Obsolete("Scheduled for removal in v17")]
public IPublishedContent? GetById(bool preview, Udi contentId)
{
if(contentId is not GuidUdi guidUdi)
{
throw new NotSupportedException("Only GuidUdi is supported");
}
return GetById(preview, guidUdi.Guid);
}
[Obsolete("Scheduled for removal in v17")]
public IPublishedContent? GetById(Udi contentId)
{
if(contentId is not GuidUdi guidUdi)
{
throw new NotSupportedException("Only GuidUdi is supported");
}
return GetById(guidUdi.Guid);
}
public IEnumerable<IPublishedContent> GetAtRoot(bool preview, string? culture = null)
{
_mediaNavigationQueryService.TryGetRootKeys(out IEnumerable<Guid> rootKeys);
@@ -63,21 +40,4 @@ public sealed class MediaCache : IPublishedMediaCache
IEnumerable<IPublishedContent> rootContent = rootKeys.Select(key => GetById(preview, key)).WhereNotNull();
return culture is null ? rootContent : rootContent.Where(x => x.IsInvariantOrHasCulture(culture));
}
public IEnumerable<IPublishedContent> GetAtRoot(string? culture = null)
{
_mediaNavigationQueryService.TryGetRootKeys(out IEnumerable<Guid> rootKeys);
IEnumerable<IPublishedContent> rootContent = rootKeys.Select(key => GetById(key)).WhereNotNull();
return culture is null ? rootContent : rootContent.Where(x => x.IsInvariantOrHasCulture(culture));
}
[Obsolete("Media does not support preview, this method will be removed in future versions")]
public bool HasContent(bool preview) => HasContent();
public bool HasContent()
{
_mediaNavigationQueryService.TryGetRootKeys(out IEnumerable<Guid> rootKeys);
return rootKeys.Any();
}
}

View File

@@ -1,36 +1,44 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Web;
using Umbraco.Cms.Web.Website.Models;
using Umbraco.Extensions;
namespace Umbraco.Cms.Web.Website.Controllers;
public class RenderNoContentController : Controller
{
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly GlobalSettings _globalSettings;
private readonly IDocumentUrlService _urlService;
[ActivatorUtilitiesConstructor]
public RenderNoContentController(
IHostingEnvironment hostingEnvironment,
IOptionsSnapshot<GlobalSettings> globalSettings,
IDocumentUrlService urlService)
{
_hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
_globalSettings = globalSettings.Value ?? throw new ArgumentNullException(nameof(globalSettings));
_urlService = urlService;
}
[Obsolete("Scheduled for removal in Umbraco 18")]
public RenderNoContentController(
IUmbracoContextAccessor umbracoContextAccessor,
IHostingEnvironment hostingEnvironment,
IOptionsSnapshot<GlobalSettings> globalSettings)
: this(hostingEnvironment, globalSettings, StaticServiceProvider.Instance.GetRequiredService<IDocumentUrlService>())
{
_umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor));
_hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
_globalSettings = globalSettings.Value ?? throw new ArgumentNullException(nameof(globalSettings));
}
public ActionResult Index()
{
IUmbracoContext umbracoContext = _umbracoContextAccessor.GetRequiredUmbracoContext();
IPublishedContentCache? store = umbracoContext.Content;
if (store?.HasContent() ?? false)
if (_urlService.HasAny())
{
// If there is actually content, go to the root.
return Redirect("~/");

View File

@@ -59,7 +59,8 @@ public static partial class UmbracoBuilderExtensions
x.GetRequiredService<IControllerActionSearcher>(),
x.GetRequiredService<IPublicAccessRequestHandler>(),
x.GetRequiredService<IUmbracoVirtualPageRoute>(),
x.GetRequiredService<IOptionsMonitor<GlobalSettings>>()));
x.GetRequiredService<IOptionsMonitor<GlobalSettings>>(),
x.GetRequiredService<IDocumentUrlService>()));
builder.Services.AddSingleton<IControllerActionSearcher, ControllerActionSearcher>();
builder.Services.TryAddEnumerable(Singleton<MatcherPolicy, NotFoundSelectorPolicy>());
builder.Services.AddSingleton<IUmbracoVirtualPageRoute, UmbracoVirtualPageRoute>();

View File

@@ -5,9 +5,11 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Web;
@@ -45,6 +47,7 @@ public class UmbracoRouteValueTransformer : DynamicRouteValueTransformer
private readonly IRuntimeState _runtime;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly IUmbracoVirtualPageRoute _umbracoVirtualPageRoute;
private readonly IDocumentUrlService _urlService;
private GlobalSettings _globalSettings;
/// <summary>
@@ -61,7 +64,8 @@ public class UmbracoRouteValueTransformer : DynamicRouteValueTransformer
IControllerActionSearcher controllerActionSearcher,
IPublicAccessRequestHandler publicAccessRequestHandler,
IUmbracoVirtualPageRoute umbracoVirtualPageRoute,
IOptionsMonitor<GlobalSettings> globalSettings)
IOptionsMonitor<GlobalSettings> globalSettings,
IDocumentUrlService urlService)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_umbracoContextAccessor =
@@ -77,6 +81,39 @@ public class UmbracoRouteValueTransformer : DynamicRouteValueTransformer
_umbracoVirtualPageRoute = umbracoVirtualPageRoute;
_globalSettings = globalSettings.CurrentValue;
globalSettings.OnChange(x => _globalSettings = x);
_urlService = urlService;
}
/// <summary>
/// Initializes a new instance of the <see cref="UmbracoRouteValueTransformer" /> class.
/// </summary>
[Obsolete("Scheduled for removal in Umbraco 18")]
public UmbracoRouteValueTransformer(
ILogger<UmbracoRouteValueTransformer> logger,
IUmbracoContextAccessor umbracoContextAccessor,
IPublishedRouter publishedRouter,
IRuntimeState runtime,
IUmbracoRouteValuesFactory routeValuesFactory,
IRoutableDocumentFilter routableDocumentFilter,
IDataProtectionProvider dataProtectionProvider,
IControllerActionSearcher controllerActionSearcher,
IPublicAccessRequestHandler publicAccessRequestHandler,
IUmbracoVirtualPageRoute umbracoVirtualPageRoute,
IOptionsMonitor<GlobalSettings> globalSettings)
: this(
logger,
umbracoContextAccessor,
publishedRouter,
runtime,
routeValuesFactory,
routableDocumentFilter,
dataProtectionProvider,
controllerActionSearcher,
publicAccessRequestHandler,
umbracoVirtualPageRoute,
globalSettings,
StaticServiceProvider.Instance.GetRequiredService<IDocumentUrlService>())
{
}
/// <inheritdoc />
@@ -100,8 +137,7 @@ public class UmbracoRouteValueTransformer : DynamicRouteValueTransformer
}
// Check if there is no existing content and return the no content controller
// FIXME: This should be changed to route cache, so instead, if there are any routes, we know there is content.
if (!umbracoContext.Content?.HasContent() ?? false)
if (!_urlService?.HasAny() ?? false)
{
return new RouteValueDictionary
{

View File

@@ -3,11 +3,11 @@ using Examine.Lucene;
using Examine.Lucene.Directories;
using Examine.Lucene.Providers;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Services.Navigation;
using Umbraco.Cms.Infrastructure;
using Umbraco.Cms.Infrastructure.Examine;
using Umbraco.Cms.Tests.Common.Attributes;
@@ -80,7 +80,7 @@ internal sealed class PublishedContentQueryTests : ExamineBaseTest
var variationContext = new VariationContext();
var variationContextAccessor = Mock.Of<IVariationContextAccessor>(x => x.VariationContext == variationContext);
return new PublishedContentQuery(variationContextAccessor, examineManager.Object, contentCache.Object, Mock.Of<IPublishedMediaCache>());
return new PublishedContentQuery(variationContextAccessor, examineManager.Object, contentCache.Object, Mock.Of<IPublishedMediaCache>(), Mock.Of<IDocumentNavigationQueryService>());
}
[TestCase("fr-fr", ExpectedResult = "1, 3", Description = "Search Culture: fr-fr. Must return both fr-fr and invariant results")]

View File

@@ -43,7 +43,7 @@ public class ContentFinderByUrlAliasTests
var contentItem = rootContents[0];
Mock.Get(umbracoContextAccessor).Setup(x => x.TryGetUmbracoContext(out umbracoContext)).Returns(true);
Mock.Get(umbracoContext).Setup(x => x.Content).Returns(publishedContentCache);
Mock.Get(publishedContentCache).Setup(x => x.GetAtRoot(null)).Returns(rootContents);
Mock.Get(publishedContentCache).Setup(x => x.GetById(false, It.IsAny<Guid>())).Returns(contentItem);
Mock.Get(contentItem).Setup(x => x.Id).Returns(nodeMatch);
Mock.Get(contentItem).Setup(x => x.GetProperty(Constants.Conventions.Content.UrlAlias)).Returns(urlProperty);
Mock.Get(contentItem).Setup(x => x.ItemType).Returns(PublishedItemType.Content);

View File

@@ -112,20 +112,12 @@ public class ApiRichTextMarkupParserTests
.Returns<bool, Guid>((preview, key) => mockData[key].PublishedContent);
contentCacheMock.Setup(cc => cc.GetById(It.IsAny<Guid>()))
.Returns<Guid>(key => mockData[key].PublishedContent);
contentCacheMock.Setup(cc => cc.GetById(It.IsAny<bool>(), It.IsAny<Udi>()))
.Returns<bool, Udi>((preview, udi) => mockData[((GuidUdi)udi).Guid].PublishedContent);
contentCacheMock.Setup(cc => cc.GetById(It.IsAny<Udi>()))
.Returns<Udi>(udi => mockData[((GuidUdi)udi).Guid].PublishedContent);
var mediaCacheMock = new Mock<IPublishedMediaCache>();
mediaCacheMock.Setup(cc => cc.GetById(It.IsAny<bool>(), It.IsAny<Guid>()))
.Returns<bool, Guid>((preview, key) => mockData[key].PublishedContent);
mediaCacheMock.Setup(cc => cc.GetById(It.IsAny<Guid>()))
.Returns<Guid>(key => mockData[key].PublishedContent);
mediaCacheMock.Setup(cc => cc.GetById(It.IsAny<bool>(), It.IsAny<Udi>()))
.Returns<bool, Udi>((preview, udi) => mockData[((GuidUdi)udi).Guid].PublishedContent);
mediaCacheMock.Setup(cc => cc.GetById(It.IsAny<Udi>()))
.Returns<Udi>(udi => mockData[((GuidUdi)udi).Guid].PublishedContent);
_apiMediaUrlProvider = new Mock<IApiMediaUrlProvider>();
_apiMediaUrlProvider.Setup(mup => mup.GetUrl(It.IsAny<IPublishedContent>()))

View File

@@ -7,6 +7,7 @@ using NUnit.Framework;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.IO;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Web;
using Umbraco.Cms.Tests.Common;
using Umbraco.Cms.Web.Website.Controllers;
@@ -21,13 +22,13 @@ public class RenderNoContentControllerTests
[Test]
public void Redirects_To_Root_When_Content_Published()
{
var mockUmbracoContext = new Mock<IUmbracoContext>();
mockUmbracoContext.Setup(x => x.Content.HasContent()).Returns(true);
var mockUrlService = new Mock<IDocumentUrlService>();
mockUrlService.Setup(x => x.HasAny()).Returns(true);
var mockHostingEnvironment = new Mock<IHostingEnvironment>();
var controller = new RenderNoContentController(
new TestUmbracoContextAccessor(mockUmbracoContext.Object),
mockHostingEnvironment.Object,
new TestOptionsSnapshot<GlobalSettings>(new GlobalSettings()));
new TestOptionsSnapshot<GlobalSettings>(new GlobalSettings()),
mockUrlService.Object);
var result = controller.Index() as RedirectResult;
@@ -41,8 +42,8 @@ public class RenderNoContentControllerTests
const string umbracoPathSetting = Constants.System.DefaultUmbracoPath;
const string umbracoPath = "/umbraco";
const string viewPath = "~/config/splashes/NoNodes.cshtml";
var mockUmbracoContext = new Mock<IUmbracoContext>();
mockUmbracoContext.Setup(x => x.Content.HasContent()).Returns(false);
var mockUrlService = new Mock<IDocumentUrlService>();
mockUrlService.Setup(x => x.HasAny()).Returns(false);
var mockIOHelper = new Mock<IIOHelper>();
mockIOHelper.Setup(x => x.ResolveUrl(It.Is<string>(y => y == umbracoPathSetting))).Returns(umbracoPath);
var mockHostingEnvironment = new Mock<IHostingEnvironment>();
@@ -53,7 +54,7 @@ public class RenderNoContentControllerTests
{
NoNodesViewPath = viewPath,
});
var controller = new RenderNoContentController(new TestUmbracoContextAccessor(mockUmbracoContext.Object), mockHostingEnvironment.Object, globalSettings);
var controller = new RenderNoContentController(mockHostingEnvironment.Object, globalSettings, mockUrlService.Object);
var result = controller.Index() as ViewResult;
Assert.IsNotNull(result);

View File

@@ -1,5 +1,6 @@
using System.Reflection;
using System.Threading.Tasks;
using Lucene.Net.Search.Similarities;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Controllers;
@@ -38,15 +39,17 @@ public class UmbracoRouteValueTransformerTests
IUmbracoContextAccessor ctx,
IRoutableDocumentFilter filter = null,
IPublishedRouter router = null,
IUmbracoRouteValuesFactory routeValuesFactory = null)
=> GetTransformer(ctx, Mock.Of<IRuntimeState>(x => x.Level == RuntimeLevel.Run), filter, router, routeValuesFactory);
IUmbracoRouteValuesFactory routeValuesFactory = null,
IDocumentUrlService documentUrlService = null)
=> GetTransformer(ctx, Mock.Of<IRuntimeState>(x => x.Level == RuntimeLevel.Run), filter, router, routeValuesFactory, documentUrlService);
private UmbracoRouteValueTransformer GetTransformer(
IUmbracoContextAccessor ctx,
IRuntimeState state,
IRoutableDocumentFilter filter = null,
IPublishedRouter router = null,
IUmbracoRouteValuesFactory routeValuesFactory = null)
IUmbracoRouteValuesFactory routeValuesFactory = null,
IDocumentUrlService documentUrlService = null)
{
var publicAccessRequestHandler = new Mock<IPublicAccessRequestHandler>();
publicAccessRequestHandler.Setup(x =>
@@ -67,13 +70,14 @@ public class UmbracoRouteValueTransformerTests
Mock.Of<IControllerActionSearcher>(),
publicAccessRequestHandler.Object,
Mock.Of<IUmbracoVirtualPageRoute>(),
Mock.Of<IOptionsMonitor<GlobalSettings>>());
Mock.Of<IOptionsMonitor<GlobalSettings>>(),
documentUrlService ?? Mock.Of<IDocumentUrlService>(x => x.HasAny() == true));
return transformer;
}
private IUmbracoContext GetUmbracoContext(bool hasContent)
{
var publishedContent = Mock.Of<IPublishedContentCache>(x => x.HasContent() == hasContent);
var publishedContent = Mock.Of<IDocumentUrlService>(x => x.HasAny() == hasContent);
var uri = new Uri("http://example.com");
var umbracoContext = Mock.Of<IUmbracoContext>(x =>
@@ -142,7 +146,11 @@ public class UmbracoRouteValueTransformerTests
var umbracoContext = GetUmbracoContext(false);
var transformer = GetTransformerWithRunState(
Mock.Of<IUmbracoContextAccessor>(x => x.TryGetUmbracoContext(out umbracoContext)));
Mock.Of<IUmbracoContextAccessor>(x => x.TryGetUmbracoContext(out umbracoContext)),
null,
null,
null,
Mock.Of<IDocumentUrlService>(x => x.HasAny() == false));
var result = await transformer.TransformAsync(new DefaultHttpContext(), new RouteValueDictionary());
Assert.AreEqual(2, result.Count);