diff --git a/Directory.Packages.props b/Directory.Packages.props
index 8bedbf588a..5a8717576b 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -12,28 +12,28 @@
-
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -58,9 +58,9 @@
-
-
-
+
+
+
@@ -69,7 +69,7 @@
-
+
@@ -81,6 +81,8 @@
+
+
@@ -88,9 +90,9 @@
-
+
-
+
diff --git a/global.json b/global.json
index 9c2a135743..1ada742598 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "9.0.100-rc.1.24452.12",
+ "version": "9.0.100-rc.2.24474.11",
"rollForward": "latestFeature",
"allowPrerelease": true
}
diff --git a/src/Umbraco.Cms.Api.Common/DependencyInjection/UmbracoBuilderAuthExtensions.cs b/src/Umbraco.Cms.Api.Common/DependencyInjection/UmbracoBuilderAuthExtensions.cs
index f34fc2dde9..1558329746 100644
--- a/src/Umbraco.Cms.Api.Common/DependencyInjection/UmbracoBuilderAuthExtensions.cs
+++ b/src/Umbraco.Cms.Api.Common/DependencyInjection/UmbracoBuilderAuthExtensions.cs
@@ -41,7 +41,7 @@ public static class UmbracoBuilderAuthExtensions
.SetTokenEndpointUris(
Paths.MemberApi.TokenEndpoint.TrimStart(Constants.CharArrays.ForwardSlash),
Paths.BackOfficeApi.TokenEndpoint.TrimStart(Constants.CharArrays.ForwardSlash))
- .SetLogoutEndpointUris(
+ .SetEndSessionEndpointUris(
Paths.MemberApi.LogoutEndpoint.TrimStart(Constants.CharArrays.ForwardSlash),
Paths.BackOfficeApi.LogoutEndpoint.TrimStart(Constants.CharArrays.ForwardSlash))
.SetRevocationEndpointUris(
@@ -62,7 +62,7 @@ public static class UmbracoBuilderAuthExtensions
.UseAspNetCore()
.EnableAuthorizationEndpointPassthrough()
.EnableTokenEndpointPassthrough()
- .EnableLogoutEndpointPassthrough();
+ .EnableEndSessionEndpointPassthrough();
// Enable reference tokens
// - see https://documentation.openiddict.com/configuration/token-storage.html
diff --git a/src/Umbraco.Cms.Api.Delivery/Security/MemberApplicationManager.cs b/src/Umbraco.Cms.Api.Delivery/Security/MemberApplicationManager.cs
index 67cfb4b7cf..9cfd7b78e1 100644
--- a/src/Umbraco.Cms.Api.Delivery/Security/MemberApplicationManager.cs
+++ b/src/Umbraco.Cms.Api.Delivery/Security/MemberApplicationManager.cs
@@ -41,7 +41,7 @@ public class MemberApplicationManager : OpenIdDictApplicationManagerBase, IMembe
{
OpenIddictConstants.Permissions.Endpoints.Authorization,
OpenIddictConstants.Permissions.Endpoints.Token,
- OpenIddictConstants.Permissions.Endpoints.Logout,
+ OpenIddictConstants.Permissions.Endpoints.EndSession,
OpenIddictConstants.Permissions.Endpoints.Revocation,
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode,
OpenIddictConstants.Permissions.GrantTypes.RefreshToken,
diff --git a/src/Umbraco.Cms.Api.Management/Security/BackOfficeApplicationManager.cs b/src/Umbraco.Cms.Api.Management/Security/BackOfficeApplicationManager.cs
index 36fe1b0acc..cbf0fcd8ad 100644
--- a/src/Umbraco.Cms.Api.Management/Security/BackOfficeApplicationManager.cs
+++ b/src/Umbraco.Cms.Api.Management/Security/BackOfficeApplicationManager.cs
@@ -132,7 +132,7 @@ public class BackOfficeApplicationManager : OpenIdDictApplicationManagerBase, IB
{
OpenIddictConstants.Permissions.Endpoints.Authorization,
OpenIddictConstants.Permissions.Endpoints.Token,
- OpenIddictConstants.Permissions.Endpoints.Logout,
+ OpenIddictConstants.Permissions.Endpoints.EndSession,
OpenIddictConstants.Permissions.Endpoints.Revocation,
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode,
OpenIddictConstants.Permissions.GrantTypes.RefreshToken,
diff --git a/src/Umbraco.Cms.Persistence.EFCore.SqlServer/Umbraco.Cms.Persistence.EFCore.SqlServer.csproj b/src/Umbraco.Cms.Persistence.EFCore.SqlServer/Umbraco.Cms.Persistence.EFCore.SqlServer.csproj
index a1864f636f..264cf02579 100644
--- a/src/Umbraco.Cms.Persistence.EFCore.SqlServer/Umbraco.Cms.Persistence.EFCore.SqlServer.csproj
+++ b/src/Umbraco.Cms.Persistence.EFCore.SqlServer/Umbraco.Cms.Persistence.EFCore.SqlServer.csproj
@@ -6,8 +6,12 @@
+
+
+
+
diff --git a/src/Umbraco.Cms.Persistence.EFCore/Umbraco.Cms.Persistence.EFCore.csproj b/src/Umbraco.Cms.Persistence.EFCore/Umbraco.Cms.Persistence.EFCore.csproj
index e9d05b5633..bbf03ea87a 100644
--- a/src/Umbraco.Cms.Persistence.EFCore/Umbraco.Cms.Persistence.EFCore.csproj
+++ b/src/Umbraco.Cms.Persistence.EFCore/Umbraco.Cms.Persistence.EFCore.csproj
@@ -16,6 +16,8 @@
+
+
diff --git a/src/Umbraco.Cms.Persistence.SqlServer/Umbraco.Cms.Persistence.SqlServer.csproj b/src/Umbraco.Cms.Persistence.SqlServer/Umbraco.Cms.Persistence.SqlServer.csproj
index d5edbbee4c..3868136baa 100644
--- a/src/Umbraco.Cms.Persistence.SqlServer/Umbraco.Cms.Persistence.SqlServer.csproj
+++ b/src/Umbraco.Cms.Persistence.SqlServer/Umbraco.Cms.Persistence.SqlServer.csproj
@@ -18,7 +18,8 @@
-
+
+
diff --git a/src/Umbraco.Cms.StaticAssets/umbraco/UmbracoLogin/Index.cshtml b/src/Umbraco.Cms.StaticAssets/umbraco/UmbracoLogin/Index.cshtml
index 716521066c..856796cd25 100644
--- a/src/Umbraco.Cms.StaticAssets/umbraco/UmbracoLogin/Index.cshtml
+++ b/src/Umbraco.Cms.StaticAssets/umbraco/UmbracoLogin/Index.cshtml
@@ -31,6 +31,7 @@
var allowPasswordReset = SecuritySettings.Value.AllowPasswordReset && EmailSender.CanSendRequiredEmail();
var disableLocalLogin = ExternalLogins.HasDenyLocalLogin();
}
+@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@@ -44,7 +45,7 @@
Umbraco
-
+
@await Html.BackOfficeImportMapScriptAsync(JsonSerializer, BackOfficePathGenerator, PackageManifestService)
-
+
diff --git a/src/Umbraco.Core/Cache/Refreshers/Implement/ContentTypeCacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/Implement/ContentTypeCacheRefresher.cs
index dba66ec1b0..f9936933cc 100644
--- a/src/Umbraco.Core/Cache/Refreshers/Implement/ContentTypeCacheRefresher.cs
+++ b/src/Umbraco.Core/Cache/Refreshers/Implement/ContentTypeCacheRefresher.cs
@@ -14,6 +14,7 @@ public sealed class ContentTypeCacheRefresher : PayloadCacheRefresherBase { });
+ _publishedContentTypeFactory.NotifyDataTypeChanges();
+
// now we can trigger the event
base.Refresh(payloads);
}
diff --git a/src/Umbraco.Core/Cache/Refreshers/Implement/DataTypeCacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/Implement/DataTypeCacheRefresher.cs
index f28dd89ea5..de25660fa0 100644
--- a/src/Umbraco.Core/Cache/Refreshers/Implement/DataTypeCacheRefresher.cs
+++ b/src/Umbraco.Core/Cache/Refreshers/Implement/DataTypeCacheRefresher.cs
@@ -13,6 +13,7 @@ public sealed class DataTypeCacheRefresher : PayloadCacheRefresherBase { });
+ var changedIds = payloads.Select(x => x.Id).ToArray();
+ _publishedContentTypeFactory.NotifyDataTypeChanges(changedIds);
+
base.Refresh(payloads);
}
diff --git a/src/Umbraco.Core/Extensions/PublishedContentExtensions.cs b/src/Umbraco.Core/Extensions/PublishedContentExtensions.cs
index 7dde30fb98..7d9f66052f 100644
--- a/src/Umbraco.Core/Extensions/PublishedContentExtensions.cs
+++ b/src/Umbraco.Core/Extensions/PublishedContentExtensions.cs
@@ -2,7 +2,9 @@
// See LICENSE for more details.
using System.Data;
+using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.Configuration.Models;
+using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Membership;
using Umbraco.Cms.Core.Models.PublishedContent;
@@ -1909,5 +1911,491 @@ public static class PublishedContentExtensions
private static Dictionary GetAliasesAndNames(IContentTypeBase? contentType) =>
contentType?.PropertyTypes.ToDictionary(x => x.Alias, x => x.Name) ?? new Dictionary();
+
+
#endregion
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IPublishedContent? Ancestor(this IPublishedContent content, int maxLevel)
+ {
+ return content.Ancestor(GetPublishedCache(content), GetNavigationQueryService(content), maxLevel);
+ }
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IPublishedContent? Ancestor(this IPublishedContent content, string contentTypeAlias)
+ {
+ return content.Ancestor(GetPublishedCache(content), GetNavigationQueryService(content), contentTypeAlias);
+ }
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static T? Ancestor(this IPublishedContent content, int maxLevel)
+ where T : class, IPublishedContent
+ {
+ return Ancestor(content, GetPublishedCache(content), GetNavigationQueryService(content), maxLevel);
+ }
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable Ancestors(this IPublishedContent content, int maxLevel)
+ {
+ return content.Ancestors(GetPublishedCache(content), GetNavigationQueryService(content), maxLevel);
+ }
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable Ancestors(this IPublishedContent content, string contentTypeAlias)
+ {
+ return content.Ancestors(GetPublishedCache(content), GetNavigationQueryService(content), contentTypeAlias);
+ }
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable Ancestors(this IPublishedContent content)
+ where T : class, IPublishedContent
+ {
+ return Ancestors(content, GetPublishedCache(content), GetNavigationQueryService(content));
+ }
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable Ancestors(this IPublishedContent content, int maxLevel)
+ where T : class, IPublishedContent
+ {
+ return Ancestors(content, GetPublishedCache(content), GetNavigationQueryService(content), maxLevel);
+ }
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IPublishedContent AncestorOrSelf(this IPublishedContent content, int maxLevel)
+ {
+ return AncestorOrSelf(content, GetPublishedCache(content), GetNavigationQueryService(content), maxLevel);
+ }
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IPublishedContent AncestorOrSelf(this IPublishedContent content, string contentTypeAlias)
+ {
+ return AncestorOrSelf(content, GetPublishedCache(content), GetNavigationQueryService(content), contentTypeAlias);
+ }
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static T? AncestorOrSelf(this IPublishedContent content, int maxLevel)
+ where T : class, IPublishedContent
+ {
+ return AncestorOrSelf(content, GetPublishedCache(content), GetNavigationQueryService(content), maxLevel);
+ }
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable AncestorsOrSelf(this IPublishedContent content, int maxLevel)
+ {
+ return content.AncestorsOrSelf(GetPublishedCache(content), GetNavigationQueryService(content), maxLevel);
+ }
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable AncestorsOrSelf(this IPublishedContent content, string contentTypeAlias)
+ {
+ return content.Ancestors(GetPublishedCache(content), GetNavigationQueryService(content), contentTypeAlias);
+ }
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable AncestorsOrSelf(this IPublishedContent content, int maxLevel)
+ where T : class, IPublishedContent
+ {
+ return AncestorsOrSelf(content, GetPublishedCache(content), GetNavigationQueryService(content), maxLevel);
+ }
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable AncestorsOrSelf(this IPublishedContent content, bool orSelf,
+ Func? func)
+ {
+ return AncestorsOrSelf(content, GetPublishedCache(content), GetNavigationQueryService(content), orSelf, func);
+ }
+
+ [Obsolete(
+ "Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable Breadcrumbs(
+ this IPublishedContent content,
+ bool andSelf = true) =>
+ content.Breadcrumbs(GetPublishedCache(content), GetNavigationQueryService(content), andSelf);
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable Breadcrumbs(
+ this IPublishedContent content,
+ int minLevel,
+ bool andSelf = true) =>
+ content.Breadcrumbs(GetPublishedCache(content), GetNavigationQueryService(content), minLevel, andSelf);
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable Breadcrumbs(
+ this IPublishedContent content,
+ bool andSelf = true)
+ where T : class, IPublishedContent=>
+ content.Breadcrumbs(GetPublishedCache(content), GetNavigationQueryService(content), andSelf);
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable Children(
+ this IPublishedContent content,
+ IVariationContextAccessor? variationContextAccessor,
+ string? culture = null)
+ => Children(content, variationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture);
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable Children(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ Func predicate,
+ string? culture = null) =>
+ content.Children(variationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture).Where(predicate);
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable ChildrenOfType(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string? contentTypeAlias,
+ string? culture = null) =>
+ content.Children(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), x => x.ContentType.Alias.InvariantEquals(contentTypeAlias),
+ culture);
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable Children(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string? culture = null)
+ where T : class, IPublishedContent =>
+ content.Children(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), culture).OfType();
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static DataTable ChildrenAsTable(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ IContentTypeService contentTypeService,
+ IMediaTypeService mediaTypeService,
+ IMemberTypeService memberTypeService,
+ IPublishedUrlProvider publishedUrlProvider,
+ string contentTypeAliasFilter = "",
+ string? culture = null)
+ => GenerateDataTable(content, variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), contentTypeService, mediaTypeService, memberTypeService, publishedUrlProvider, contentTypeAliasFilter, culture);
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable DescendantsOrSelfOfType(
+ this IEnumerable parentNodes,
+ IVariationContextAccessor variationContextAccessor,
+ string docTypeAlias,
+ string? culture = null) => parentNodes.SelectMany(x =>
+ x.DescendantsOrSelfOfType(variationContextAccessor, GetPublishedCache(parentNodes.First()),
+ GetNavigationQueryService(parentNodes.First()), docTypeAlias, culture));
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable DescendantsOrSelf(
+ this IEnumerable parentNodes,
+ IVariationContextAccessor variationContextAccessor,
+ string? culture = null)
+ where T : class, IPublishedContent =>
+ parentNodes.SelectMany(x => x.DescendantsOrSelf(variationContextAccessor, GetPublishedCache(parentNodes.First()),
+ GetNavigationQueryService(parentNodes.First()), culture));
+
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable Descendants(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string? culture = null) =>
+ content.DescendantsOrSelf(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), false, null, culture);
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable Descendants(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ int level,
+ string? culture = null) =>
+ content.DescendantsOrSelf(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), false, p => p.Level >= level, culture);
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable DescendantsOfType(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string contentTypeAlias, string? culture = null) =>
+ content.DescendantsOrSelf(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), false, p => p.ContentType.Alias.InvariantEquals(contentTypeAlias), culture);
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable Descendants(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string? culture = null)
+ where T : class, IPublishedContent =>
+ content.Descendants(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), culture).OfType();
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable Descendants(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ int level,
+ string? culture = null)
+ where T : class, IPublishedContent =>
+ content.Descendants(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), level, culture).OfType();
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable DescendantsOrSelf(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string? culture = null) =>
+ content.DescendantsOrSelf(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), true, null, culture);
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable DescendantsOrSelf(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ int level,
+ string? culture = null) =>
+ content.DescendantsOrSelf(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), true, p => p.Level >= level, culture);
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable DescendantsOrSelfOfType(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string contentTypeAlias,
+ string? culture = null) =>
+ content.DescendantsOrSelf(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), true, p => p.ContentType.Alias.InvariantEquals(contentTypeAlias), culture);
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable DescendantsOrSelf(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string? culture = null)
+ where T : class, IPublishedContent =>
+ content.DescendantsOrSelf(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), culture).OfType();
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable DescendantsOrSelf(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ int level,
+ string? culture = null)
+ where T : class, IPublishedContent =>
+ content.DescendantsOrSelf(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), level, culture).OfType();
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IPublishedContent? Descendant(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string? culture = null) =>
+ content.Children(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), culture)?.FirstOrDefault();
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IPublishedContent? Descendant(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ int level,
+ string? culture = null) => content
+ .EnumerateDescendants(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), false, culture).FirstOrDefault(x => x.Level == level);
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IPublishedContent? DescendantOfType(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string contentTypeAlias,
+ string? culture = null) => content
+ .EnumerateDescendants(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), false, culture)
+ .FirstOrDefault(x => x.ContentType.Alias.InvariantEquals(contentTypeAlias));
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static T? Descendant(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string? culture = null)
+ where T : class, IPublishedContent =>
+ content.EnumerateDescendants(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), false, culture).FirstOrDefault(x => x is T) as T;
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static T? Descendant(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ int level,
+ string? culture = null)
+ where T : class, IPublishedContent =>
+ content.Descendant(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), level, culture) as T;
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IPublishedContent? DescendantOrSelf(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ int level,
+ string? culture = null) => content
+ .EnumerateDescendants(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), true, culture).FirstOrDefault(x => x.Level == level);
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IPublishedContent? DescendantOrSelfOfType(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string contentTypeAlias,
+ string? culture = null) => content
+ .EnumerateDescendants(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), true, culture)
+ .FirstOrDefault(x => x.ContentType.Alias.InvariantEquals(contentTypeAlias));
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static T? DescendantOrSelf(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string? culture = null)
+ where T : class, IPublishedContent =>
+ content.EnumerateDescendants(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), true, culture).FirstOrDefault(x => x is T) as T;
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static T? DescendantOrSelf(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ int level,
+ string? culture = null)
+ where T : class, IPublishedContent =>
+ content.DescendantOrSelf(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), level, culture) as T;
+
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IPublishedContent? FirstChild(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string? culture = null) =>
+ content.Children(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), culture)?.FirstOrDefault();
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IPublishedContent? FirstChildOfType(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string contentTypeAlias,
+ string? culture = null) =>
+ content.ChildrenOfType(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), contentTypeAlias, culture)?.FirstOrDefault();
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IPublishedContent? FirstChild(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ Func predicate,
+ string? culture = null)
+ => content.Children(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), predicate, culture)?.FirstOrDefault();
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IPublishedContent? FirstChild(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ Guid uniqueId,
+ string? culture = null) => content
+ .Children(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), x => x.Key == uniqueId, culture)?.FirstOrDefault();
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static T? FirstChild(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string? culture = null)
+ where T : class, IPublishedContent =>
+ content.Children(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), culture)?.FirstOrDefault();
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static T? FirstChild(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ Func predicate,
+ string? culture = null)
+ where T : class, IPublishedContent =>
+ content.Children(variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), culture)?.FirstOrDefault(predicate);
+
+ [Obsolete(
+ "Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable Siblings(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string? culture = null) =>
+ Siblings(content, GetPublishedCache(content), GetNavigationQueryService(content), variationContextAccessor, culture);
+
+ [Obsolete(
+ "Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable SiblingsOfType(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string contentTypeAlias,
+ string? culture = null) =>
+ SiblingsOfType(content, variationContextAccessor,
+ GetPublishedCache(content), GetNavigationQueryService(content), contentTypeAlias, culture);
+
+ [Obsolete(
+ "Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable Siblings(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string? culture = null)
+ where T : class, IPublishedContent =>
+ Siblings(content, variationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture);
+
+ [Obsolete(
+ "Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable? SiblingsAndSelf(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string? culture = null) => SiblingsAndSelf(content, GetPublishedCache(content), GetNavigationQueryService(content), variationContextAccessor, culture);
+
+ [Obsolete(
+ "Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable SiblingsAndSelfOfType(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string contentTypeAlias,
+ string? culture = null) => SiblingsAndSelfOfType(content, variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), contentTypeAlias, culture);
+
+ [Obsolete("Please use IPublishedCache and IDocumentNavigationQueryService or IMediaNavigationQueryService directly. This will be removed in a future version of Umbraco")]
+ public static IEnumerable SiblingsAndSelf(
+ this IPublishedContent content,
+ IVariationContextAccessor variationContextAccessor,
+ string? culture = null)
+ where T : class, IPublishedContent => SiblingsAndSelf(content, variationContextAccessor, GetPublishedCache(content),
+ GetNavigationQueryService(content), culture);
+
+
+ private static INavigationQueryService GetNavigationQueryService(IPublishedContent content)
+ {
+ switch (content.ContentType.ItemType)
+ {
+ case PublishedItemType.Content:
+ return StaticServiceProvider.Instance.GetRequiredService();
+ case PublishedItemType.Media:
+ return StaticServiceProvider.Instance.GetRequiredService();
+ default:
+ throw new NotSupportedException("Unsupported content type.");
+ }
+
+ }
+
+ private static IPublishedCache GetPublishedCache(IPublishedContent content)
+ {
+ switch (content.ContentType.ItemType)
+ {
+ case PublishedItemType.Content:
+ return StaticServiceProvider.Instance.GetRequiredService();
+ case PublishedItemType.Media:
+ return StaticServiceProvider.Instance.GetRequiredService();
+ default:
+ throw new NotSupportedException("Unsupported content type.");
+ }
+ }
}
diff --git a/src/Umbraco.Core/PublishedCache/IPublishedContentCache.cs b/src/Umbraco.Core/PublishedCache/IPublishedContentCache.cs
index 8353225f10..8230b0f306 100644
--- a/src/Umbraco.Core/PublishedCache/IPublishedContentCache.cs
+++ b/src/Umbraco.Core/PublishedCache/IPublishedContentCache.cs
@@ -11,7 +11,7 @@ public interface IPublishedContentCache : IPublishedCache
/// A value indicating whether to consider unpublished content.
/// The content, or null.
/// Considers published or unpublished content depending on defaults.
- Task GetByIdAsync(int id, bool preview = false);
+ Task GetByIdAsync(int id, bool? preview = null);
///
/// Gets a content identified by its unique identifier.
@@ -20,7 +20,7 @@ public interface IPublishedContentCache : IPublishedCache
/// A value indicating whether to consider unpublished content.
/// The content, or null.
/// Considers published or unpublished content depending on defaults.
- Task GetByIdAsync(Guid key, bool preview = false);
+ Task GetByIdAsync(Guid key, bool? preview = null);
// FIXME: All these routing methods needs to be removed, as they are no longer part of the content cache
///
diff --git a/src/Umbraco.Core/Services/EntityTypeContainerService.cs b/src/Umbraco.Core/Services/EntityTypeContainerService.cs
index 9263d07530..962d853ce8 100644
--- a/src/Umbraco.Core/Services/EntityTypeContainerService.cs
+++ b/src/Umbraco.Core/Services/EntityTypeContainerService.cs
@@ -50,6 +50,22 @@ internal abstract class EntityTypeContainerService
+ public async Task> GetAsync(string name, int level)
+ {
+ using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true);
+ ReadLock(scope);
+ return await Task.FromResult(_entityContainerRepository.Get(name, level));
+ }
+ ///
+ public async Task> GetAllAsync()
+ {
+ using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true);
+ ReadLock(scope);
+ return await Task.FromResult(_entityContainerRepository.GetMany());
+ }
+
///
public async Task GetParentAsync(EntityContainer container)
=> await Task.FromResult(GetParent(container));
diff --git a/src/Umbraco.Core/Services/IEntityTypeContainerService.cs b/src/Umbraco.Core/Services/IEntityTypeContainerService.cs
index e58e322304..831eb4b2e4 100644
--- a/src/Umbraco.Core/Services/IEntityTypeContainerService.cs
+++ b/src/Umbraco.Core/Services/IEntityTypeContainerService.cs
@@ -14,6 +14,20 @@ public interface IEntityTypeContainerService
///
Task GetAsync(Guid id);
+ ///
+ /// Gets containers by name and level
+ ///
+ /// The name of the containers to get.
+ /// The level in the tree of the containers to get.
+ ///
+ Task> GetAsync(string name, int level);
+
+ ///
+ /// Gets all containers
+ ///
+ ///
+ Task> GetAllAsync();
+
///
/// Gets the parent container of a container
///
diff --git a/src/Umbraco.Core/Services/IPreviewService.cs b/src/Umbraco.Core/Services/IPreviewService.cs
index c9e276d83e..c65dbe16bb 100644
--- a/src/Umbraco.Core/Services/IPreviewService.cs
+++ b/src/Umbraco.Core/Services/IPreviewService.cs
@@ -15,5 +15,7 @@ public interface IPreviewService
///
Task EndPreviewAsync();
+ bool IsInPreview();
+
Task> TryGetPreviewClaimsIdentityAsync();
}
diff --git a/src/Umbraco.Core/Services/PreviewService.cs b/src/Umbraco.Core/Services/PreviewService.cs
index bc11ab53bf..c487d4d407 100644
--- a/src/Umbraco.Core/Services/PreviewService.cs
+++ b/src/Umbraco.Core/Services/PreviewService.cs
@@ -1,5 +1,6 @@
using System.Security.Claims;
using Microsoft.Extensions.DependencyInjection;
+using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Models.Membership;
using Umbraco.Cms.Core.Preview;
using Umbraco.Cms.Core.Security;
@@ -13,15 +14,18 @@ public class PreviewService : IPreviewService
private readonly ICookieManager _cookieManager;
private readonly IPreviewTokenGenerator _previewTokenGenerator;
private readonly IServiceScopeFactory _serviceScopeFactory;
+ private readonly IRequestCache _requestCache;
public PreviewService(
ICookieManager cookieManager,
IPreviewTokenGenerator previewTokenGenerator,
- IServiceScopeFactory serviceScopeFactory)
+ IServiceScopeFactory serviceScopeFactory,
+ IRequestCache requestCache)
{
_cookieManager = cookieManager;
_previewTokenGenerator = previewTokenGenerator;
_serviceScopeFactory = serviceScopeFactory;
+ _requestCache = requestCache;
}
public async Task TryEnterPreviewAsync(IUser user)
@@ -42,6 +46,11 @@ public class PreviewService : IPreviewService
return Task.CompletedTask;
}
+ public bool IsInPreview() =>
+ _requestCache.Get(
+ "IsInPreview",
+ () => TryGetPreviewClaimsIdentityAsync().GetAwaiter().GetResult().Success) as bool? ?? false;
+
public async Task> TryGetPreviewClaimsIdentityAsync()
{
var cookieValue = _cookieManager.GetCookieValue(Constants.Web.PreviewCookieName);
diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_15_0_0/AddDocumentUrl.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_15_0_0/AddDocumentUrl.cs
index d1b70f034e..0fc6c3ba11 100644
--- a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_15_0_0/AddDocumentUrl.cs
+++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_15_0_0/AddDocumentUrl.cs
@@ -1,4 +1,5 @@
-using Umbraco.Cms.Infrastructure.Persistence.Dtos;
+using Umbraco.Cms.Core;
+using Umbraco.Cms.Infrastructure.Persistence.Dtos;
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_15_0_0;
@@ -11,5 +12,10 @@ public class AddDocumentUrl : MigrationBase
}
protected override void Migrate()
- => Create.Table().Do();
+ {
+ if (TableExists(Constants.DatabaseSchema.Tables.DocumentUrl) is false)
+ {
+ Create.Table().Do();
+ }
+ }
}
diff --git a/src/Umbraco.PublishedCache.HybridCache/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.PublishedCache.HybridCache/DependencyInjection/UmbracoBuilderExtensions.cs
index c8e93b6351..191927ba37 100644
--- a/src/Umbraco.PublishedCache.HybridCache/DependencyInjection/UmbracoBuilderExtensions.cs
+++ b/src/Umbraco.PublishedCache.HybridCache/DependencyInjection/UmbracoBuilderExtensions.cs
@@ -29,7 +29,9 @@ public static class UmbracoBuilderExtensions
///
public static IUmbracoBuilder AddUmbracoHybridCache(this IUmbracoBuilder builder)
{
+#pragma warning disable EXTEXP0018
builder.Services.AddHybridCache();
+#pragma warning restore EXTEXP0018
builder.Services.AddSingleton();
builder.Services.AddSingleton();
builder.Services.AddSingleton();
diff --git a/src/Umbraco.PublishedCache.HybridCache/DocumentCache.cs b/src/Umbraco.PublishedCache.HybridCache/DocumentCache.cs
index d978919a65..9be78a9ea2 100644
--- a/src/Umbraco.PublishedCache.HybridCache/DocumentCache.cs
+++ b/src/Umbraco.PublishedCache.HybridCache/DocumentCache.cs
@@ -21,19 +21,19 @@ public sealed class DocumentCache : IPublishedContentCache
_publishedContentTypeCache = publishedContentTypeCache;
}
- public async Task GetByIdAsync(int id, bool preview = false) => await _documentCacheService.GetByIdAsync(id, preview);
+ public async Task GetByIdAsync(int id, bool? preview = null) => await _documentCacheService.GetByIdAsync(id, preview);
- public async Task GetByIdAsync(Guid key, bool preview = false) => await _documentCacheService.GetByKeyAsync(key, preview);
+ public async Task GetByIdAsync(Guid key, bool? preview = null) => await _documentCacheService.GetByKeyAsync(key, preview);
public IPublishedContent? GetById(bool preview, int contentId) => GetByIdAsync(contentId, preview).GetAwaiter().GetResult();
public IPublishedContent? GetById(bool preview, Guid contentId) => GetByIdAsync(contentId, preview).GetAwaiter().GetResult();
- public IPublishedContent? GetById(int contentId) => GetByIdAsync(contentId, false).GetAwaiter().GetResult();
+ public IPublishedContent? GetById(int contentId) => GetByIdAsync(contentId).GetAwaiter().GetResult();
- public IPublishedContent? GetById(Guid contentId) => GetByIdAsync(contentId, false).GetAwaiter().GetResult();
+ public IPublishedContent? GetById(Guid contentId) => GetByIdAsync(contentId).GetAwaiter().GetResult();
public IPublishedContentType? GetContentType(int id) => _publishedContentTypeCache.Get(PublishedItemType.Content, id);
diff --git a/src/Umbraco.PublishedCache.HybridCache/Services/DocumentCacheService.cs b/src/Umbraco.PublishedCache.HybridCache/Services/DocumentCacheService.cs
index 4b8628574f..b73f48dcd7 100644
--- a/src/Umbraco.PublishedCache.HybridCache/Services/DocumentCacheService.cs
+++ b/src/Umbraco.PublishedCache.HybridCache/Services/DocumentCacheService.cs
@@ -22,6 +22,7 @@ internal sealed class DocumentCacheService : IDocumentCacheService
private readonly ICacheNodeFactory _cacheNodeFactory;
private readonly IEnumerable _seedKeyProviders;
private readonly IPublishedModelFactory _publishedModelFactory;
+ private readonly IPreviewService _previewService;
private readonly CacheSettings _cacheSettings;
private HashSet? _seedKeys;
@@ -54,7 +55,8 @@ internal sealed class DocumentCacheService : IDocumentCacheService
ICacheNodeFactory cacheNodeFactory,
IEnumerable seedKeyProviders,
IOptions cacheSettings,
- IPublishedModelFactory publishedModelFactory)
+ IPublishedModelFactory publishedModelFactory,
+ IPreviewService previewService)
{
_databaseCacheRepository = databaseCacheRepository;
_idKeyMap = idKeyMap;
@@ -64,22 +66,30 @@ internal sealed class DocumentCacheService : IDocumentCacheService
_cacheNodeFactory = cacheNodeFactory;
_seedKeyProviders = seedKeyProviders;
_publishedModelFactory = publishedModelFactory;
+ _previewService = previewService;
_cacheSettings = cacheSettings.Value;
}
- public async Task GetByKeyAsync(Guid key, bool preview = false)
+ public async Task GetByKeyAsync(Guid key, bool? preview = null)
{
using ICoreScope scope = _scopeProvider.CreateCoreScope();
+ bool calculatedPreview = preview ?? GetPreview();
+
ContentCacheNode? contentCacheNode = await _hybridCache.GetOrCreateAsync(
- GetCacheKey(key, preview), // Unique key to the cache entry
- async cancel => await _databaseCacheRepository.GetContentSourceAsync(key, preview));
+ GetCacheKey(key, calculatedPreview), // Unique key to the cache entry
+ async cancel => await _databaseCacheRepository.GetContentSourceAsync(key, calculatedPreview));
scope.Complete();
- return contentCacheNode is null ? null : _publishedContentFactory.ToIPublishedContent(contentCacheNode, preview).CreateModel(_publishedModelFactory);
+ return contentCacheNode is null ? null : _publishedContentFactory.ToIPublishedContent(contentCacheNode, calculatedPreview).CreateModel(_publishedModelFactory);
}
- public async Task GetByIdAsync(int id, bool preview = false)
+ private bool GetPreview()
+ {
+ return _previewService.IsInPreview();
+ }
+
+ public async Task GetByIdAsync(int id, bool? preview = null)
{
Attempt keyAttempt = _idKeyMap.GetKeyForId(id, UmbracoObjectTypes.Document);
if (keyAttempt.Success is false)
@@ -87,12 +97,14 @@ internal sealed class DocumentCacheService : IDocumentCacheService
return null;
}
+ bool calculatedPreview = preview ?? GetPreview();
+
using ICoreScope scope = _scopeProvider.CreateCoreScope();
ContentCacheNode? contentCacheNode = await _hybridCache.GetOrCreateAsync(
- GetCacheKey(keyAttempt.Result, preview), // Unique key to the cache entry
- async cancel => await _databaseCacheRepository.GetContentSourceAsync(id, preview));
+ GetCacheKey(keyAttempt.Result, calculatedPreview), // Unique key to the cache entry
+ async cancel => await _databaseCacheRepository.GetContentSourceAsync(id, calculatedPreview));
scope.Complete();
- return contentCacheNode is null ? null : _publishedContentFactory.ToIPublishedContent(contentCacheNode, preview).CreateModel(_publishedModelFactory);;
+ return contentCacheNode is null ? null : _publishedContentFactory.ToIPublishedContent(contentCacheNode, calculatedPreview).CreateModel(_publishedModelFactory);;
}
public IEnumerable GetByContentType(IPublishedContentType contentType)
diff --git a/src/Umbraco.PublishedCache.HybridCache/Services/IDocumentCacheService.cs b/src/Umbraco.PublishedCache.HybridCache/Services/IDocumentCacheService.cs
index 873551c06b..18a25496e2 100644
--- a/src/Umbraco.PublishedCache.HybridCache/Services/IDocumentCacheService.cs
+++ b/src/Umbraco.PublishedCache.HybridCache/Services/IDocumentCacheService.cs
@@ -5,9 +5,9 @@ namespace Umbraco.Cms.Infrastructure.HybridCache.Services;
public interface IDocumentCacheService
{
- Task GetByKeyAsync(Guid key, bool preview = false);
+ Task GetByKeyAsync(Guid key, bool? preview = null);
- Task GetByIdAsync(int id, bool preview = false);
+ Task GetByIdAsync(int id, bool? preview = null);
Task SeedAsync(CancellationToken cancellationToken);
diff --git a/src/Umbraco.PublishedCache.HybridCache/Services/MediaCacheService.cs b/src/Umbraco.PublishedCache.HybridCache/Services/MediaCacheService.cs
index 78e456dbf0..1bd2fe3e2b 100644
--- a/src/Umbraco.PublishedCache.HybridCache/Services/MediaCacheService.cs
+++ b/src/Umbraco.PublishedCache.HybridCache/Services/MediaCacheService.cs
@@ -8,6 +8,7 @@ using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Infrastructure.HybridCache.Factories;
using Umbraco.Cms.Infrastructure.HybridCache.Persistence;
using Umbraco.Cms.Infrastructure.HybridCache.Serialization;
+using Umbraco.Extensions;
namespace Umbraco.Cms.Infrastructure.HybridCache.Services;
@@ -20,6 +21,7 @@ internal class MediaCacheService : IMediaCacheService
private readonly IPublishedContentFactory _publishedContentFactory;
private readonly ICacheNodeFactory _cacheNodeFactory;
private readonly IEnumerable _seedKeyProviders;
+ private readonly IPublishedModelFactory _publishedModelFactory;
private readonly CacheSettings _cacheSettings;
private HashSet? _seedKeys;
@@ -51,6 +53,7 @@ internal class MediaCacheService : IMediaCacheService
IPublishedContentFactory publishedContentFactory,
ICacheNodeFactory cacheNodeFactory,
IEnumerable seedKeyProviders,
+ IPublishedModelFactory publishedModelFactory,
IOptions cacheSettings)
{
_databaseCacheRepository = databaseCacheRepository;
@@ -60,6 +63,7 @@ internal class MediaCacheService : IMediaCacheService
_publishedContentFactory = publishedContentFactory;
_cacheNodeFactory = cacheNodeFactory;
_seedKeyProviders = seedKeyProviders;
+ _publishedModelFactory = publishedModelFactory;
_cacheSettings = cacheSettings.Value;
}
@@ -78,7 +82,7 @@ internal class MediaCacheService : IMediaCacheService
async cancel => await _databaseCacheRepository.GetMediaSourceAsync(idAttempt.Result));
scope.Complete();
- return contentCacheNode is null ? null : _publishedContentFactory.ToIPublishedMedia(contentCacheNode);
+ return contentCacheNode is null ? null : _publishedContentFactory.ToIPublishedMedia(contentCacheNode).CreateModel(_publishedModelFactory);
}
public async Task GetByIdAsync(int id)
@@ -94,7 +98,7 @@ internal class MediaCacheService : IMediaCacheService
$"{keyAttempt.Result}", // Unique key to the cache entry
async cancel => await _databaseCacheRepository.GetMediaSourceAsync(id));
scope.Complete();
- return contentCacheNode is null ? null : _publishedContentFactory.ToIPublishedMedia(contentCacheNode);
+ return contentCacheNode is null ? null : _publishedContentFactory.ToIPublishedMedia(contentCacheNode).CreateModel(_publishedModelFactory);
}
public async Task HasContentByIdAsync(int id)
@@ -144,7 +148,7 @@ internal class MediaCacheService : IMediaCacheService
foreach (Guid key in SeedKeys)
{
- if(cancellationToken.IsCancellationRequested)
+ if (cancellationToken.IsCancellationRequested)
{
break;
}
@@ -187,7 +191,8 @@ internal class MediaCacheService : IMediaCacheService
private HybridCacheEntryOptions GetSeedEntryOptions() => new()
{
- Expiration = _cacheSettings.SeedCacheDuration, LocalCacheExpiration = _cacheSettings.SeedCacheDuration,
+ Expiration = _cacheSettings.SeedCacheDuration,
+ LocalCacheExpiration = _cacheSettings.SeedCacheDuration,
};
private string GetCacheKey(Guid key, bool preview) => preview ? $"{key}+draft" : $"{key}";
diff --git a/src/Umbraco.Web.Common/Extensions/FriendlyPublishedContentExtensions.cs b/src/Umbraco.Web.Common/Extensions/FriendlyPublishedContentExtensions.cs
index 858c7d82cd..60c7a27a57 100644
--- a/src/Umbraco.Web.Common/Extensions/FriendlyPublishedContentExtensions.cs
+++ b/src/Umbraco.Web.Common/Extensions/FriendlyPublishedContentExtensions.cs
@@ -22,9 +22,15 @@ public static class FriendlyPublishedContentExtensions
private static IPublishedContentCache PublishedContentCache { get; } =
StaticServiceProvider.Instance.GetRequiredService();
+ private static IPublishedMediaCache PublishedMediaCache { get; } =
+ StaticServiceProvider.Instance.GetRequiredService();
+
private static IDocumentNavigationQueryService DocumentNavigationQueryService { get; } =
StaticServiceProvider.Instance.GetRequiredService();
+ private static IMediaNavigationQueryService MediaNavigationQueryService { get; } =
+ StaticServiceProvider.Instance.GetRequiredService();
+
private static IPublishedModelFactory PublishedModelFactory { get; } =
StaticServiceProvider.Instance.GetRequiredService();
@@ -61,6 +67,33 @@ public static class FriendlyPublishedContentExtensions
private static IMemberTypeService MemberTypeService { get; } =
StaticServiceProvider.Instance.GetRequiredService();
+ private static INavigationQueryService GetNavigationQueryService(IPublishedContent content)
+ {
+ switch (content.ContentType.ItemType)
+ {
+ case PublishedItemType.Content:
+ return DocumentNavigationQueryService;
+ case PublishedItemType.Media:
+ return MediaNavigationQueryService;
+ default:
+ throw new NotSupportedException("Unsupported content type.");
+ }
+
+ }
+
+ private static IPublishedCache GetPublishedCache(IPublishedContent content)
+ {
+ switch (content.ContentType.ItemType)
+ {
+ case PublishedItemType.Content:
+ return PublishedContentCache;
+ case PublishedItemType.Media:
+ return PublishedMediaCache;
+ default:
+ throw new NotSupportedException("Unsupported content type.");
+ }
+ }
+
///
/// Creates a strongly typed published content model for an internal published content.
///
@@ -207,7 +240,7 @@ public static class FriendlyPublishedContentExtensions
/// set to 1.
///
public static IPublishedContent Root(this IPublishedContent content)
- => content.Root(PublishedContentCache, DocumentNavigationQueryService);
+ => content.Root(GetPublishedCache(content), GetNavigationQueryService(content));
///
/// Gets the root content (ancestor or self at level 1) for the specified if it's of the
@@ -226,7 +259,7 @@ public static class FriendlyPublishedContentExtensions
///
public static T? Root(this IPublishedContent content)
where T : class, IPublishedContent
- => content.Root(PublishedContentCache, DocumentNavigationQueryService);
+ => content.Root(GetPublishedCache(content), GetNavigationQueryService(content));
///
/// Gets the parent of the content item.
@@ -236,7 +269,7 @@ public static class FriendlyPublishedContentExtensions
/// The parent of content of the specified content type or null.
public static T? Parent(this IPublishedContent content)
where T : class, IPublishedContent
- => content.Parent(PublishedContentCache, DocumentNavigationQueryService);
+ => content.Parent(GetPublishedCache(content), GetNavigationQueryService(content));
///
/// Gets the ancestors of the content.
@@ -245,7 +278,7 @@ public static class FriendlyPublishedContentExtensions
/// The ancestors of the content, in down-top order.
/// Does not consider the content itself.
public static IEnumerable Ancestors(this IPublishedContent content)
- => content.Ancestors(PublishedContentCache, DocumentNavigationQueryService);
+ => content.Ancestors(GetPublishedCache(content), GetNavigationQueryService(content));
///
/// Gets the content and its ancestors.
@@ -253,7 +286,7 @@ public static class FriendlyPublishedContentExtensions
/// The content.
/// The content and its ancestors, in down-top order.
public static IEnumerable AncestorsOrSelf(this IPublishedContent content)
- => content.AncestorsOrSelf(PublishedContentCache, DocumentNavigationQueryService);
+ => content.AncestorsOrSelf(GetPublishedCache(content), GetNavigationQueryService(content));
///
/// Gets the content and its ancestors, of a specified content type.
@@ -264,7 +297,7 @@ public static class FriendlyPublishedContentExtensions
/// May or may not begin with the content itself, depending on its content type.
public static IEnumerable AncestorsOrSelf(this IPublishedContent content)
where T : class, IPublishedContent
- => content.AncestorsOrSelf(PublishedContentCache, DocumentNavigationQueryService);
+ => content.AncestorsOrSelf(GetPublishedCache(content), GetNavigationQueryService(content));
///
/// Gets the ancestor of the content, i.e. its parent.
@@ -272,7 +305,7 @@ public static class FriendlyPublishedContentExtensions
/// The content.
/// The ancestor of the content.
public static IPublishedContent? Ancestor(this IPublishedContent content)
- => content.Ancestor(PublishedContentCache, DocumentNavigationQueryService);
+ => content.Ancestor(GetPublishedCache(content), GetNavigationQueryService(content));
///
/// Gets the nearest ancestor of the content, of a specified content type.
@@ -283,7 +316,7 @@ public static class FriendlyPublishedContentExtensions
/// Does not consider the content itself. May return null.
public static T? Ancestor(this IPublishedContent content)
where T : class, IPublishedContent
- => content.Ancestor(PublishedContentCache, DocumentNavigationQueryService);
+ => content.Ancestor(GetPublishedCache(content), GetNavigationQueryService(content));
///
/// Gets the content or its nearest ancestor, of a specified content type.
@@ -294,7 +327,7 @@ public static class FriendlyPublishedContentExtensions
/// May or may not return the content itself depending on its content type. May return null.
public static T? AncestorOrSelf(this IPublishedContent content)
where T : class, IPublishedContent
- => content.AncestorOrSelf(PublishedContentCache, DocumentNavigationQueryService);
+ => content.AncestorOrSelf(GetPublishedCache(content), GetNavigationQueryService(content));
///
/// Returns all DescendantsOrSelf of all content referenced
@@ -311,7 +344,7 @@ public static class FriendlyPublishedContentExtensions
///
public static IEnumerable DescendantsOrSelfOfType(
this IEnumerable parentNodes, string docTypeAlias, string? culture = null)
- => parentNodes.DescendantsOrSelfOfType(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, docTypeAlias, culture);
+ => parentNodes.DescendantsOrSelfOfType(VariationContextAccessor, GetPublishedCache(parentNodes.First()), GetNavigationQueryService(parentNodes.First()), docTypeAlias, culture);
///
/// Returns all DescendantsOrSelf of all content referenced
@@ -329,77 +362,77 @@ public static class FriendlyPublishedContentExtensions
this IEnumerable parentNodes,
string? culture = null)
where T : class, IPublishedContent
- => parentNodes.DescendantsOrSelf(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, culture);
+ => parentNodes.DescendantsOrSelf(VariationContextAccessor, GetPublishedCache(parentNodes.First()), GetNavigationQueryService(parentNodes.First()), culture);
public static IEnumerable Descendants(this IPublishedContent content, string? culture = null)
- => content.Descendants(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, culture);
+ => content.Descendants(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture);
public static IEnumerable Descendants(this IPublishedContent content, int level, string? culture = null)
- => content.Descendants(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, level, culture);
+ => content.Descendants(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), level, culture);
public static IEnumerable DescendantsOfType(this IPublishedContent content, string contentTypeAlias, string? culture = null)
- => content.DescendantsOfType(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, contentTypeAlias, culture);
+ => content.DescendantsOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), contentTypeAlias, culture);
public static IEnumerable Descendants(this IPublishedContent content, string? culture = null)
where T : class, IPublishedContent
- => content.Descendants(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, culture);
+ => content.Descendants(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture);
public static IEnumerable Descendants(this IPublishedContent content, int level, string? culture = null)
where T : class, IPublishedContent
- => content.Descendants(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, level, culture);
+ => content.Descendants(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), level, culture);
public static IEnumerable DescendantsOrSelf(
this IPublishedContent content,
string? culture = null)
- => content.DescendantsOrSelf(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, culture);
+ => content.DescendantsOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture);
public static IEnumerable DescendantsOrSelf(this IPublishedContent content, int level, string? culture = null)
- => content.DescendantsOrSelf(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, level, culture);
+ => content.DescendantsOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), level, culture);
public static IEnumerable DescendantsOrSelfOfType(this IPublishedContent content, string contentTypeAlias, string? culture = null)
- => content.DescendantsOrSelfOfType(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, contentTypeAlias, culture);
+ => content.DescendantsOrSelfOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), contentTypeAlias, culture);
public static IEnumerable DescendantsOrSelf(this IPublishedContent content, string? culture = null)
where T : class, IPublishedContent
- => content.DescendantsOrSelf(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, culture);
+ => content.DescendantsOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture);
public static IEnumerable DescendantsOrSelf(this IPublishedContent content, int level, string? culture = null)
where T : class, IPublishedContent
- => content.DescendantsOrSelf(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, level, culture);
+ => content.DescendantsOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), level, culture);
public static IPublishedContent? Descendant(this IPublishedContent content, string? culture = null)
- => content.Descendant(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, culture);
+ => content.Descendant(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture);
public static IPublishedContent? Descendant(this IPublishedContent content, int level, string? culture = null)
- => content.Descendant(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, level, culture);
+ => content.Descendant(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), level, culture);
public static IPublishedContent? DescendantOfType(this IPublishedContent content, string contentTypeAlias, string? culture = null)
- => content.DescendantOfType(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, contentTypeAlias, culture);
+ => content.DescendantOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), contentTypeAlias, culture);
public static T? Descendant(this IPublishedContent content, string? culture = null)
where T : class, IPublishedContent
- => content.Descendant(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, culture);
+ => content.Descendant(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture);
public static T? Descendant(this IPublishedContent content, int level, string? culture = null)
where T : class, IPublishedContent
- => content.Descendant(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, level, culture);
+ => content.Descendant(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), level, culture);
public static IPublishedContent DescendantOrSelf(this IPublishedContent content, string? culture = null)
=> content.DescendantOrSelf(VariationContextAccessor, culture);
public static IPublishedContent? DescendantOrSelf(this IPublishedContent content, int level, string? culture = null)
- => content.DescendantOrSelf(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, level, culture);
+ => content.DescendantOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), level, culture);
public static IPublishedContent? DescendantOrSelfOfType(this IPublishedContent content, string contentTypeAlias, string? culture = null)
- => content.DescendantOrSelfOfType(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, contentTypeAlias, culture);
+ => content.DescendantOrSelfOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), contentTypeAlias, culture);
public static T? DescendantOrSelf(this IPublishedContent content, string? culture = null)
where T : class, IPublishedContent
- => content.DescendantOrSelf(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, culture);
+ => content.DescendantOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture);
public static T? DescendantOrSelf(this IPublishedContent content, int level, string? culture = null)
where T : class, IPublishedContent
- => content.DescendantOrSelf(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, level, culture);
+ => content.DescendantOrSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), level, culture);
///
/// Gets the children of the content item.
@@ -427,7 +460,7 @@ public static class FriendlyPublishedContentExtensions
///
///
public static IEnumerable Children(this IPublishedContent content, string? culture = null)
- => content.Children(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, culture);
+ => content.Children(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture);
///
/// Gets the children of the content, filtered by a predicate.
@@ -446,7 +479,7 @@ public static class FriendlyPublishedContentExtensions
this IPublishedContent content,
Func predicate,
string? culture = null)
- => content.Children(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, predicate, culture);
+ => content.Children(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), predicate, culture);
///
/// Gets the children of the content, of any of the specified types.
@@ -459,7 +492,7 @@ public static class FriendlyPublishedContentExtensions
/// The content type alias.
/// The children of the content, of any of the specified types.
public static IEnumerable? ChildrenOfType(this IPublishedContent content, string contentTypeAlias, string? culture = null)
- => content.ChildrenOfType(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, contentTypeAlias, culture);
+ => content.ChildrenOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), contentTypeAlias, culture);
///
/// Gets the children of the content, of a given content type.
@@ -476,30 +509,30 @@ public static class FriendlyPublishedContentExtensions
///
public static IEnumerable? Children(this IPublishedContent content, string? culture = null)
where T : class, IPublishedContent
- => content.Children(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, culture);
+ => content.Children(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture);
public static IPublishedContent? FirstChild(this IPublishedContent content, string? culture = null)
- => content.FirstChild(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, culture);
+ => content.FirstChild(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture);
///
/// Gets the first child of the content, of a given content type.
///
public static IPublishedContent? FirstChildOfType(this IPublishedContent content, string contentTypeAlias, string? culture = null)
- => content.FirstChildOfType(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, contentTypeAlias, culture);
+ => content.FirstChildOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), contentTypeAlias, culture);
public static IPublishedContent? FirstChild(this IPublishedContent content, Func predicate, string? culture = null)
- => content.FirstChild(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, predicate, culture);
+ => content.FirstChild(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), predicate, culture);
public static IPublishedContent? FirstChild(this IPublishedContent content, Guid uniqueId, string? culture = null)
- => content.FirstChild(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, uniqueId, culture);
+ => content.FirstChild(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), uniqueId, culture);
public static T? FirstChild(this IPublishedContent content, string? culture = null)
where T : class, IPublishedContent
- => content.FirstChild(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, culture);
+ => content.FirstChild(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture);
public static T? FirstChild(this IPublishedContent content, Func predicate, string? culture = null)
where T : class, IPublishedContent
- => content.FirstChild(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, predicate, culture);
+ => content.FirstChild(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), predicate, culture);
///
/// Gets the siblings of the content.
@@ -514,7 +547,7 @@ public static class FriendlyPublishedContentExtensions
/// Note that in V7 this method also return the content node self.
///
public static IEnumerable? Siblings(this IPublishedContent content, string? culture = null)
- => content.Siblings(PublishedContentCache, DocumentNavigationQueryService, VariationContextAccessor, culture);
+ => content.Siblings(GetPublishedCache(content), GetNavigationQueryService(content), VariationContextAccessor, culture);
///
/// Gets the siblings of the content, of a given content type.
@@ -530,7 +563,7 @@ public static class FriendlyPublishedContentExtensions
/// Note that in V7 this method also return the content node self.
///
public static IEnumerable? SiblingsOfType(this IPublishedContent content, string contentTypeAlias, string? culture = null)
- => content.SiblingsOfType(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, contentTypeAlias, culture);
+ => content.SiblingsOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), contentTypeAlias, culture);
///
/// Gets the siblings of the content, of a given content type.
@@ -547,7 +580,7 @@ public static class FriendlyPublishedContentExtensions
///
public static IEnumerable? Siblings(this IPublishedContent content, string? culture = null)
where T : class, IPublishedContent
- => content.Siblings(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, culture);
+ => content.Siblings(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture);
///
/// Gets the siblings of the content including the node itself to indicate the position.
@@ -561,7 +594,7 @@ public static class FriendlyPublishedContentExtensions
public static IEnumerable? SiblingsAndSelf(
this IPublishedContent content,
string? culture = null)
- => content.SiblingsAndSelf(PublishedContentCache, DocumentNavigationQueryService, VariationContextAccessor, culture);
+ => content.SiblingsAndSelf(GetPublishedCache(content), GetNavigationQueryService(content), VariationContextAccessor, culture);
///
/// Gets the siblings of the content including the node itself to indicate the position, of a given content type.
@@ -577,7 +610,7 @@ public static class FriendlyPublishedContentExtensions
this IPublishedContent content,
string contentTypeAlias,
string? culture = null)
- => content.SiblingsAndSelfOfType(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, contentTypeAlias, culture);
+ => content.SiblingsAndSelfOfType(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), contentTypeAlias, culture);
///
/// Gets the siblings of the content including the node itself to indicate the position, of a given content type.
@@ -591,7 +624,7 @@ public static class FriendlyPublishedContentExtensions
/// The siblings of the content including the node itself, of the given content type.
public static IEnumerable? SiblingsAndSelf(this IPublishedContent content, string? culture = null)
where T : class, IPublishedContent
- => content.SiblingsAndSelf(VariationContextAccessor, PublishedContentCache, DocumentNavigationQueryService, culture);
+ => content.SiblingsAndSelf(VariationContextAccessor, GetPublishedCache(content), GetNavigationQueryService(content), culture);
///
/// Gets the url of the content item.
@@ -626,8 +659,8 @@ public static class FriendlyPublishedContentExtensions
=>
content.ChildrenAsTable(
VariationContextAccessor,
- PublishedContentCache,
- DocumentNavigationQueryService,
+ GetPublishedCache(content),
+ GetNavigationQueryService(content),
ContentTypeService,
MediaTypeService,
MemberTypeService,
@@ -700,4 +733,5 @@ public static class FriendlyPublishedContentExtensions
string term,
string? indexName = null)
=> content.SearchChildren(ExamineManager, UmbracoContextAccessor, term, indexName);
+
}
diff --git a/src/Umbraco.Web.UI.Client b/src/Umbraco.Web.UI.Client
index 00e5576244..4729d3baa7 160000
--- a/src/Umbraco.Web.UI.Client
+++ b/src/Umbraco.Web.UI.Client
@@ -1 +1 @@
-Subproject commit 00e5576244a11e0fc1ea9aa2b79d3deba04e1609
+Subproject commit 4729d3baa7611ed63380abcfc184c1bb5a48b3bb
diff --git a/src/Umbraco.Web.UI.Login/public/login.jpg b/src/Umbraco.Web.UI.Login/public/login.jpg
index 4be79488eb..ed893bf3c0 100644
Binary files a/src/Umbraco.Web.UI.Login/public/login.jpg and b/src/Umbraco.Web.UI.Login/public/login.jpg differ
diff --git a/tests/Directory.Packages.props b/tests/Directory.Packages.props
index a3b4ceff47..3b4a2714b8 100644
--- a/tests/Directory.Packages.props
+++ b/tests/Directory.Packages.props
@@ -5,12 +5,12 @@
-
-
+
+
-
-
+
+
@@ -22,4 +22,4 @@
-
+
\ No newline at end of file
diff --git a/tests/Umbraco.Tests.Common/Builders/Extensions/BuilderExtensions.cs b/tests/Umbraco.Tests.Common/Builders/Extensions/BuilderExtensions.cs
index accee29bae..a44c5c7ba9 100644
--- a/tests/Umbraco.Tests.Common/Builders/Extensions/BuilderExtensions.cs
+++ b/tests/Umbraco.Tests.Common/Builders/Extensions/BuilderExtensions.cs
@@ -232,7 +232,8 @@ public static class BuilderExtensions
return builder;
}
- public static T WithPropertyValues(this T builder, object propertyValues, string? culture = null, string? segment = null)
+ public static T WithPropertyValues(this T builder, object propertyValues, string? culture = null,
+ string? segment = null)
where T : IWithPropertyValues
{
builder.PropertyValues = propertyValues;
diff --git a/tests/Umbraco.Tests.Common/Builders/MediaTypeEditingBuilder.cs b/tests/Umbraco.Tests.Common/Builders/MediaTypeEditingBuilder.cs
index eae219ecd1..c1291d64db 100644
--- a/tests/Umbraco.Tests.Common/Builders/MediaTypeEditingBuilder.cs
+++ b/tests/Umbraco.Tests.Common/Builders/MediaTypeEditingBuilder.cs
@@ -41,7 +41,8 @@ public class MediaTypeEditingBuilder : ContentTypeEditingBaseBuilder(contentType, updateModel);
return model;
}
- private T MapBaseProperties(IContentType contentType, T model) where T : ContentTypeModelBase
+ private static T MapBaseProperties(IContentType contentType, T model) where T : ContentTypeModelBase
{
model.Alias = contentType.Alias;
model.Name = contentType.Name;
diff --git a/tests/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTestWithContentEditing.cs b/tests/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTestWithContentEditing.cs
index e1f047dd90..fba87a9893 100644
--- a/tests/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTestWithContentEditing.cs
+++ b/tests/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTestWithContentEditing.cs
@@ -67,8 +67,7 @@ public abstract class UmbracoIntegrationTestWithContentEditing : UmbracoIntegrat
Assert.IsTrue(contentTypeAttempt.Success);
var contentTypeResult = contentTypeAttempt.Result;
- ContentTypeUpdateHelper contentTypeUpdateHelper = new ContentTypeUpdateHelper();
- ContentTypeUpdateModel = contentTypeUpdateHelper.CreateContentTypeUpdateModel(contentTypeResult); ContentTypeUpdateModel.AllowedContentTypes = new[]
+ ContentTypeUpdateModel = ContentTypeUpdateHelper.CreateContentTypeUpdateModel(contentTypeResult); ContentTypeUpdateModel.AllowedContentTypes = new[]
{
new ContentTypeSort(contentTypeResult.Key, 0, ContentTypeCreateModel.Alias),
};
diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Cache/PublishedContentTypeCacheTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Cache/PublishedContentTypeCacheTests.cs
index d74439634a..71c450b54c 100644
--- a/tests/Umbraco.Tests.Integration/Umbraco.Core/Cache/PublishedContentTypeCacheTests.cs
+++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Cache/PublishedContentTypeCacheTests.cs
@@ -37,8 +37,7 @@ public class PublishedContentTypeCacheTests : UmbracoIntegrationTestWithContentE
Assert.IsNotNull(contentType);
Assert.AreEqual(1, ContentType.PropertyTypes.Count());
// Update the content type
- ContentTypeUpdateHelper contentTypeUpdateHelper = new ContentTypeUpdateHelper();
- var updateModel = contentTypeUpdateHelper.CreateContentTypeUpdateModel(ContentType);
+ var updateModel = ContentTypeUpdateHelper.CreateContentTypeUpdateModel(ContentType);
updateModel.Properties = new List();
await ContentTypeEditingService.UpdateAsync(ContentType, updateModel, Constants.Security.SuperUserKey);
diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/PublishedContent/PublishContentTypeFactoryTest.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/PublishedContent/PublishContentTypeFactoryTest.cs
new file mode 100644
index 0000000000..c8805492a9
--- /dev/null
+++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/PublishedContent/PublishContentTypeFactoryTest.cs
@@ -0,0 +1,98 @@
+using NUnit.Framework;
+using Umbraco.Cms.Core;
+using Umbraco.Cms.Core.Cache;
+using Umbraco.Cms.Core.Models.PublishedContent;
+using Umbraco.Cms.Core.Notifications;
+using Umbraco.Cms.Core.Services;
+using Umbraco.Cms.Core.Services.ContentTypeEditing;
+using Umbraco.Cms.Core.Sync;
+using Umbraco.Cms.Tests.Common.Builders;
+using Umbraco.Cms.Tests.Common.Builders.Extensions;
+using Umbraco.Cms.Tests.Common.TestHelpers;
+using Umbraco.Cms.Tests.Common.Testing;
+using Umbraco.Cms.Tests.Integration.Testing;
+using Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services;
+
+namespace Umbraco.Cms.Tests.Integration.Umbraco.Core.PublishedContent;
+
+[TestFixture]
+[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)]
+public class PublishContentTypeFactoryTest : UmbracoIntegrationTest
+{
+ protected override void CustomTestSetup(IUmbracoBuilder builder)
+ {
+ builder.AddNotificationHandler();
+ builder.AddNotificationHandler();
+ builder.Services.AddUnique();
+ base.CustomTestSetup(builder);
+ }
+
+ private ITemplateService TemplateService => GetRequiredService();
+
+ private IContentTypeEditingService ContentTypeEditingService => GetRequiredService();
+
+ private IDataTypeService DataTypeService => GetRequiredService();
+
+ private IPublishedContentTypeFactory PublishedContentTypeFactory => GetRequiredService();
+
+ [Test]
+ public async Task Can_Update_Content_Type()
+ {
+ // Create a content type
+ var template = TemplateBuilder.CreateTextPageTemplate("defaultTemplate");
+ await TemplateService.CreateAsync(template, Constants.Security.SuperUserKey);
+ var contentTypeCreateModel = ContentTypeEditingBuilder.CreateSimpleContentType("umbTextpage", "Textpage", defaultTemplateKey: template.Key);
+ var contentTypeAttempt = await ContentTypeEditingService.CreateAsync(contentTypeCreateModel, Constants.Security.SuperUserKey);
+ Assert.IsTrue(contentTypeAttempt.Success);
+ Assert.IsNotNull(contentTypeAttempt.Result);
+
+ // Fetch the content type to cache data types
+ var contentType = contentTypeAttempt.Result;
+ PublishedContentTypeFactory.CreateContentType(contentType);
+
+ var dataType = new DataTypeBuilder()
+ .WithId(0)
+ .Build();
+ var dataTypeCreateResult = await DataTypeService.CreateAsync(dataType, Constants.Security.SuperUserKey);
+ Assert.IsTrue(dataTypeCreateResult.Success);
+
+ contentType.AddPropertyGroup("group", "Group");
+ var propertyTypeAlias = "test";
+ var propertyType = new PropertyTypeBuilder()
+ .WithAlias(propertyTypeAlias)
+ .WithDataTypeId(dataTypeCreateResult.Result.Id)
+ .Build();
+ propertyType.DataTypeKey = dataType.Key;
+
+ contentType.AddPropertyType(propertyType, "group", "Group");
+
+ // Update the content type
+ var contentTypeUpdate = ContentTypeUpdateHelper.CreateContentTypeUpdateModel(contentType);
+ var updateResult = await ContentTypeEditingService.UpdateAsync(contentType, contentTypeUpdate, Constants.Security.SuperUserKey);
+ Assert.IsTrue(updateResult.Success);
+
+
+ var publishedContentType = PublishedContentTypeFactory.CreateContentType(updateResult.Result);
+ Assert.That(publishedContentType.PropertyTypes.Where(x => x.Alias == propertyTypeAlias), Is.Not.Empty);
+ }
+
+ [Test]
+ public async Task Can_Get_Updated_Datatype()
+ {
+ var dataType = new DataTypeBuilder()
+ .WithId(0)
+ .Build();
+ dataType.EditorUiAlias = "NotUpdated";
+ var dataTypeCreateResult = await DataTypeService.CreateAsync(dataType, Constants.Security.SuperUserKey);
+ Assert.IsTrue(dataTypeCreateResult.Success);
+ var createdDataType = dataTypeCreateResult.Result;
+ PublishedDataType createdPublishedDataType = PublishedContentTypeFactory.GetDataType(createdDataType.Id);
+ Assert.That(createdPublishedDataType.EditorUiAlias, Is.EqualTo("NotUpdated"));
+
+ createdDataType.EditorUiAlias = "Updated";
+ var dataTypeUpdateResult = await DataTypeService.UpdateAsync(createdDataType, Constants.Security.SuperUserKey);
+ Assert.IsTrue(dataTypeUpdateResult.Success);
+ var updatedPublishedDataType = PublishedContentTypeFactory.GetDataType(createdDataType.Id);
+ Assert.That(updatedPublishedDataType.EditorUiAlias, Is.EqualTo("Updated"));
+ }
+}
diff --git a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheMockTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheMockTests.cs
index b0e3bc6ec7..2e810114d0 100644
--- a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheMockTests.cs
+++ b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheMockTests.cs
@@ -104,7 +104,8 @@ public class DocumentHybridCacheMockTests : UmbracoIntegrationTestWithContent
GetRequiredService(),
GetSeedProviders(),
Options.Create(new CacheSettings()),
- GetRequiredService());
+ GetRequiredService(),
+ GetRequiredService());
_mockedCache = new DocumentCache(_mockDocumentCacheService, GetRequiredService());
}
diff --git a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheTemplateTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheTemplateTests.cs
index eb352ff6c8..a0873bd983 100644
--- a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheTemplateTests.cs
+++ b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheTemplateTests.cs
@@ -1,4 +1,4 @@
-using NUnit.Framework;
+using NUnit.Framework;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models.ContentEditing;
using Umbraco.Cms.Core.PublishedCache;
@@ -36,7 +36,6 @@ public class DocumentHybridCacheTemplateTests : UmbracoIntegrationTestWithConten
// Assert
Assert.AreEqual(updateContentResult.Status, ContentEditingOperationStatus.Success);
var textPageAfter = await PublishedContentHybridCache.GetByIdAsync(TextpageId, true);
- // Should this not be null?
Assert.AreEqual(textPageAfter.TemplateId, null);
}
}