Skip to content
Merged
  •  
  •  
  •  
8 changes: 7 additions & 1 deletion src/Umbraco.Core/Actions/ActionDocumentPropertyRead.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
namespace Umbraco.Cms.Core.Actions;
namespace Umbraco.Cms.Core.Actions;

/// <summary>
/// Represents the action that allows reading document property values.
/// </summary>
/// <remarks>
/// This action is used for permission control when accessing property values on documents.
/// </remarks>
public class ActionDocumentPropertyRead : IAction
{
/// <inheritdoc cref="IAction.ActionLetter" />
Expand Down
8 changes: 7 additions & 1 deletion src/Umbraco.Core/Actions/ActionDocumentPropertyWrite.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
namespace Umbraco.Cms.Core.Actions;
namespace Umbraco.Cms.Core.Actions;

/// <summary>
/// Represents the action that allows writing document property values.
/// </summary>
/// <remarks>
/// This action is used for permission control when modifying property values on documents.
/// </remarks>
public class ActionDocumentPropertyWrite : IAction
{
/// <inheritdoc cref="IAction.ActionLetter" />
Expand Down
10 changes: 9 additions & 1 deletion src/Umbraco.Core/Blocks/IPartialViewBlockEngine.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
using Umbraco.Cms.Core.Models.Blocks;
using Umbraco.Cms.Core.Models.Blocks;
using Umbraco.Cms.Core.Models.PublishedContent;

namespace Umbraco.Cms.Core.Blocks;

/// <summary>
/// Defines a contract for rendering block references using partial views.
/// </summary>
public interface IPartialViewBlockEngine
{
/// <summary>
/// Executes the partial view associated with the given block reference and returns the rendered output.
/// </summary>
/// <param name="blockReference">The block reference containing content and settings elements to render.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains the rendered HTML string.</returns>
Task<string> ExecuteAsync(IBlockReference<IPublishedElement, IPublishedElement> blockReference);
}
70 changes: 69 additions & 1 deletion src/Umbraco.Core/Cache/AppCacheExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,20 @@
namespace Umbraco.Extensions;

/// <summary>
/// Extensions for strongly typed access
/// Provides extension methods for strongly typed access to <see cref="IAppCache" /> and <see cref="IAppPolicyCache" />.
/// </summary>
public static class AppCacheExtensions
{
/// <summary>
/// Gets a strongly typed cache item with the specified key, creating it if necessary using the provided factory.
/// </summary>
/// <typeparam name="T">The type of the cached item.</typeparam>
/// <param name="provider">The cache provider.</param>
/// <param name="cacheKey">The cache key.</param>
/// <param name="getCacheItem">A factory function that creates the item if not found.</param>
/// <param name="timeout">An optional cache timeout.</param>
/// <param name="isSliding">Whether the timeout is sliding (resets on access).</param>
/// <returns>The cached item, or default if not found and factory returns null.</returns>
public static T? GetCacheItem<T>(
this IAppPolicyCache provider,
string cacheKey,
Expand All @@ -18,6 +28,15 @@ public static class AppCacheExtensions
return result == null ? default : result.TryConvertTo<T>().Result;
}

/// <summary>
/// Inserts a strongly typed cache item with the specified key.
/// </summary>
/// <typeparam name="T">The type of the cached item.</typeparam>
/// <param name="provider">The cache provider.</param>
/// <param name="cacheKey">The cache key.</param>
/// <param name="getCacheItem">A factory function that creates the item to cache.</param>
/// <param name="timeout">An optional cache timeout.</param>
/// <param name="isSliding">Whether the timeout is sliding (resets on access).</param>
public static void InsertCacheItem<T>(
this IAppPolicyCache provider,
string cacheKey,
Expand All @@ -26,18 +45,39 @@ public static void InsertCacheItem<T>(
bool isSliding = false) =>
provider.Insert(cacheKey, () => getCacheItem(), timeout, isSliding);

/// <summary>
/// Gets strongly typed cache items with keys starting with the specified value.
/// </summary>
/// <typeparam name="T">The type of the cached items.</typeparam>
/// <param name="provider">The cache provider.</param>
/// <param name="keyStartsWith">The key prefix to search for.</param>
/// <returns>A collection of cached items matching the search.</returns>
public static IEnumerable<T?> GetCacheItemsByKeySearch<T>(this IAppCache provider, string keyStartsWith)
{
IEnumerable<object?> result = provider.SearchByKey(keyStartsWith);
return result.Select(x => x.TryConvertTo<T>().Result);
}

/// <summary>
/// Gets strongly typed cache items with keys matching a regular expression.
/// </summary>
/// <typeparam name="T">The type of the cached items.</typeparam>
/// <param name="provider">The cache provider.</param>
/// <param name="regexString">The regular expression pattern to match keys against.</param>
/// <returns>A collection of cached items matching the search.</returns>
public static IEnumerable<T?> GetCacheItemsByKeyExpression<T>(this IAppCache provider, string regexString)
{
IEnumerable<object?> result = provider.SearchByRegex(regexString);
return result.Select(x => x.TryConvertTo<T>().Result);
}

/// <summary>
/// Gets a strongly typed cache item with the specified key.
/// </summary>
/// <typeparam name="T">The type of the cached item.</typeparam>
/// <param name="provider">The cache provider.</param>
/// <param name="cacheKey">The cache key.</param>
/// <returns>The cached item, or default if not found.</returns>
public static T? GetCacheItem<T>(this IAppCache provider, string cacheKey)
{
var result = provider.Get(cacheKey);
Expand All @@ -56,6 +96,14 @@ public static void InsertCacheItem<T>(
return result.TryConvertTo<T>().Result;
}

/// <summary>
/// Gets a strongly typed cache item with the specified key, creating it if necessary using the provided factory.
/// </summary>
/// <typeparam name="T">The type of the cached item.</typeparam>
/// <param name="provider">The cache provider.</param>
/// <param name="cacheKey">The cache key.</param>
/// <param name="getCacheItem">A factory function that creates the item if not found.</param>
/// <returns>The cached item, or default if not found and factory returns null.</returns>
public static T? GetCacheItem<T>(this IAppCache provider, string cacheKey, Func<T> getCacheItem)
{
var result = provider.Get(cacheKey, () => getCacheItem());
Expand All @@ -74,6 +122,16 @@ public static void InsertCacheItem<T>(
return result.TryConvertTo<T>().Result;
}

/// <summary>
/// Asynchronously gets a strongly typed cache item with the specified key, creating it if necessary using the provided factory.
/// </summary>
/// <typeparam name="T">The type of the cached item.</typeparam>
/// <param name="provider">The cache provider.</param>
/// <param name="cacheKey">The cache key.</param>
/// <param name="getCacheItemAsync">An async factory function that creates the item if not found.</param>
/// <param name="timeout">An optional cache timeout.</param>
/// <param name="isSliding">Whether the timeout is sliding (resets on access).</param>
/// <returns>A task representing the asynchronous operation, containing the cached item.</returns>
public static async Task<T?> GetCacheItemAsync<T>(
this IAppPolicyCache provider,
string cacheKey,
Expand Down Expand Up @@ -108,6 +166,16 @@ public static void InsertCacheItem<T>(

private static bool RequestedNullRepresentationInCache<T>() => typeof(T) == typeof(string);

/// <summary>
/// Asynchronously inserts a strongly typed cache item with the specified key.
/// </summary>
/// <typeparam name="T">The type of the cached item.</typeparam>
/// <param name="provider">The cache provider.</param>
/// <param name="cacheKey">The cache key.</param>
/// <param name="getCacheItemAsync">An async factory function that creates the item to cache.</param>
/// <param name="timeout">An optional cache timeout.</param>
/// <param name="isSliding">Whether the timeout is sliding (resets on access).</param>
/// <returns>A task representing the asynchronous operation.</returns>
public static async Task InsertCacheItemAsync<T>(
this IAppPolicyCache provider,
string cacheKey,
Expand Down
10 changes: 10 additions & 0 deletions src/Umbraco.Core/Cache/AppCaches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,27 @@ public AppCaches(
/// </remarks>
public IsolatedCaches IsolatedCaches { get; }

/// <summary>
/// Creates a new instance of <see cref="AppCaches" /> with the specified request cache.
/// </summary>
/// <param name="requestCache">The request cache to use.</param>
/// <returns>A new <see cref="AppCaches" /> instance.</returns>
public static AppCaches Create(IRequestCache requestCache) =>
new(
new DeepCloneAppCache(new ObjectCacheAppCache()),
requestCache,
new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache())));

/// <inheritdoc />
public void Dispose() =>

// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(true);

/// <summary>
/// Releases the unmanaged resources used by the <see cref="AppCaches" /> and optionally releases the managed resources.
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
if (!_disposedValue)
Expand Down
5 changes: 5 additions & 0 deletions src/Umbraco.Core/Cache/AppPolicedCacheDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public abstract class AppPolicedCacheDictionary<TKey> : IDisposable
/// <param name="cacheFactory"></param>
protected AppPolicedCacheDictionary(Func<TKey, IAppPolicyCache> cacheFactory) => _cacheFactory = cacheFactory;

/// <inheritdoc />
public void Dispose() =>

// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Expand Down Expand Up @@ -75,6 +76,10 @@ protected void ClearCache(TKey key)
}
}

/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
if (!_disposedValue)
Expand Down
45 changes: 43 additions & 2 deletions src/Umbraco.Core/Cache/CacheKeys.cs
Original file line number Diff line number Diff line change
@@ -1,27 +1,68 @@
namespace Umbraco.Cms.Core.Cache;

/// <summary>
/// Constants storing cache keys used in caching
/// Constants storing cache keys used in caching.
/// </summary>
public static class CacheKeys
{
public const string ApplicationsCacheKey = "ApplicationCache"; // used by SectionService
/// <summary>
/// Cache key for applications (sections) cache, used by SectionService.
/// </summary>
public const string ApplicationsCacheKey = "ApplicationCache";

/// <summary>
/// Cache key prefix for template front-end cache.
/// </summary>
// TODO: this one can probably be removed
public const string TemplateFrontEndCacheKey = "template";

/// <summary>
/// Cache key prefix for user group lookup by alias.
/// </summary>
public const string UserGroupGetByAliasCacheKeyPrefix = "UserGroupRepository_GetByAlias_";

/// <summary>
/// Cache key prefix for user's content start nodes.
/// </summary>
public const string UserAllContentStartNodesPrefix = "AllContentStartNodes";

/// <summary>
/// Cache key prefix for user's media start nodes.
/// </summary>
public const string UserAllMediaStartNodesPrefix = "AllMediaStartNodes";

/// <summary>
/// Cache key prefix for user's media start node paths.
/// </summary>
public const string UserMediaStartNodePathsPrefix = "MediaStartNodePaths";

/// <summary>
/// Cache key prefix for user's content start node paths.
/// </summary>
public const string UserContentStartNodePathsPrefix = "ContentStartNodePaths";

/// <summary>
/// Cache key for content recycle bin.
/// </summary>
public const string ContentRecycleBinCacheKey = "recycleBin_content";

/// <summary>
/// Cache key for media recycle bin.
/// </summary>
public const string MediaRecycleBinCacheKey = "recycleBin_media";

/// <summary>
/// Cache key prefix for preview (draft) property cache values.
/// </summary>
public const string PreviewPropertyCacheKeyPrefix = "Cache.Property.CacheValues[D:";

/// <summary>
/// Cache key prefix for published property cache values.
/// </summary>
public const string PropertyCacheKeyPrefix = "Cache.Property.CacheValues[P:";

/// <summary>
/// Cache key prefix for member username lookups.
/// </summary>
public const string MemberUserNameCachePrefix = "uRepo_userNameKey+";
}
17 changes: 15 additions & 2 deletions src/Umbraco.Core/Cache/DataTypeConfigurationCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,32 @@
namespace Umbraco.Cms.Core.Cache;

/// <summary>
/// This cache is a temporary measure to reduce the amount of computational power required to deserialize and initialize <see cref="IDataType" /> when fetched from the main cache/database,
/// because datatypes are fetched multiple times troughout a (backoffice content) request with a lot of content (or nested content) and each of these fetches initializes certain fields on the datatypes.
/// Implements <see cref="IDataTypeConfigurationCache" /> to cache data type configurations.
/// </summary>
/// <remarks>
/// This cache is a temporary measure to reduce the amount of computational power required to
/// deserialize and initialize <see cref="IDataType" /> when fetched from the main cache/database,
/// because data types are fetched multiple times throughout a (backoffice content) request with
/// a lot of content (or nested content) and each of these fetches initializes certain fields on the data types.
/// </remarks>
internal sealed class DataTypeConfigurationCache : IDataTypeConfigurationCache
{
private readonly IDataTypeService _dataTypeService;
private readonly IMemoryCache _memoryCache;

/// <summary>
/// Initializes a new instance of the <see cref="DataTypeConfigurationCache" /> class.
/// </summary>
/// <param name="dataTypeService">The data type service.</param>
/// <param name="memoryCache">The memory cache.</param>
/// <param name="idKeyMap">The ID/key map service.</param>
public DataTypeConfigurationCache(IDataTypeService dataTypeService, IMemoryCache memoryCache, IIdKeyMap idKeyMap)
{
_dataTypeService = dataTypeService;
_memoryCache = memoryCache;
}

/// <inheritdoc />
public T? GetConfigurationAs<T>(Guid key)
where T : class
{
Expand All @@ -39,6 +51,7 @@ public DataTypeConfigurationCache(IDataTypeService dataTypeService, IMemoryCache
return configuration;
}

/// <inheritdoc />
public void ClearCache(IEnumerable<Guid> keys)
{
foreach (Guid key in keys)
Expand Down
12 changes: 12 additions & 0 deletions src/Umbraco.Core/Cache/DataTypeConfigurationCacheRefresher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,25 @@

namespace Umbraco.Cms.Core.Cache;

/// <summary>
/// Handles <see cref="DataTypeCacheRefresherNotification" /> to clear the data type configuration cache.
/// </summary>
/// <remarks>
/// This handler ensures that the <see cref="IDataTypeConfigurationCache" /> is cleared when
/// data types are modified, keeping cached configurations in sync with the database.
/// </remarks>
internal sealed class DataTypeConfigurationCacheRefresher : INotificationHandler<DataTypeCacheRefresherNotification>
{
private readonly IDataTypeConfigurationCache _dataTypeConfigurationCache;

/// <summary>
/// Initializes a new instance of the <see cref="DataTypeConfigurationCacheRefresher" /> class.
/// </summary>
/// <param name="dataTypeConfigurationCache">The data type configuration cache.</param>
public DataTypeConfigurationCacheRefresher(IDataTypeConfigurationCache dataTypeConfigurationCache)
=> _dataTypeConfigurationCache = dataTypeConfigurationCache;

/// <inheritdoc />
public void Handle(DataTypeCacheRefresherNotification notification)
=> _dataTypeConfigurationCache.ClearCache(((DataTypeCacheRefresher.JsonPayload[])notification.MessageObject).Select(x => x.Key));
}
5 changes: 5 additions & 0 deletions src/Umbraco.Core/Cache/DeepCloneAppCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,16 @@ public void Insert(string key, Func<object?> factory, TimeSpan? timeout = null,
/// <inheritdoc />
public void ClearByRegex(string regex) => InnerCache.ClearByRegex(regex);

/// <inheritdoc />
public void Dispose() =>

// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(true);

/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
if (!_disposedValue)
Expand Down
Loading
Loading