From 08b6fd3576dcbf56d13bcd03bbb8b15d9058adfe Mon Sep 17 00:00:00 2001 From: yv01p Date: Wed, 24 Dec 2025 14:45:55 +0000 Subject: [PATCH] refactor(core): inject ContentPermissionManager into ContentService MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 6: Add constructor parameter and lazy fallback for ContentPermissionManager. Changes: - Add private fields _permissionManager and _permissionManagerLazy to ContentService - Add PermissionManager property accessor with null safety check - Update primary constructor to accept ContentPermissionManager as parameter 23 - Update all obsolete constructors with lazy resolution via StaticServiceProvider - Update DI factory in UmbracoBuilder to pass ContentPermissionManager - Make ContentPermissionManager public for DI compatibility 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../DependencyInjection/UmbracoBuilder.cs | 3 +- .../Services/ContentPermissionManager.cs | 6 ++-- src/Umbraco.Core/Services/ContentService.cs | 30 ++++++++++++++++++- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs index 0caee529fc..257a1dea3c 100644 --- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs @@ -328,7 +328,8 @@ namespace Umbraco.Cms.Core.DependencyInjection sp.GetRequiredService(), sp.GetRequiredService(), sp.GetRequiredService(), - sp.GetRequiredService())); + sp.GetRequiredService(), + sp.GetRequiredService())); Services.AddUnique(); Services.AddUnique(); Services.AddUnique(); diff --git a/src/Umbraco.Core/Services/ContentPermissionManager.cs b/src/Umbraco.Core/Services/ContentPermissionManager.cs index ad6fe0ee5c..3ff45c6fb0 100644 --- a/src/Umbraco.Core/Services/ContentPermissionManager.cs +++ b/src/Umbraco.Core/Services/ContentPermissionManager.cs @@ -13,11 +13,11 @@ namespace Umbraco.Cms.Core.Services; /// /// /// -/// This is an internal class that encapsulates permission operations extracted from ContentService +/// This class encapsulates permission operations extracted from ContentService /// as part of the ContentService refactoring initiative (Phase 6). /// /// -/// Design Decision: This class is internal (not public interface) because: +/// Design Decision: This class is public for DI but not intended for direct external use: /// /// Permission operations are tightly coupled to content entities /// They don't require independent testability beyond ContentService tests @@ -29,7 +29,7 @@ namespace Umbraco.Cms.Core.Services; /// materialized collection (not deferred), so scope disposal before enumeration is safe. /// /// -internal sealed class ContentPermissionManager +public sealed class ContentPermissionManager { private readonly ICoreScopeProvider _scopeProvider; private readonly IDocumentRepository _documentRepository; diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index 7f7f3c76d3..d7d6993ba7 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -67,6 +67,10 @@ public class ContentService : RepositoryService, IContentService private readonly IContentPublishOperationService? _publishOperationService; private readonly Lazy? _publishOperationServiceLazy; + // Permission manager field (for Phase 6 extracted permission operations) + private readonly ContentPermissionManager? _permissionManager; + private readonly Lazy? _permissionManagerLazy; + /// /// Gets the query operation service. /// @@ -99,6 +103,14 @@ public class ContentService : RepositoryService, IContentService _publishOperationService ?? _publishOperationServiceLazy?.Value ?? throw new InvalidOperationException("PublishOperationService not initialized. Ensure the service is properly injected via constructor."); + /// + /// Gets the permission manager. + /// + /// Thrown if the manager was not properly initialized. + private ContentPermissionManager PermissionManager => + _permissionManager ?? _permissionManagerLazy?.Value + ?? throw new InvalidOperationException("PermissionManager not initialized. Ensure the manager is properly injected via constructor."); + #region Constructors [Microsoft.Extensions.DependencyInjection.ActivatorUtilitiesConstructor] @@ -124,7 +136,8 @@ public class ContentService : RepositoryService, IContentService IContentQueryOperationService queryOperationService, // NEW PARAMETER - Phase 2 query operations IContentVersionOperationService versionOperationService, // NEW PARAMETER - Phase 3 version operations IContentMoveOperationService moveOperationService, // NEW PARAMETER - Phase 4 move operations - IContentPublishOperationService publishOperationService) // NEW PARAMETER - Phase 5 publish operations + IContentPublishOperationService publishOperationService, // NEW PARAMETER - Phase 5 publish operations + ContentPermissionManager permissionManager) // NEW PARAMETER - Phase 6 permission operations : base(provider, loggerFactory, eventMessagesFactory) { _documentRepository = documentRepository; @@ -169,6 +182,11 @@ public class ContentService : RepositoryService, IContentService ArgumentNullException.ThrowIfNull(publishOperationService); _publishOperationService = publishOperationService; _publishOperationServiceLazy = null; // Not needed when directly injected + + // Phase 6: Permission manager (direct injection) + ArgumentNullException.ThrowIfNull(permissionManager); + _permissionManager = permissionManager; + _permissionManagerLazy = null; // Not needed when directly injected } [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] @@ -240,6 +258,11 @@ public class ContentService : RepositoryService, IContentService _publishOperationServiceLazy = new Lazy(() => StaticServiceProvider.Instance.GetRequiredService(), LazyThreadSafetyMode.ExecutionAndPublication); + + // Phase 6: Lazy resolution of ContentPermissionManager + _permissionManagerLazy = new Lazy(() => + StaticServiceProvider.Instance.GetRequiredService(), + LazyThreadSafetyMode.ExecutionAndPublication); } [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] @@ -310,6 +333,11 @@ public class ContentService : RepositoryService, IContentService _publishOperationServiceLazy = new Lazy(() => StaticServiceProvider.Instance.GetRequiredService(), LazyThreadSafetyMode.ExecutionAndPublication); + + // Phase 6: Lazy resolution of ContentPermissionManager + _permissionManagerLazy = new Lazy(() => + StaticServiceProvider.Instance.GetRequiredService(), + LazyThreadSafetyMode.ExecutionAndPublication); } #endregion