diff --git a/src/Umbraco.Core/Deploy/ArtifactDeployState.cs b/src/Umbraco.Core/Deploy/ArtifactDeployState.cs index 0da78292f2..d451c1941d 100644 --- a/src/Umbraco.Core/Deploy/ArtifactDeployState.cs +++ b/src/Umbraco.Core/Deploy/ArtifactDeployState.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Cms.Core.Deploy +namespace Umbraco.Cms.Core.Deploy { /// /// Represent the state of an artifact being deployed. @@ -24,10 +24,7 @@ /// /// Gets the artifact. /// - public IArtifact? Artifact - { - get { return GetArtifactAsIArtifact(); } - } + public IArtifact Artifact => GetArtifactAsIArtifact(); /// /// Gets the artifact as an . @@ -35,7 +32,7 @@ /// The artifact, as an . /// This is because classes that inherit from this class cannot override the Artifact property /// with a property that specializes the return type, and so they need to 'new' the property. - protected abstract IArtifact? GetArtifactAsIArtifact(); + protected abstract IArtifact GetArtifactAsIArtifact(); /// /// Gets or sets the service connector in charge of deploying the artifact. diff --git a/src/Umbraco.Core/Deploy/ArtifactDeployStateOfTArtifactTEntity.cs b/src/Umbraco.Core/Deploy/ArtifactDeployStateOfTArtifactTEntity.cs index bb9a06274e..afe619f3bd 100644 --- a/src/Umbraco.Core/Deploy/ArtifactDeployStateOfTArtifactTEntity.cs +++ b/src/Umbraco.Core/Deploy/ArtifactDeployStateOfTArtifactTEntity.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Cms.Core.Deploy +namespace Umbraco.Cms.Core.Deploy { /// /// Represent the state of an artifact being deployed. @@ -8,12 +8,6 @@ public class ArtifactDeployState : ArtifactDeployState where TArtifact : IArtifact { - /// - /// Initializes a new instance of the class. - /// - public ArtifactDeployState() - { } - /// /// Initializes a new instance of the class. /// @@ -32,15 +26,15 @@ /// /// Gets or sets the artifact. /// - public new TArtifact? Artifact { get; set; } + public new TArtifact Artifact { get; set; } /// /// Gets or sets the entity. /// - public TEntity? Entity { get; set; } + public TEntity Entity { get; set; } /// - protected sealed override IArtifact? GetArtifactAsIArtifact() + protected sealed override IArtifact GetArtifactAsIArtifact() { return Artifact; } diff --git a/src/Umbraco.Core/Deploy/ILocalLinkParser.cs b/src/Umbraco.Core/Deploy/ILocalLinkParser.cs index f807b9604f..5883f73217 100644 --- a/src/Umbraco.Core/Deploy/ILocalLinkParser.cs +++ b/src/Umbraco.Core/Deploy/ILocalLinkParser.cs @@ -1,5 +1,3 @@ -using System.Collections.Generic; - namespace Umbraco.Cms.Core.Deploy { /// diff --git a/src/Umbraco.Core/Deploy/IServiceConnector.cs b/src/Umbraco.Core/Deploy/IServiceConnector.cs index dfc4f3d28e..3f789e2e38 100644 --- a/src/Umbraco.Core/Deploy/IServiceConnector.cs +++ b/src/Umbraco.Core/Deploy/IServiceConnector.cs @@ -78,7 +78,7 @@ namespace Umbraco.Cms.Core.Deploy /// A collection of differences to append to, if not null. /// A boolean value indicating whether the artifacts are identical. /// ServiceConnectorBase{TArtifact} provides a very basic default implementation. - bool Compare(IArtifact art1, IArtifact art2, ICollection? differences = null); + bool Compare(IArtifact? art1, IArtifact? art2, ICollection? differences = null); } } diff --git a/src/Umbraco.Core/Deploy/IValueConnector.cs b/src/Umbraco.Core/Deploy/IValueConnector.cs index 32a536a870..90896f9da4 100644 --- a/src/Umbraco.Core/Deploy/IValueConnector.cs +++ b/src/Umbraco.Core/Deploy/IValueConnector.cs @@ -32,6 +32,6 @@ namespace Umbraco.Cms.Core.Deploy /// The value property type< /// The current content property value. /// The content property value. - object? FromArtifact(string? value, IPropertyType propertyType, object currentValue); + object? FromArtifact(string? value, IPropertyType propertyType, object? currentValue); } } diff --git a/src/Umbraco.Core/Persistence/Repositories/IMemberTypeContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IMemberTypeContainerRepository.cs new file mode 100644 index 0000000000..1ccf3e756c --- /dev/null +++ b/src/Umbraco.Core/Persistence/Repositories/IMemberTypeContainerRepository.cs @@ -0,0 +1,5 @@ +namespace Umbraco.Cms.Core.Persistence.Repositories +{ + public interface IMemberTypeContainerRepository : IEntityContainerRepository + { } +} diff --git a/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs b/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs index 10775e2ce3..d97021dce0 100644 --- a/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs +++ b/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; using System.Globalization; -using System.Linq; using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Exceptions; @@ -20,12 +17,12 @@ namespace Umbraco.Cms.Core.Services where TItem : class, IContentTypeComposition { private readonly IAuditRepository _auditRepository; - private readonly IEntityContainerRepository? _containerRepository; + private readonly IEntityContainerRepository _containerRepository; private readonly IEntityRepository _entityRepository; private readonly IEventAggregator _eventAggregator; protected ContentTypeServiceBase(ICoreScopeProvider provider, ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, - TRepository repository, IAuditRepository auditRepository, IEntityContainerRepository? containerRepository, IEntityRepository entityRepository, + TRepository repository, IAuditRepository auditRepository, IEntityContainerRepository containerRepository, IEntityRepository entityRepository, IEventAggregator eventAggregator) : base(provider, loggerFactory, eventMessagesFactory) { @@ -943,7 +940,7 @@ namespace Umbraco.Cms.Core.Services { scope.ReadLock(ReadLockIds); // also for containers - return _containerRepository?.Get(containerId); + return _containerRepository.Get(containerId); } } @@ -953,42 +950,37 @@ namespace Umbraco.Cms.Core.Services { scope.ReadLock(ReadLockIds); // also for containers - return _containerRepository?.Get(containerId); + return _containerRepository.Get(containerId); } } - public IEnumerable? GetContainers(int[] containerIds) + public IEnumerable GetContainers(int[] containerIds) { using (var scope = ScopeProvider.CreateCoreScope(autoComplete: true)) { scope.ReadLock(ReadLockIds); // also for containers - return _containerRepository?.GetMany(containerIds); + return _containerRepository.GetMany(containerIds); } } - public IEnumerable? GetContainers(TItem? item) + public IEnumerable GetContainers(TItem item) { - var ancestorIds = item?.Path.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries) + var ancestorIds = item.Path.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries) .Select(x => int.TryParse(x, NumberStyles.Integer, CultureInfo.InvariantCulture, out var asInt) ? asInt : int.MinValue) .Where(x => x != int.MinValue && x != item.Id) .ToArray(); - if (ancestorIds is null) - { - return null; - } - return GetContainers(ancestorIds); } - public IEnumerable? GetContainers(string name, int level) + public IEnumerable GetContainers(string name, int level) { using (var scope = ScopeProvider.CreateCoreScope(autoComplete: true)) { scope.ReadLock(ReadLockIds); // also for containers - return _containerRepository?.Get(name, level); + return _containerRepository.Get(name, level); } } diff --git a/src/Umbraco.Core/Services/EntityXmlSerializer.cs b/src/Umbraco.Core/Services/EntityXmlSerializer.cs index 8123dd06da..c91f536b38 100644 --- a/src/Umbraco.Core/Services/EntityXmlSerializer.cs +++ b/src/Umbraco.Core/Services/EntityXmlSerializer.cs @@ -522,14 +522,11 @@ namespace Umbraco.Cms.Core.Services if (contentType.Level != 1 && masterContentType == null) { //get URL encoded folder names - var folders = _contentTypeService.GetContainers(contentType)? + IOrderedEnumerable folders = _contentTypeService.GetContainers(contentType) .OrderBy(x => x.Level); - if (folders is not null) - { - folderNames = string.Join("/", folders.Select(x => WebUtility.UrlEncode(x.Name)).ToArray()); - folderKeys = string.Join("/", folders.Select(x => x.Key).ToArray()); - } + folderNames = string.Join("/", folders.Select(x => WebUtility.UrlEncode(x.Name)).ToArray()); + folderKeys = string.Join("/", folders.Select(x => x.Key).ToArray()); } if (string.IsNullOrWhiteSpace(folderNames) == false) diff --git a/src/Umbraco.Core/Services/IContentTypeServiceBase.cs b/src/Umbraco.Core/Services/IContentTypeServiceBase.cs index c0d5bb96a0..5614d87bf3 100644 --- a/src/Umbraco.Core/Services/IContentTypeServiceBase.cs +++ b/src/Umbraco.Core/Services/IContentTypeServiceBase.cs @@ -82,9 +82,9 @@ namespace Umbraco.Cms.Core.Services Attempt SaveContainer(EntityContainer container, int userId = Constants.Security.SuperUserId); EntityContainer? GetContainer(int containerId); EntityContainer? GetContainer(Guid containerId); - IEnumerable? GetContainers(int[] containerIds); - IEnumerable? GetContainers(TItem? contentType); - IEnumerable? GetContainers(string folderName, int level); + IEnumerable GetContainers(int[] containerIds); + IEnumerable GetContainers(TItem contentType); + IEnumerable GetContainers(string folderName, int level); Attempt DeleteContainer(int containerId, int userId = Constants.Security.SuperUserId); Attempt?> RenameContainer(int id, string name, int userId = Constants.Security.SuperUserId); diff --git a/src/Umbraco.Core/Services/IRelationService.cs b/src/Umbraco.Core/Services/IRelationService.cs index c4060cd695..a0825611f7 100644 --- a/src/Umbraco.Core/Services/IRelationService.cs +++ b/src/Umbraco.Core/Services/IRelationService.cs @@ -129,9 +129,9 @@ namespace Umbraco.Cms.Core.Services /// /// Id of the child or parent to retrieve relations for /// An enumerable list of objects - IEnumerable? GetByParentOrChildId(int id); + IEnumerable GetByParentOrChildId(int id); - IEnumerable? GetByParentOrChildId(int id, string relationTypeAlias); + IEnumerable GetByParentOrChildId(int id, string relationTypeAlias); /// /// Gets a relation by the unique combination of parentId, childId and relationType. diff --git a/src/Umbraco.Core/Services/MemberTypeService.cs b/src/Umbraco.Core/Services/MemberTypeService.cs index 1157d42466..1d42989841 100644 --- a/src/Umbraco.Core/Services/MemberTypeService.cs +++ b/src/Umbraco.Core/Services/MemberTypeService.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; @@ -7,6 +6,7 @@ using Umbraco.Cms.Core.Notifications; using Umbraco.Cms.Core.Persistence.Repositories; using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Core.Services.Changes; +using Umbraco.Cms.Web.Common.DependencyInjection; using Umbraco.Extensions; namespace Umbraco.Cms.Core.Services @@ -15,9 +15,16 @@ namespace Umbraco.Cms.Core.Services { private readonly IMemberTypeRepository _memberTypeRepository; + [Obsolete("Please use the constructor taking all parameters. This constructor will be removed in V12.")] public MemberTypeService(ICoreScopeProvider provider, ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, IMemberService memberService, IMemberTypeRepository memberTypeRepository, IAuditRepository auditRepository, IEntityRepository entityRepository, IEventAggregator eventAggregator) - : base(provider, loggerFactory, eventMessagesFactory, memberTypeRepository, auditRepository, null, entityRepository, eventAggregator) + : this(provider, loggerFactory, eventMessagesFactory, memberService, memberTypeRepository, auditRepository, StaticServiceProvider.Instance.GetRequiredService(), entityRepository, eventAggregator) + { + } + + public MemberTypeService(ICoreScopeProvider provider, ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, IMemberService memberService, + IMemberTypeRepository memberTypeRepository, IAuditRepository auditRepository, IMemberTypeContainerRepository entityContainerRepository, IEntityRepository entityRepository, IEventAggregator eventAggregator) + : base(provider, loggerFactory, eventMessagesFactory, memberTypeRepository, auditRepository, entityContainerRepository, entityRepository, eventAggregator) { MemberService = memberService; _memberTypeRepository = memberTypeRepository; diff --git a/src/Umbraco.Core/Services/RelationService.cs b/src/Umbraco.Core/Services/RelationService.cs index 90762c3c74..966e4ec7df 100644 --- a/src/Umbraco.Core/Services/RelationService.cs +++ b/src/Umbraco.Core/Services/RelationService.cs @@ -153,7 +153,7 @@ namespace Umbraco.Cms.Core.Services public IEnumerable GetByChild(IUmbracoEntity child, string relationTypeAlias) => GetByChildId(child.Id, relationTypeAlias); /// - public IEnumerable? GetByParentOrChildId(int id) + public IEnumerable GetByParentOrChildId(int id) { using (var scope = ScopeProvider.CreateCoreScope(autoComplete: true)) { @@ -162,7 +162,7 @@ namespace Umbraco.Cms.Core.Services } } - public IEnumerable? GetByParentOrChildId(int id, string relationTypeAlias) + public IEnumerable GetByParentOrChildId(int id, string relationTypeAlias) { using (var scope = ScopeProvider.CreateCoreScope(autoComplete: true)) { diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Repositories.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Repositories.cs index f1d3e38ac2..9d85594eb2 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Repositories.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Repositories.cs @@ -43,6 +43,7 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection builder.Services.AddUnique(); builder.Services.AddUnique(); builder.Services.AddUnique(); + builder.Services.AddUnique(); builder.Services.AddUnique(); builder.Services.AddUnique(); builder.Services.AddUnique(); diff --git a/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs b/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs index 69271baf2c..f0bca5f1ea 100644 --- a/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs +++ b/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs @@ -687,7 +687,7 @@ namespace Umbraco.Cms.Infrastructure.Packaging // The folder might already exist, but with a different key, so check if it exists, even if there is a key. // Level 1 = root level folders, there can only be one with the same name - current ??= _contentTypeService.GetContainers(rootFolder, 1)?.FirstOrDefault(); + current ??= _contentTypeService.GetContainers(rootFolder, 1).FirstOrDefault(); if (current == null) { diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberTypeContainerRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberTypeContainerRepository.cs new file mode 100644 index 0000000000..dbde4e1f5b --- /dev/null +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberTypeContainerRepository.cs @@ -0,0 +1,32 @@ +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Persistence.Repositories; + +namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement +{ + /// + /// A no-op implementation of , as containers aren't supported for members. + /// + /// + /// Introduced to avoid inconsistencies with nullability of dependencies for type repositories for content, media and members. + /// + internal class MemberTypeContainerRepository : IMemberTypeContainerRepository + { + public void Delete(EntityContainer entity) + { + } + + public bool Exists(int id) => false; + + public EntityContainer? Get(Guid id) => null; + + public IEnumerable Get(string name, int level) => Enumerable.Empty(); + + public EntityContainer? Get(int id) => null; + + public IEnumerable GetMany(params int[]? ids) => Enumerable.Empty(); + + public void Save(EntityContainer entity) + { + } + } +} diff --git a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeControllerBase.cs b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeControllerBase.cs index 6e06a0e21b..4a09276442 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeControllerBase.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeControllerBase.cs @@ -165,9 +165,9 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers } IContentTypeComposition? contentType = allContentTypes.FirstOrDefault(c => c.Key == x.Item1?.Key); - EntityContainer[]? containers = GetEntityContainers(contentType, type)?.ToArray(); + EntityContainer[] containers = GetEntityContainers(contentType, type).ToArray(); var containerPath = - $"/{(containers != null && containers.Any() ? $"{string.Join("/", containers.Select(c => c.Name))}/" : null)}"; + $"/{(containers.Any() ? $"{string.Join("/", containers.Select(c => c.Name))}/" : null)}"; if (x.Item1 is not null) { x.Item1.AdditionalData["containerPath"] = containerPath; @@ -178,22 +178,32 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers .ToList(); } - private IEnumerable? GetEntityContainers(IContentTypeComposition? contentType, + private IEnumerable GetEntityContainers(IContentTypeComposition? contentType, UmbracoObjectTypes type) { if (contentType == null) { - return null; + return Enumerable.Empty(); } switch (type) { case UmbracoObjectTypes.DocumentType: - return ContentTypeService.GetContainers(contentType as IContentType); + if (contentType is IContentType documentContentType) + { + return ContentTypeService.GetContainers(documentContentType); + } + + return Enumerable.Empty(); case UmbracoObjectTypes.MediaType: - return MediaTypeService.GetContainers(contentType as IMediaType); + if (contentType is IMediaType mediaContentType) + { + return MediaTypeService.GetContainers(mediaContentType); + } + + return Enumerable.Empty(); case UmbracoObjectTypes.MemberType: - return new EntityContainer[0]; + return Enumerable.Empty(); default: throw new ArgumentOutOfRangeException("The entity type was not a content type"); }