diff --git a/src/Umbraco.Core/Attempt.cs b/src/Umbraco.Core/Attempt.cs index f9c254b9d4..71eabd2f0d 100644 --- a/src/Umbraco.Core/Attempt.cs +++ b/src/Umbraco.Core/Attempt.cs @@ -76,7 +76,7 @@ namespace Umbraco.Cms.Core /// The result of the attempt. /// The exception causing the failure of the attempt. /// The failed attempt. - public static Attempt Fail(TResult result, Exception exception) + public static Attempt Fail(TResult result, Exception exception) { return Attempt.Fail(result, exception); } diff --git a/src/Umbraco.Core/AttemptOfTResult.cs b/src/Umbraco.Core/AttemptOfTResult.cs index 97950a60c5..dc143a4353 100644 --- a/src/Umbraco.Core/AttemptOfTResult.cs +++ b/src/Umbraco.Core/AttemptOfTResult.cs @@ -102,9 +102,9 @@ namespace Umbraco.Cms.Core /// The result of the attempt. /// The exception causing the failure of the attempt. /// The failed attempt. - public static Attempt Fail(TResult result, Exception exception) + public static Attempt Fail(TResult result, Exception exception) { - return new Attempt(false, result, exception); + return new Attempt(false, result, exception); } /// diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs index 91e6f71415..58c57eb668 100644 --- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs @@ -17,7 +17,7 @@ namespace Umbraco.Cms.Core.DependencyInjection public static partial class UmbracoBuilderExtensions { - private static IUmbracoBuilder AddUmbracoOptions(this IUmbracoBuilder builder, Action> configure = null) + private static IUmbracoBuilder AddUmbracoOptions(this IUmbracoBuilder builder, Action>? configure = null) where TOptions : class { var umbracoOptionsAttribute = typeof(TOptions).GetCustomAttribute(); diff --git a/src/Umbraco.Core/Enum.cs b/src/Umbraco.Core/Enum.cs index 90de399300..787d157254 100644 --- a/src/Umbraco.Core/Enum.cs +++ b/src/Umbraco.Core/Enum.cs @@ -33,9 +33,9 @@ namespace Umbraco.Cms.Core var name = value.ToString(); IntToValue[Convert.ToInt32(value)] = value; - ValueToName[value] = name; - SensitiveNameToValue[name] = value; - InsensitiveNameToValue[name.ToLowerInvariant()] = value; + ValueToName[value] = name!; + SensitiveNameToValue[name!] = value; + InsensitiveNameToValue[name!.ToLowerInvariant()] = value; } } diff --git a/src/Umbraco.Core/Extensions/ContentExtensions.cs b/src/Umbraco.Core/Extensions/ContentExtensions.cs index fa85fa5420..4c574ca3c4 100644 --- a/src/Umbraco.Core/Extensions/ContentExtensions.cs +++ b/src/Umbraco.Core/Extensions/ContentExtensions.cs @@ -310,7 +310,7 @@ namespace Umbraco.Extensions return property; var contentType = contentTypeBaseServiceProvider.GetContentTypeOf(content); - var propertyType = contentType.CompositionPropertyTypes + var propertyType = contentType?.CompositionPropertyTypes .FirstOrDefault(x => x.Alias?.InvariantEquals(propertyTypeAlias) ?? false); if (propertyType == null) throw new Exception("No property type exists with alias " + propertyTypeAlias + "."); @@ -339,7 +339,7 @@ namespace Umbraco.Extensions public static string StoreFile(this IContentBase content, MediaFileManager mediaFileManager, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, string propertyTypeAlias, string filename, Stream filestream, string filepath) { var contentType = contentTypeBaseServiceProvider.GetContentTypeOf(content); - var propertyType = contentType + var propertyType = contentType? .CompositionPropertyTypes.FirstOrDefault(x => x.Alias?.InvariantEquals(propertyTypeAlias) ?? false); if (propertyType == null) throw new ArgumentException("Invalid property type alias " + propertyTypeAlias + "."); diff --git a/src/Umbraco.Core/Mapping/IUmbracoMapper.cs b/src/Umbraco.Core/Mapping/IUmbracoMapper.cs index 7a0448b036..fdf6e099c9 100644 --- a/src/Umbraco.Core/Mapping/IUmbracoMapper.cs +++ b/src/Umbraco.Core/Mapping/IUmbracoMapper.cs @@ -90,7 +90,7 @@ namespace Umbraco.Cms.Core.Mapping /// The source object. /// A mapper context. /// The target object. - TTarget Map(TSource source, MapperContext context); + TTarget Map(TSource? source, MapperContext context); /// /// Maps a source object to an existing target object. diff --git a/src/Umbraco.Core/Mapping/MapperContext.cs b/src/Umbraco.Core/Mapping/MapperContext.cs index 8c0413ada2..4bc4455e67 100644 --- a/src/Umbraco.Core/Mapping/MapperContext.cs +++ b/src/Umbraco.Core/Mapping/MapperContext.cs @@ -63,7 +63,7 @@ namespace Umbraco.Cms.Core.Mapping /// The target type. /// The source object. /// The target object. - public TTarget Map(TSource source) + public TTarget Map(TSource? source) => _mapper.Map(source, this); // let's say this is a bad (dangerous) idea, and leave it out for now diff --git a/src/Umbraco.Core/Media/Exif/ExifFileTypeDescriptor.cs b/src/Umbraco.Core/Media/Exif/ExifFileTypeDescriptor.cs index 92b0a16dc3..61d6b70f30 100644 --- a/src/Umbraco.Core/Media/Exif/ExifFileTypeDescriptor.cs +++ b/src/Umbraco.Core/Media/Exif/ExifFileTypeDescriptor.cs @@ -38,14 +38,14 @@ namespace Umbraco.Cms.Core.Media.Exif /// internal sealed class ExifFileTypeDescriptor : CustomTypeDescriptor { - ImageFile owner; + ImageFile? owner; - public ExifFileTypeDescriptor(ICustomTypeDescriptor parent, object instance) + public ExifFileTypeDescriptor(ICustomTypeDescriptor? parent, object? instance) : base(parent) { - owner = (ImageFile)instance; + owner = (ImageFile?)instance; } - public override PropertyDescriptorCollection GetProperties(Attribute[] attributes) + public override PropertyDescriptorCollection GetProperties(Attribute[]? attributes) { return GetProperties(); } @@ -60,10 +60,13 @@ namespace Umbraco.Cms.Core.Media.Exif // Enumerate the original set of properties and create our new set with it List properties = new List(); - foreach (ExifProperty prop in owner.Properties) + if (owner is not null) { - ExifPropertyDescriptor pd = new ExifPropertyDescriptor(prop); - properties.Add(pd); + foreach (ExifProperty prop in owner.Properties) + { + ExifPropertyDescriptor pd = new ExifPropertyDescriptor(prop); + properties.Add(pd); + } } // Finally return the list @@ -92,7 +95,7 @@ namespace Umbraco.Cms.Core.Media.Exif get { return typeof(JPEGFile); } } - public override object GetValue(object component) + public override object GetValue(object? component) { return linkedProperty.Value; } @@ -112,9 +115,12 @@ namespace Umbraco.Cms.Core.Media.Exif linkedProperty.Value = originalValue; } - public override void SetValue(object component, object value) + public override void SetValue(object? component, object? value) { - linkedProperty.Value = value; + if (value is not null) + { + linkedProperty.Value = value; + } } public override bool ShouldSerializeValue(object component) diff --git a/src/Umbraco.Core/Media/Exif/ExifProperty.cs b/src/Umbraco.Core/Media/Exif/ExifProperty.cs index d530e494b0..a3c28aabbc 100644 --- a/src/Umbraco.Core/Media/Exif/ExifProperty.cs +++ b/src/Umbraco.Core/Media/Exif/ExifProperty.cs @@ -10,7 +10,7 @@ namespace Umbraco.Cms.Core.Media.Exif { protected ExifTag mTag; protected IFD mIFD; - protected string mName; + protected string? mName; /// /// Gets the Exif tag associated with this property. diff --git a/src/Umbraco.Core/Models/AuditItem.cs b/src/Umbraco.Core/Models/AuditItem.cs index 6eca2ae185..83ecad0878 100644 --- a/src/Umbraco.Core/Models/AuditItem.cs +++ b/src/Umbraco.Core/Models/AuditItem.cs @@ -7,7 +7,7 @@ namespace Umbraco.Cms.Core.Models /// /// Initializes a new instance of the class. /// - public AuditItem(int objectId, AuditType type, int userId, string entityType, string? comment = null, string? parameters = null) + public AuditItem(int objectId, AuditType type, int userId, string? entityType, string? comment = null, string? parameters = null) { DisableChangeTracking(); @@ -25,7 +25,7 @@ namespace Umbraco.Cms.Core.Models public AuditType AuditType { get; } /// - public string EntityType { get; } + public string? EntityType { get; } /// public int UserId { get; } diff --git a/src/Umbraco.Core/Models/ContentRepositoryExtensions.cs b/src/Umbraco.Core/Models/ContentRepositoryExtensions.cs index 520fec3afe..7dcaee86b4 100644 --- a/src/Umbraco.Core/Models/ContentRepositoryExtensions.cs +++ b/src/Umbraco.Core/Models/ContentRepositoryExtensions.cs @@ -230,7 +230,7 @@ namespace Umbraco.Extensions /// /// A value indicating whether it was possible to publish the names and values for the specified /// culture(s). The method may fail if required names are not set, but it does NOT validate property data - public static bool PublishCulture(this IContent content, CultureImpact impact) + public static bool PublishCulture(this IContent content, CultureImpact? impact) { if (impact == null) throw new ArgumentNullException(nameof(impact)); diff --git a/src/Umbraco.Core/Models/IAuditItem.cs b/src/Umbraco.Core/Models/IAuditItem.cs index 9a70a11428..dbc7ad1fd4 100644 --- a/src/Umbraco.Core/Models/IAuditItem.cs +++ b/src/Umbraco.Core/Models/IAuditItem.cs @@ -15,7 +15,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets the audited entity type. /// - string EntityType { get; } + string? EntityType { get; } /// /// Gets the audit user identifier. diff --git a/src/Umbraco.Core/Models/IDataValueEditor.cs b/src/Umbraco.Core/Models/IDataValueEditor.cs index fb15fa530d..41fbaa6c25 100644 --- a/src/Umbraco.Core/Models/IDataValueEditor.cs +++ b/src/Umbraco.Core/Models/IDataValueEditor.cs @@ -40,7 +40,7 @@ namespace Umbraco.Cms.Core.Models /// The property value. /// A value indicating whether the property value is required. /// A specific format (regex) that the property value must respect. - IEnumerable Validate(object value, bool required, string format); + IEnumerable Validate(object value, bool required, string? format); /// /// Gets the validators to use to validate the edited value. diff --git a/src/Umbraco.Core/Models/Mapping/ContentTypeMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/ContentTypeMapDefinition.cs index 2bea03098d..801aa746c0 100644 --- a/src/Umbraco.Core/Models/Mapping/ContentTypeMapDefinition.cs +++ b/src/Umbraco.Core/Models/Mapping/ContentTypeMapDefinition.cs @@ -702,7 +702,7 @@ namespace Umbraco.Cms.Core.Models.Mapping return Enumerable.Empty(); } - IContentType parent = _contentTypeService.Get(source.ParentId); + IContentType? parent = _contentTypeService.Get(source.ParentId); if (parent == null) { return Enumerable.Empty(); diff --git a/src/Umbraco.Core/Models/Mapping/MemberTabsAndPropertiesMapper.cs b/src/Umbraco.Core/Models/Mapping/MemberTabsAndPropertiesMapper.cs index 0bb0f8b60f..2021afa4c2 100644 --- a/src/Umbraco.Core/Models/Mapping/MemberTabsAndPropertiesMapper.cs +++ b/src/Umbraco.Core/Models/Mapping/MemberTabsAndPropertiesMapper.cs @@ -59,15 +59,19 @@ namespace Umbraco.Cms.Core.Models.Mapping var memberType = _memberTypeService.Get(source.ContentTypeId); - IgnoreProperties = memberType.CompositionPropertyTypes - .Where(x => x.HasIdentity == false) - .Select(x => x.Alias) - .ToArray(); + if (memberType is not null) + { + + IgnoreProperties = memberType.CompositionPropertyTypes + .Where(x => x.HasIdentity == false) + .Select(x => x.Alias) + .ToArray(); + } var resolved = base.Map(source, context); // IMember.IsLockedOut can't be set to true, so make it readonly when that's the case (you can only unlock) - var isLockedOutProperty = resolved.Where(x => x.Properties is not null).SelectMany(x => x.Properties).FirstOrDefault(x => x.Alias == Constants.Conventions.Member.IsLockedOut); + var isLockedOutProperty = resolved.Where(x => x.Properties is not null).SelectMany(x => x.Properties!).FirstOrDefault(x => x.Alias == Constants.Conventions.Member.IsLockedOut); if (isLockedOutProperty?.Value != null && isLockedOutProperty.Value.ToString() != "1") { isLockedOutProperty.Readonly = true; @@ -115,7 +119,7 @@ namespace Umbraco.Cms.Core.Models.Mapping foreach (var prop in result) { // check if this property is flagged as sensitive - var isSensitiveProperty = memberType.IsSensitiveProperty(prop.Alias); + var isSensitiveProperty = memberType?.IsSensitiveProperty(prop.Alias) ?? false; // check permissions for viewing sensitive data if (isSensitiveProperty && (_backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser.HasAccessToSensitiveData() == false)) { diff --git a/src/Umbraco.Core/Models/Mapping/TabsAndPropertiesMapper.cs b/src/Umbraco.Core/Models/Mapping/TabsAndPropertiesMapper.cs index d42e5f69df..e3f1c9e938 100644 --- a/src/Umbraco.Core/Models/Mapping/TabsAndPropertiesMapper.cs +++ b/src/Umbraco.Core/Models/Mapping/TabsAndPropertiesMapper.cs @@ -109,39 +109,42 @@ namespace Umbraco.Cms.Core.Models.Mapping var contentType = _contentTypeBaseServiceProvider.GetContentTypeOf(source); // Merge the groups, as compositions can introduce duplicate aliases - var groups = contentType.CompositionPropertyGroups.OrderBy(x => x.SortOrder).ToArray(); - var parentAliases = groups.Select(x => x.GetParentAlias()).Distinct().ToArray(); - foreach (var groupsByAlias in groups.GroupBy(x => x.Alias)) + var groups = contentType?.CompositionPropertyGroups.OrderBy(x => x.SortOrder).ToArray(); + var parentAliases = groups?.Select(x => x.GetParentAlias()).Distinct().ToArray(); + if (groups is not null) { - var properties = new List(); - - // Merge properties for groups with the same alias - foreach (var group in groupsByAlias) + foreach (var groupsByAlias in groups.GroupBy(x => x.Alias)) { - var groupProperties = source.GetPropertiesForGroup(group) - .Where(x => IgnoreProperties.Contains(x.Alias) == false); // Skip ignored properties + var properties = new List(); - properties.AddRange(groupProperties); + // Merge properties for groups with the same alias + foreach (var group in groupsByAlias) + { + var groupProperties = source.GetPropertiesForGroup(group) + .Where(x => IgnoreProperties.Contains(x.Alias) == false); // Skip ignored properties + + properties.AddRange(groupProperties); + } + + if (properties.Count == 0 && (!parentAliases?.Contains(groupsByAlias.Key) ?? false)) + continue; + + // Map the properties + var mappedProperties = MapProperties(source, properties, context); + + // Add the tab (the first is closest to the content type, e.g. local, then direct composition) + var g = groupsByAlias.First(); + + tabs.Add(new Tab + { + Id = g.Id, + Key = g.Key, + Type = g.Type.ToString(), + Alias = g.Alias, + Label = LocalizedTextService.UmbracoDictionaryTranslate(CultureDictionary, g.Name), + Properties = mappedProperties + }); } - - if (properties.Count == 0 && !parentAliases.Contains(groupsByAlias.Key)) - continue; - - // Map the properties - var mappedProperties = MapProperties(source, properties, context); - - // Add the tab (the first is closest to the content type, e.g. local, then direct composition) - var g = groupsByAlias.First(); - - tabs.Add(new Tab - { - Id = g.Id, - Key = g.Key, - Type = g.Type.ToString(), - Alias = g.Alias, - Label = LocalizedTextService.UmbracoDictionaryTranslate(CultureDictionary, g.Name), - Properties = mappedProperties - }); } MapGenericProperties(source, tabs, context); diff --git a/src/Umbraco.Core/Models/Membership/IMembershipUser.cs b/src/Umbraco.Core/Models/Membership/IMembershipUser.cs index 29f0d320a5..b4a38479f6 100644 --- a/src/Umbraco.Core/Models/Membership/IMembershipUser.cs +++ b/src/Umbraco.Core/Models/Membership/IMembershipUser.cs @@ -8,8 +8,8 @@ namespace Umbraco.Cms.Core.Models.Membership /// public interface IMembershipUser : IEntity { - string? Username { get; set; } - string? Email { get; set; } + string Username { get; set; } + string Email { get; set; } DateTime? EmailConfirmedDate { get; set; } /// diff --git a/src/Umbraco.Core/Models/Membership/IUser.cs b/src/Umbraco.Core/Models/Membership/IUser.cs index c7c68dabda..ca41d892e7 100644 --- a/src/Umbraco.Core/Models/Membership/IUser.cs +++ b/src/Umbraco.Core/Models/Membership/IUser.cs @@ -13,7 +13,7 @@ namespace Umbraco.Cms.Core.Models.Membership { UserState UserState { get; } - string? Name { get; set; } + string Name { get; set; } int SessionTimeout { get; set; } int[]? StartContentIds { get; set; } int[]? StartMediaIds { get; set; } diff --git a/src/Umbraco.Core/Persistence/Repositories/IContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IContentRepository.cs index dca545d197..be12da3203 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IContentRepository.cs @@ -59,24 +59,24 @@ namespace Umbraco.Cms.Core.Persistence.Repositories /// /// Gets the count of content items of a given content type. /// - int Count(string contentTypeAlias = null); + int Count(string? contentTypeAlias = null); /// /// Gets the count of child content items of a given parent content, of a given content type. /// - int CountChildren(int parentId, string contentTypeAlias = null); + int CountChildren(int parentId, string? contentTypeAlias = null); /// /// Gets the count of descendant content items of a given parent content, of a given content type. /// - int CountDescendants(int parentId, string contentTypeAlias = null); + int CountDescendants(int parentId, string? contentTypeAlias = null); /// /// Gets paged content items. /// /// Here, can be null but cannot. - IEnumerable GetPage(IQuery query, long pageIndex, int pageSize, out long totalRecords, - IQuery filter, Ordering ordering); + IEnumerable GetPage(IQuery? query, long pageIndex, int pageSize, out long totalRecords, + IQuery? filter, Ordering? ordering); ContentDataIntegrityReport CheckDataIntegrity(ContentDataIntegrityReportOptions options); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IDocumentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IDocumentRepository.cs index 0aebfa28a5..e0b7f234ec 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IDocumentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IDocumentRepository.cs @@ -56,9 +56,9 @@ namespace Umbraco.Cms.Core.Persistence.Repositories /// /// We require this on the repo because the IQuery{IContent} cannot supply the 'newest' parameter /// - int CountPublished(string contentTypeAlias = null); + int CountPublished(string? contentTypeAlias = null); - bool IsPathPublished(IContent content); + bool IsPathPublished(IContent? content); /// /// Used to bulk update the permissions set for a content item. This will replace all permissions diff --git a/src/Umbraco.Core/Persistence/Repositories/IEntityRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IEntityRepository.cs index 800981540b..30efd080d9 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IEntityRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IEntityRepository.cs @@ -36,7 +36,7 @@ namespace Umbraco.Cms.Core.Persistence.Repositories UmbracoObjectTypes GetObjectType(Guid key); int ReserveId(Guid key); - IEnumerable GetAllPaths(Guid objectType, params int[] ids); + IEnumerable GetAllPaths(Guid objectType, params int[]? ids); IEnumerable GetAllPaths(Guid objectType, params Guid[] keys); bool Exists(int id); @@ -54,6 +54,6 @@ namespace Umbraco.Cms.Core.Persistence.Repositories /// /// IEnumerable GetPagedResultsByQuery(IQuery query, Guid objectType, long pageIndex, int pageSize, out long totalRecords, - IQuery filter, Ordering ordering); + IQuery? filter, Ordering? ordering); } } diff --git a/src/Umbraco.Core/Persistence/Repositories/ILanguageRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ILanguageRepository.cs index 0ea0638d9f..eeaeed82bb 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ILanguageRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ILanguageRepository.cs @@ -12,7 +12,7 @@ namespace Umbraco.Cms.Core.Persistence.Repositories /// /// This can be optimized and bypass all deep cloning. /// - int? GetIdByIsoCode(string isoCode, bool throwOnNotFound = true); + int? GetIdByIsoCode(string? isoCode, bool throwOnNotFound = true); /// /// Gets a language ISO code from its identifier. diff --git a/src/Umbraco.Core/Persistence/Repositories/IRedirectUrlRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IRedirectUrlRepository.cs index 3a4e5f900b..d02fe72bc8 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IRedirectUrlRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IRedirectUrlRepository.cs @@ -16,7 +16,7 @@ namespace Umbraco.Cms.Core.Persistence.Repositories /// The content unique key. /// The culture. /// - IRedirectUrl Get(string url, Guid contentKey, string culture); + IRedirectUrl Get(string url, Guid contentKey, string? culture); /// /// Deletes a redirect URL. diff --git a/src/Umbraco.Core/Persistence/Repositories/IRelationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IRelationRepository.cs index cff64d4a79..8328038d19 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IRelationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IRelationRepository.cs @@ -9,7 +9,7 @@ namespace Umbraco.Cms.Core.Persistence.Repositories { public interface IRelationRepository : IReadWriteQueryRepository { - IEnumerable GetPagedRelationsByQuery(IQuery query, long pageIndex, int pageSize, out long totalRecords, Ordering ordering); + IEnumerable GetPagedRelationsByQuery(IQuery query, long pageIndex, int pageSize, out long totalRecords, Ordering? ordering); /// /// Persist multiple at once diff --git a/src/Umbraco.Core/Persistence/Repositories/ITemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ITemplateRepository.cs index 3c9174e818..34b061a50e 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ITemplateRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ITemplateRepository.cs @@ -5,7 +5,7 @@ namespace Umbraco.Cms.Core.Persistence.Repositories { public interface ITemplateRepository : IReadWriteQueryRepository, IFileRepository { - ITemplate Get(string alias); + ITemplate Get(string? alias); IEnumerable GetAll(params string[] aliases); diff --git a/src/Umbraco.Core/Persistence/Repositories/IUserGroupRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IUserGroupRepository.cs index 7bb42cb774..6f2cd75bdb 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IUserGroupRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IUserGroupRepository.cs @@ -23,7 +23,7 @@ namespace Umbraco.Cms.Core.Persistence.Repositories /// /// /// - void AddOrUpdateGroupWithUsers(IUserGroup userGroup, int[] userIds); + void AddOrUpdateGroupWithUsers(IUserGroup userGroup, int[]? userIds); /// /// Gets explicitly defined permissions for the group for specified entities @@ -46,7 +46,7 @@ namespace Umbraco.Cms.Core.Persistence.Repositories /// Id of group /// Permissions as enumerable list of /// Specify the nodes to replace permissions for. If nothing is specified all permissions are removed. - void ReplaceGroupPermissions(int groupId, IEnumerable permissions, params int[] entityIds); + void ReplaceGroupPermissions(int groupId, IEnumerable? permissions, params int[] entityIds); /// /// Assigns the same permission set for a single group to any number of entities diff --git a/src/Umbraco.Core/Persistence/Repositories/IUserRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IUserRepository.cs index 3552400b14..1c74f8430e 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IUserRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IUserRepository.cs @@ -68,8 +68,8 @@ namespace Umbraco.Cms.Core.Persistence.Repositories /// Optional parameter to filter by specified user state /// /// - IEnumerable GetPagedResultsByQuery(IQuery query, long pageIndex, int pageSize, out long totalRecords, - Expression> orderBy, Direction orderDirection = Direction.Ascending, + IEnumerable GetPagedResultsByQuery(IQuery? query, long pageIndex, int pageSize, out long totalRecords, + Expression> orderBy, Direction orderDirection = Direction.Ascending, string[]? includeUserGroups = null, string[]? excludeUserGroups = null, UserState[]? userState = null, IQuery? filter = null); diff --git a/src/Umbraco.Core/Persistence/SqlExpressionExtensions.cs b/src/Umbraco.Core/Persistence/SqlExpressionExtensions.cs index 321e40cb88..8eb27f1a81 100644 --- a/src/Umbraco.Core/Persistence/SqlExpressionExtensions.cs +++ b/src/Umbraco.Core/Persistence/SqlExpressionExtensions.cs @@ -41,7 +41,7 @@ namespace Umbraco.Cms.Core.Persistence public static bool SqlEquals(this string str, string txt, TextColumnType columnType) => str.InvariantEquals(txt); - public static bool SqlStartsWith(this string str, string txt, TextColumnType columnType) => str.InvariantStartsWith(txt); + public static bool SqlStartsWith(this string? str, string txt, TextColumnType columnType) => str?.InvariantStartsWith(txt) ?? false; public static bool SqlEndsWith(this string str, string txt, TextColumnType columnType) => str.InvariantEndsWith(txt); #pragma warning restore IDE0060 // Remove unused parameter diff --git a/src/Umbraco.Core/Scoping/IScopeProvider.cs b/src/Umbraco.Core/Scoping/IScopeProvider.cs index c12680763f..ab32ee3645 100644 --- a/src/Umbraco.Core/Scoping/IScopeProvider.cs +++ b/src/Umbraco.Core/Scoping/IScopeProvider.cs @@ -34,7 +34,7 @@ namespace Umbraco.Cms.Core.Scoping IScope CreateScope( IsolationLevel isolationLevel = IsolationLevel.Unspecified, RepositoryCacheMode repositoryCacheMode = RepositoryCacheMode.Unspecified, - IScopedNotificationPublisher scopedNotificationPublisher = null, + IScopedNotificationPublisher? scopedNotificationPublisher = null, bool? scopeFileSystems = null, bool callContext = false, bool autoComplete = false); @@ -55,7 +55,7 @@ namespace Umbraco.Cms.Core.Scoping IScope CreateDetachedScope( IsolationLevel isolationLevel = IsolationLevel.Unspecified, RepositoryCacheMode repositoryCacheMode = RepositoryCacheMode.Unspecified, - IScopedNotificationPublisher scopedNotificationPublisher = null, + IScopedNotificationPublisher? scopedNotificationPublisher = null, bool? scopeFileSystems = null); /// diff --git a/src/Umbraco.Core/Services/ConsentService.cs b/src/Umbraco.Core/Services/ConsentService.cs index 0d7dc77660..5027df687b 100644 --- a/src/Umbraco.Core/Services/ConsentService.cs +++ b/src/Umbraco.Core/Services/ConsentService.cs @@ -25,7 +25,7 @@ namespace Umbraco.Cms.Core.Services } /// - public IConsent RegisterConsent(string source, string context, string action, ConsentState state, string comment = null) + public IConsent RegisterConsent(string source, string context, string action, ConsentState state, string? comment = null) { // prevent stupid states var v = 0; @@ -57,7 +57,7 @@ namespace Umbraco.Cms.Core.Services } /// - public IEnumerable LookupConsent(string source = null, string context = null, string action = null, + public IEnumerable LookupConsent(string? source = null, string? context = null, string? action = null, bool sourceStartsWith = false, bool contextStartsWith = false, bool actionStartsWith = false, bool includeHistory = false) { @@ -66,11 +66,11 @@ namespace Umbraco.Cms.Core.Services var query = Query(); if (string.IsNullOrWhiteSpace(source) == false) - query = sourceStartsWith ? query.Where(x => x.Source.StartsWith(source)) : query.Where(x => x.Source == source); + query = sourceStartsWith ? query.Where(x => x.Source!.StartsWith(source)) : query.Where(x => x.Source == source); if (string.IsNullOrWhiteSpace(context) == false) - query = contextStartsWith ? query.Where(x => x.Context.StartsWith(context)) : query.Where(x => x.Context == context); + query = contextStartsWith ? query.Where(x => x.Context!.StartsWith(context)) : query.Where(x => x.Context == context); if (string.IsNullOrWhiteSpace(action) == false) - query = actionStartsWith ? query.Where(x => x.Action.StartsWith(action)) : query.Where(x => x.Action == action); + query = actionStartsWith ? query.Where(x => x.Action!.StartsWith(action)) : query.Where(x => x.Action == action); if (includeHistory == false) query = query.Where(x => x.Current); diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index 5a73ce4c0c..65ac5689c7 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -32,7 +32,7 @@ namespace Umbraco.Cms.Core.Services private readonly ILogger _logger; private readonly Lazy _propertyValidationService; private readonly IShortStringHelper _shortStringHelper; - private IQuery _queryNotTrashed; + private IQuery? _queryNotTrashed; #region Constructors @@ -75,7 +75,7 @@ namespace Umbraco.Cms.Core.Services EventMessages evtMsgs = EventMessagesFactory.Get(); // Get the current copy of the node - IContent content = GetById(id); + IContent? content = GetById(id); // Get the version IContent version = GetVersion(versionId); @@ -134,7 +134,7 @@ namespace Umbraco.Cms.Core.Services #region Count - public int CountPublished(string contentTypeAlias = null) + public int CountPublished(string? contentTypeAlias = null) { using (IScope scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -143,7 +143,7 @@ namespace Umbraco.Cms.Core.Services } } - public int Count(string contentTypeAlias = null) + public int Count(string? contentTypeAlias = null) { using (IScope scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -152,7 +152,7 @@ namespace Umbraco.Cms.Core.Services } } - public int CountChildren(int parentId, string contentTypeAlias = null) + public int CountChildren(int parentId, string? contentTypeAlias = null) { using (IScope scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -161,7 +161,7 @@ namespace Umbraco.Cms.Core.Services } } - public int CountDescendants(int parentId, string contentTypeAlias = null) + public int CountDescendants(int parentId, string? contentTypeAlias = null) { using (IScope scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -244,7 +244,7 @@ namespace Umbraco.Cms.Core.Services { // TODO: what about culture? - IContent parent = GetById(parentId); + IContent? parent = GetById(parentId); return Create(name, parent, contentTypeAlias, userId); } @@ -291,7 +291,7 @@ namespace Umbraco.Cms.Core.Services throw new ArgumentException("Content type must be specified", nameof(contentType)); } - IContent parent = parentId > 0 ? GetById(parentId) : null; + IContent? parent = parentId > 0 ? GetById(parentId) : null; if (parentId > 0 && parent is null) { throw new ArgumentException("No content with that id.", nameof(parentId)); @@ -315,7 +315,7 @@ namespace Umbraco.Cms.Core.Services /// The alias of the content type. /// The optional id of the user creating the content. /// The content object. - public IContent Create(string name, IContent parent, string contentTypeAlias, + public IContent Create(string name, IContent? parent, string contentTypeAlias, int userId = Constants.Security.SuperUserId) { // TODO: what about culture? @@ -363,14 +363,14 @@ namespace Umbraco.Cms.Core.Services nameof(contentTypeAlias)); // causes rollback } - IContent parent = parentId > 0 ? GetById(parentId) : null; // + locks + IContent? parent = parentId > 0 ? GetById(parentId) : null; // + locks if (parentId > 0 && parent == null) { throw new ArgumentException("No content with that id.", nameof(parentId)); // causes rollback } Content content = parentId > 0 - ? new Content(name, parent, contentType, userId) + ? new Content(name, parent!, contentType, userId) : new Content(name, parentId, contentType, userId); Save(content, userId); @@ -429,7 +429,7 @@ namespace Umbraco.Cms.Core.Services /// /// /// - public IContent GetById(int id) + public IContent? GetById(int id) { using (IScope scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -460,7 +460,7 @@ namespace Umbraco.Cms.Core.Services var index = items.ToDictionary(x => x.Id, x => x); - return idsA.Select(x => index.TryGetValue(x, out IContent c) ? c : null).WhereNotNull(); + return idsA.Select(x => index.TryGetValue(x, out IContent? c) ? c : null).WhereNotNull(); } } @@ -471,7 +471,7 @@ namespace Umbraco.Cms.Core.Services /// /// /// - public IContent GetById(Guid key) + public IContent? GetById(Guid key) { using (IScope scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -505,7 +505,7 @@ namespace Umbraco.Cms.Core.Services /// /// /// - Attempt IContentServiceBase.Save(IEnumerable contents, int userId) => + Attempt IContentServiceBase.Save(IEnumerable contents, int userId) => Attempt.Succeed(Save(contents, userId)); /// @@ -530,14 +530,14 @@ namespace Umbraco.Cms.Core.Services var index = items.ToDictionary(x => x.Key, x => x); - return idsA.Select(x => index.TryGetValue(x, out IContent c) ? c : null).WhereNotNull(); + return idsA.Select(x => index.TryGetValue(x, out IContent? c) ? c : null).WhereNotNull(); } } /// public IEnumerable GetPagedOfType(int contentTypeId, long pageIndex, int pageSize, out long totalRecords - , IQuery filter = null, Ordering ordering = null) + , IQuery? filter = null, Ordering? ordering = null) { if (pageIndex < 0) { @@ -565,7 +565,7 @@ namespace Umbraco.Cms.Core.Services /// public IEnumerable GetPagedOfTypes(int[] contentTypeIds, long pageIndex, int pageSize, - out long totalRecords, IQuery filter, Ordering ordering = null) + out long totalRecords, IQuery filter, Ordering? ordering = null) { if (pageIndex < 0) { @@ -670,7 +670,7 @@ namespace Umbraco.Cms.Core.Services public IEnumerable GetAncestors(int id) { // intentionally not locking - IContent content = GetById(id); + IContent? content = GetById(id); return GetAncestors(content); } @@ -679,16 +679,16 @@ namespace Umbraco.Cms.Core.Services /// /// to retrieve ancestors for /// An Enumerable list of objects - public IEnumerable GetAncestors(IContent content) + public IEnumerable GetAncestors(IContent? content) { //null check otherwise we get exceptions - if (content.Path.IsNullOrWhiteSpace()) + if (content?.Path.IsNullOrWhiteSpace() ?? true) { return Enumerable.Empty(); } - var ids = content.GetAncestorIds().ToArray(); - if (ids.Any() == false) + var ids = content.GetAncestorIds()?.ToArray(); + if (ids?.Any() == false) { return new List(); } @@ -696,7 +696,7 @@ namespace Umbraco.Cms.Core.Services using (IScope scope = ScopeProvider.CreateScope(autoComplete: true)) { scope.ReadLock(Constants.Locks.ContentTree); - return _documentRepository.GetMany(ids); + return _documentRepository.GetMany(ids!); } } @@ -717,7 +717,7 @@ namespace Umbraco.Cms.Core.Services /// public IEnumerable GetPagedChildren(int id, long pageIndex, int pageSize, out long totalChildren, - IQuery filter = null, Ordering ordering = null) + IQuery? filter = null, Ordering? ordering = null) { if (pageIndex < 0) { @@ -745,7 +745,7 @@ namespace Umbraco.Cms.Core.Services /// public IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalChildren, - IQuery filter = null, Ordering ordering = null) + IQuery? filter = null, Ordering? ordering = null) { if (ordering == null) { @@ -786,9 +786,9 @@ namespace Umbraco.Cms.Core.Services return query; } - private IEnumerable GetPagedLocked(IQuery query, long pageIndex, int pageSize, + private IEnumerable GetPagedLocked(IQuery? query, long pageIndex, int pageSize, out long totalChildren, - IQuery filter, Ordering ordering) + IQuery? filter, Ordering? ordering) { if (pageIndex < 0) { @@ -813,10 +813,10 @@ namespace Umbraco.Cms.Core.Services /// /// Id of the to retrieve the parent from /// Parent object - public IContent GetParent(int id) + public IContent? GetParent(int id) { // intentionally not locking - IContent content = GetById(id); + IContent? content = GetById(id); return GetParent(content); } @@ -825,9 +825,9 @@ namespace Umbraco.Cms.Core.Services /// /// to retrieve the parent from /// Parent object - public IContent GetParent(IContent content) + public IContent? GetParent(IContent? content) { - if (content.ParentId == Constants.System.Root || content.ParentId == Constants.System.RecycleBinContent) + if (content?.ParentId == Constants.System.Root || content?.ParentId == Constants.System.RecycleBinContent || content is null) { return null; } @@ -887,7 +887,7 @@ namespace Umbraco.Cms.Core.Services /// /// An Enumerable list of objects public IEnumerable GetPagedContentInRecycleBin(long pageIndex, int pageSize, out long totalRecords, - IQuery filter = null, Ordering ordering = null) + IQuery? filter = null, Ordering? ordering = null) { using (IScope scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -929,11 +929,11 @@ namespace Umbraco.Cms.Core.Services } // not trashed and has a parent: publishable if the parent is path-published - IContent parent = GetById(content.ParentId); + IContent? parent = GetById(content.ParentId); return parent == null || IsPathPublished(parent); } - public bool IsPathPublished(IContent content) + public bool IsPathPublished(IContent? content) { using (IScope scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -947,7 +947,7 @@ namespace Umbraco.Cms.Core.Services #region Save, Publish, Unpublish /// - public OperationResult Save(IContent content, int userId = Constants.Security.SuperUserId, ContentScheduleCollection contentSchedule = null) + public OperationResult Save(IContent content, int userId = Constants.Security.SuperUserId, ContentScheduleCollection? contentSchedule = null) { PublishedState publishedState = content.PublishedState; if (publishedState != PublishedState.Published && publishedState != PublishedState.Unpublished) @@ -983,8 +983,8 @@ namespace Umbraco.Cms.Core.Services content.WriterId = userId; //track the cultures that have changed - List culturesChanging = content.ContentType.VariesByCulture() - ? content.CultureInfos.Values.Where(x => x.IsDirty()).Select(x => x.Culture).ToList() + List? culturesChanging = content.ContentType.VariesByCulture() + ? content.CultureInfos?.Values.Where(x => x.IsDirty()).Select(x => x.Culture).ToList() : null; // TODO: Currently there's no way to change track which variant properties have changed, we only have change // tracking enabled on all values on the Property which doesn't allow us to know which variants have changed. @@ -1198,7 +1198,7 @@ namespace Umbraco.Cms.Core.Services } /// - public PublishResult Unpublish(IContent content, string culture = "*", + public PublishResult Unpublish(IContent content, string? culture = "*", int userId = Constants.Security.SuperUserId) { if (content == null) @@ -1208,7 +1208,7 @@ namespace Umbraco.Cms.Core.Services EventMessages evtMsgs = EventMessagesFactory.Get(); - culture = culture.NullOrWhiteSpaceAsNull(); + culture = culture?.NullOrWhiteSpaceAsNull(); PublishedState publishedState = content.PublishedState; if (publishedState != PublishedState.Published && publishedState != PublishedState.Unpublished) @@ -1386,8 +1386,8 @@ namespace Umbraco.Cms.Core.Services throw new ArgumentNullException(nameof(eventMessages)); } - PublishResult publishResult = null; - PublishResult unpublishResult = null; + PublishResult? publishResult = null; + PublishResult? unpublishResult = null; // nothing set = republish it all if (content.PublishedState != PublishedState.Publishing && @@ -1404,10 +1404,10 @@ namespace Umbraco.Cms.Core.Services var variesByCulture = content.ContentType.VariesByCulture(); //track cultures that are being published, changed, unpublished - IReadOnlyList culturesPublishing = null; - IReadOnlyList culturesUnpublishing = null; - IReadOnlyList culturesChanging = variesByCulture - ? content.CultureInfos.Values.Where(x => x.IsDirty()).Select(x => x.Culture).ToList() + IReadOnlyList? culturesPublishing = null; + IReadOnlyList? culturesUnpublishing = null; + IReadOnlyList? culturesChanging = variesByCulture + ? content.CultureInfos?.Values.Where(x => x.IsDirty()).Select(x => x.Culture).ToList() : null; var isNew = !content.HasIdentity; @@ -1434,7 +1434,7 @@ namespace Umbraco.Cms.Core.Services //determine cultures publishing/unpublishing which will be based on previous calls to content.PublishCulture and ClearPublishInfo culturesUnpublishing = content.GetCulturesUnpublishing(); culturesPublishing = variesByCulture - ? content.PublishCultureInfos.Values.Where(x => x.IsDirty()).Select(x => x.Culture).ToList() + ? content.PublishCultureInfos?.Values.Where(x => x.IsDirty()).Select(x => x.Culture).ToList() : null; // ensure that the document can be published, and publish handling events, business rules, etc @@ -1447,7 +1447,7 @@ namespace Umbraco.Cms.Core.Services //check if a culture has been unpublished and if there are no cultures left, and then unpublish document as a whole if (publishResult.Result == PublishResultType.SuccessUnpublishCulture && - content.PublishCultureInfos.Count == 0) + content.PublishCultureInfos?.Count == 0) { // This is a special case! We are unpublishing the last culture and to persist that we need to re-publish without any cultures // so the state needs to remain Publishing to do that. However, we then also need to unpublish the document and to do that @@ -1489,8 +1489,8 @@ namespace Umbraco.Cms.Core.Services if (unpublishing) // won't happen in a branch { - IContent newest = GetById(content.Id); // ensure we have the newest version - in scope - if (content.VersionId != newest.VersionId) + IContent? newest = GetById(content.Id); // ensure we have the newest version - in scope + if (content.VersionId != newest?.VersionId) { return new PublishResult(PublishResultType.FailedPublishConcurrencyViolation, eventMessages, content); @@ -1535,7 +1535,7 @@ namespace Umbraco.Cms.Core.Services if (unpublishing) // we have tried to unpublish - won't happen in a branch { - if (unpublishResult.Success) // and succeeded, trigger events + if (unpublishResult?.Success ?? false) // and succeeded, trigger events { // events and audit scope.Notifications.Publish( @@ -1588,7 +1588,7 @@ namespace Umbraco.Cms.Core.Services if (publishing) // we have tried to publish { - if (publishResult.Success) // and succeeded, trigger events + if (publishResult?.Success ?? false) // and succeeded, trigger events { if (isNew == false && previouslyPublished == false) { @@ -1676,7 +1676,7 @@ namespace Umbraco.Cms.Core.Services // or, failed scope.Notifications.Publish(new ContentTreeChangeNotification(content, changeType, eventMessages)); - return publishResult; + return publishResult!; } /// @@ -1813,7 +1813,7 @@ namespace Umbraco.Cms.Core.Services } //publish the culture values and validate the property values, if validation fails, log the invalid properties so the develeper has an idea of what has failed - IProperty[] invalidProperties = null; + IProperty[]? invalidProperties = null; var impact = CultureImpact.Explicit(culture, IsDefaultCulture(allLangs.Value, culture)); var tryPublish = d.PublishCulture(impact) && _propertyValidationService.Value.IsPropertyDataValid(d, @@ -1862,7 +1862,7 @@ namespace Umbraco.Cms.Core.Services //Clear this schedule contentSchedule.Clear(ContentScheduleAction.Release, date); - PublishResult result = null; + PublishResult? result = null; if (d.Trashed) { @@ -1913,7 +1913,7 @@ namespace Umbraco.Cms.Core.Services } // utility 'ShouldPublish' func used by SaveAndPublishBranch - private HashSet SaveAndPublishBranch_ShouldPublish(ref HashSet cultures, string c, + private HashSet? SaveAndPublishBranch_ShouldPublish(ref HashSet? cultures, string c, bool published, bool edited, bool isRoot, bool force) { // if published, republish @@ -1960,10 +1960,10 @@ namespace Umbraco.Cms.Core.Services // determines cultures to be published // can be: null (content is not impacted), an empty set (content is impacted but already published), or cultures - HashSet ShouldPublish(IContent c) + HashSet? ShouldPublish(IContent c) { var isRoot = c.Id == content.Id; - HashSet culturesToPublish = null; + HashSet? culturesToPublish = null; if (!c.ContentType.VariesByCulture()) // invariant content type { @@ -2011,10 +2011,10 @@ namespace Umbraco.Cms.Core.Services // determines cultures to be published // can be: null (content is not impacted), an empty set (content is impacted but already published), or cultures - HashSet ShouldPublish(IContent c) + HashSet? ShouldPublish(IContent c) { var isRoot = c.Id == content.Id; - HashSet culturesToPublish = null; + HashSet? culturesToPublish = null; if (!c.ContentType.VariesByCulture()) // invariant content type { @@ -2046,7 +2046,7 @@ namespace Umbraco.Cms.Core.Services } internal IEnumerable SaveAndPublishBranch(IContent document, bool force, - Func> shouldPublish, + Func?> shouldPublish, Func, IReadOnlyCollection, bool> publishCultures, int userId = Constants.Security.SuperUserId) { @@ -2082,7 +2082,7 @@ namespace Umbraco.Cms.Core.Services } // deal with the branch root - if it fails, abort - PublishResult result = SaveAndPublishBranchItem(scope, document, shouldPublish, publishCultures, true, + PublishResult? result = SaveAndPublishBranchItem(scope, document, shouldPublish, publishCultures, true, publishedDocuments, eventMessages, userId, allLangs); if (result != null) { @@ -2153,14 +2153,14 @@ namespace Umbraco.Cms.Core.Services // shouldPublish: a function determining whether the document has changes that need to be published // note - 'force' is handled by 'editing' // publishValues: a function publishing values (using the appropriate PublishCulture calls) - private PublishResult SaveAndPublishBranchItem(IScope scope, IContent document, - Func> shouldPublish, + private PublishResult? SaveAndPublishBranchItem(IScope scope, IContent document, + Func?> shouldPublish, Func, IReadOnlyCollection, bool> publishCultures, bool isRoot, ICollection publishedDocuments, EventMessages evtMsgs, int userId, IReadOnlyCollection allLangs) { - HashSet culturesToPublish = shouldPublish(document); + HashSet? culturesToPublish = shouldPublish(document); if (culturesToPublish == null) // null = do not include { return null; @@ -2326,9 +2326,9 @@ namespace Umbraco.Cms.Core.Services } scope.WriteLock(Constants.Locks.ContentTree); - IContent c = _documentRepository.Get(id); - if (c.VersionId != versionId && - c.PublishedVersionId != versionId) // don't delete the current or published version + IContent? c = _documentRepository.Get(id); + if (c?.VersionId != versionId && + c?.PublishedVersionId != versionId) // don't delete the current or published version { _documentRepository.DeleteVersion(versionId); } @@ -2421,7 +2421,7 @@ namespace Umbraco.Cms.Core.Services { scope.WriteLock(Constants.Locks.ContentTree); - IContent parent = parentId == Constants.System.Root ? null : GetById(parentId); + IContent? parent = parentId == Constants.System.Root ? null : GetById(parentId); if (parentId != Constants.System.Root && (parent == null || parent.Trashed)) { throw new InvalidOperationException("Parent does not exist or is trashed."); // causes rollback @@ -2471,7 +2471,7 @@ namespace Umbraco.Cms.Core.Services // MUST be called from within WriteLock // trash indicates whether we are trashing, un-trashing, or not changing anything - private void PerformMoveLocked(IContent content, int parentId, IContent parent, int userId, + private void PerformMoveLocked(IContent content, int parentId, IContent? parent, int userId, ICollection<(IContent, string)> moves, bool? trash) { @@ -2600,7 +2600,7 @@ namespace Umbraco.Cms.Core.Services /// Boolean indicating whether the copy should be related to the original /// Optional Id of the User copying the Content /// The newly created object - public IContent Copy(IContent content, int parentId, bool relateToOriginal, + public IContent? Copy(IContent content, int parentId, bool relateToOriginal, int userId = Constants.Security.SuperUserId) => Copy(content, parentId, relateToOriginal, true, userId); /// @@ -2614,7 +2614,7 @@ namespace Umbraco.Cms.Core.Services /// A value indicating whether to recursively copy children. /// Optional Id of the User copying the Content /// The newly created object - public IContent Copy(IContent content, int parentId, bool relateToOriginal, bool recursive, + public IContent? Copy(IContent content, int parentId, bool relateToOriginal, bool recursive, int userId = Constants.Security.SuperUserId) { EventMessages eventMessages = EventMessagesFactory.Get(); @@ -2755,7 +2755,7 @@ namespace Umbraco.Cms.Core.Services //track the cultures changing for auditing var culturesChanging = content.ContentType.VariesByCulture() - ? string.Join(",", content.CultureInfos.Values.Where(x => x.IsDirty()).Select(x => x.Culture)) + ? string.Join(",", content.CultureInfos!.Values.Where(x => x.IsDirty()).Select(x => x.Culture)) : null; // TODO: Currently there's no way to change track which variant properties have changed, we only have change @@ -2986,7 +2986,7 @@ namespace Umbraco.Cms.Core.Services #region Private Methods - private void Audit(AuditType type, int userId, int objectId, string message = null, string parameters = null) => + private void Audit(AuditType type, int userId, int objectId, string? message = null, string? parameters = null) => _auditRepository.Save(new AuditItem(objectId, type, userId, UmbracoObjectTypes.Document.GetName(), message, parameters)); @@ -3013,8 +3013,8 @@ namespace Umbraco.Cms.Core.Services /// /// private PublishResult StrategyCanPublish(IScope scope, IContent content, bool checkPath, - IReadOnlyList culturesPublishing, - IReadOnlyCollection culturesUnpublishing, EventMessages evtMsgs, + IReadOnlyList? culturesPublishing, + IReadOnlyCollection? culturesUnpublishing, EventMessages evtMsgs, IReadOnlyCollection allLangs, IDictionary notificationState) { // raise Publishing notification @@ -3041,7 +3041,7 @@ namespace Umbraco.Cms.Core.Services } //validate the property values - IProperty[] invalidProperties = null; + IProperty[]? invalidProperties = null; if (!impactsToPublish.All(x => _propertyValidationService.Value.IsPropertyDataValid(content, out invalidProperties, x))) { @@ -3061,7 +3061,7 @@ namespace Umbraco.Cms.Core.Services "Internal error, variesByCulture but culturesPublishing is null."); } - if (content.Published && culturesPublishing.Count == 0 && culturesUnpublishing.Count == 0) + if (content.Published && culturesPublishing.Count == 0 && culturesUnpublishing?.Count == 0) { // no published cultures = cannot be published // This will occur if for example, a culture that is already unpublished is sent to be unpublished again, or vice versa, in that case @@ -3079,7 +3079,7 @@ namespace Umbraco.Cms.Core.Services return new PublishResult(PublishResultType.FailedPublishMandatoryCultureMissing, evtMsgs, content); } - if (culturesPublishing.Count == 0 && culturesUnpublishing.Count > 0) + if (culturesPublishing.Count == 0 && culturesUnpublishing?.Count > 0) { return new PublishResult(PublishResultType.SuccessUnpublishCulture, evtMsgs, content); } @@ -3162,7 +3162,7 @@ namespace Umbraco.Cms.Core.Services } //If we are both publishing and unpublishing cultures, then return a mixed status - if (variesByCulture && culturesPublishing.Count > 0 && culturesUnpublishing.Count > 0) + if (variesByCulture && culturesPublishing?.Count > 0 && culturesUnpublishing?.Count > 0) { return new PublishResult(PublishResultType.SuccessMixedCulture, evtMsgs, content); } @@ -3183,7 +3183,7 @@ namespace Umbraco.Cms.Core.Services /// /// private PublishResult StrategyPublish(IContent content, - IReadOnlyCollection culturesPublishing, IReadOnlyCollection culturesUnpublishing, + IReadOnlyCollection? culturesPublishing, IReadOnlyCollection? culturesUnpublishing, EventMessages evtMsgs) { // change state to publishing @@ -3192,31 +3192,31 @@ namespace Umbraco.Cms.Core.Services //if this is a variant then we need to log which cultures have been published/unpublished and return an appropriate result if (content.ContentType.VariesByCulture()) { - if (content.Published && culturesUnpublishing.Count == 0 && culturesPublishing.Count == 0) + if (content.Published && culturesUnpublishing?.Count == 0 && culturesPublishing?.Count == 0) { return new PublishResult(PublishResultType.FailedPublishNothingToPublish, evtMsgs, content); } - if (culturesUnpublishing.Count > 0) + if (culturesUnpublishing?.Count > 0) { _logger.LogInformation( "Document {ContentName} (id={ContentId}) cultures: {Cultures} have been unpublished.", content.Name, content.Id, string.Join(",", culturesUnpublishing)); } - if (culturesPublishing.Count > 0) + if (culturesPublishing?.Count > 0) { _logger.LogInformation( "Document {ContentName} (id={ContentId}) cultures: {Cultures} have been published.", content.Name, content.Id, string.Join(",", culturesPublishing)); } - if (culturesUnpublishing.Count > 0 && culturesPublishing.Count > 0) + if (culturesUnpublishing?.Count > 0 && culturesPublishing?.Count > 0) { return new PublishResult(PublishResultType.SuccessMixedCulture, evtMsgs, content); } - if (culturesUnpublishing.Count > 0 && culturesPublishing.Count == 0) + if (culturesUnpublishing?.Count > 0 && culturesPublishing?.Count == 0) { return new PublishResult(PublishResultType.SuccessUnpublishCulture, evtMsgs, content); } @@ -3413,7 +3413,7 @@ namespace Umbraco.Cms.Core.Services scope.ReadLock(Constants.Locks.ContentTypes); IQuery query = Query().Where(x => x.Alias == contentTypeAlias); - IContentType contentType = _contentTypeRepository.Get(query).FirstOrDefault(); + IContentType? contentType = _contentTypeRepository.Get(query).FirstOrDefault(); if (contentType == null) { @@ -3447,12 +3447,12 @@ namespace Umbraco.Cms.Core.Services #region Blueprints - public IContent GetBlueprintById(int id) + public IContent? GetBlueprintById(int id) { using (IScope scope = ScopeProvider.CreateScope(autoComplete: true)) { scope.ReadLock(Constants.Locks.ContentTree); - IContent blueprint = _documentBlueprintRepository.Get(id); + IContent? blueprint = _documentBlueprintRepository.Get(id); if (blueprint != null) { blueprint.Blueprint = true; @@ -3462,12 +3462,12 @@ namespace Umbraco.Cms.Core.Services } } - public IContent GetBlueprintById(Guid id) + public IContent? GetBlueprintById(Guid id) { using (IScope scope = ScopeProvider.CreateScope(autoComplete: true)) { scope.ReadLock(Constants.Locks.ContentTree); - IContent blueprint = _documentBlueprintRepository.Get(id); + IContent? blueprint = _documentBlueprintRepository.Get(id); if (blueprint != null) { blueprint.Blueprint = true; @@ -3524,7 +3524,7 @@ namespace Umbraco.Cms.Core.Services } } - private static readonly string[] ArrayOfOneNullString = { null }; + private static readonly string?[] ArrayOfOneNullString = { null }; public IContent CreateContentFromBlueprint(IContent blueprint, string name, int userId = Constants.Security.SuperUserId) @@ -3541,8 +3541,8 @@ namespace Umbraco.Cms.Core.Services content.CreatorId = userId; content.WriterId = userId; - IEnumerable cultures = ArrayOfOneNullString; - if (blueprint.CultureInfos.Count > 0) + IEnumerable cultures = ArrayOfOneNullString; + if (blueprint.CultureInfos?.Count > 0) { cultures = blueprint.CultureInfos.Values.Select(x => x.Culture); using (IScope scope = ScopeProvider.CreateScope()) diff --git a/src/Umbraco.Core/Services/ContentServiceExtensions.cs b/src/Umbraco.Core/Services/ContentServiceExtensions.cs index fae700f3a7..1b9d9498f7 100644 --- a/src/Umbraco.Core/Services/ContentServiceExtensions.cs +++ b/src/Umbraco.Core/Services/ContentServiceExtensions.cs @@ -26,17 +26,21 @@ namespace Umbraco.Extensions var result = new List(); var content = contentService.GetById(id); - foreach (var contentProperty in content.Properties) + if (content is not null) { - if (contentProperty.PropertyType.PropertyEditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.TinyMce)) + foreach (var contentProperty in content.Properties) { - var value = contentProperty.GetValue(culture)?.ToString(); - if (!string.IsNullOrEmpty(value)) + if (contentProperty.PropertyType.PropertyEditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.TinyMce)) { - result.AddRange(contentService.GetAnchorValuesFromRTEContent(value)); + var value = contentProperty.GetValue(culture)?.ToString(); + if (!string.IsNullOrEmpty(value)) + { + result.AddRange(contentService.GetAnchorValuesFromRTEContent(value)); + } } } } + return result; } diff --git a/src/Umbraco.Core/Services/ContentTypeBaseServiceProvider.cs b/src/Umbraco.Core/Services/ContentTypeBaseServiceProvider.cs index 769f52edf5..b493460876 100644 --- a/src/Umbraco.Core/Services/ContentTypeBaseServiceProvider.cs +++ b/src/Umbraco.Core/Services/ContentTypeBaseServiceProvider.cs @@ -33,10 +33,10 @@ namespace Umbraco.Cms.Core.Services } // note: this should be a default interface method with C# 8 - public IContentTypeComposition GetContentTypeOf(IContentBase contentBase) + public IContentTypeComposition? GetContentTypeOf(IContentBase contentBase) { if (contentBase == null) throw new ArgumentNullException(nameof(contentBase)); - return For(contentBase)?.Get(contentBase.ContentTypeId); + return For(contentBase).Get(contentBase.ContentTypeId); } } } diff --git a/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs b/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs index d12ed1bddc..d402eb5e6b 100644 --- a/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs +++ b/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs @@ -69,7 +69,7 @@ namespace Umbraco.Cms.Core.Services #region Validation - public Attempt ValidateComposition(TItem compo) + public Attempt ValidateComposition(TItem compo) { try { @@ -78,7 +78,7 @@ namespace Umbraco.Cms.Core.Services scope.ReadLock(ReadLockIds); ValidateLocked(compo); } - return Attempt.Succeed(); + return Attempt.Succeed(); } catch (InvalidCompositionException ex) { @@ -101,7 +101,7 @@ namespace Umbraco.Cms.Core.Services var propertyTypeAliases = compositionContentType.PropertyTypes.Select(x => x.Alias).ToArray(); var propertyGroupAliases = compositionContentType.PropertyGroups.ToDictionary(x => x.Alias, x => x.Type, StringComparer.InvariantCultureIgnoreCase); var indirectReferences = allContentTypes.Where(x => x.ContentTypeComposition.Any(y => y.Id == compositionContentType.Id)); - var comparer = new DelegateEqualityComparer((x, y) => x.Id == y.Id, x => x.Id); + var comparer = new DelegateEqualityComparer((x, y) => x?.Id == y?.Id, x => x.Id); var dependencies = new HashSet(compositions, comparer); var stack = new Stack(); @@ -256,12 +256,12 @@ namespace Umbraco.Cms.Core.Services #region Get, Has, Is, Count - IContentTypeComposition IContentTypeBaseService.Get(int id) + IContentTypeComposition? IContentTypeBaseService.Get(int id) { return Get(id); } - public TItem Get(int id) + public TItem? Get(int id) { using (var scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -279,7 +279,7 @@ namespace Umbraco.Cms.Core.Services } } - public TItem Get(Guid id) + public TItem? Get(Guid id) { using (var scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -382,7 +382,14 @@ namespace Umbraco.Cms.Core.Services scope.ReadLock(ReadLockIds); var descendants = new List(); - if (andSelf) descendants.Add(Repository.Get(id)); + if (andSelf) + { + var self = Repository.Get(id); + if (self is not null) + { + descendants.Add(self); + } + } var ids = new Stack(); ids.Push(id); @@ -575,10 +582,10 @@ namespace Umbraco.Cms.Core.Services DeleteItemsOfTypes(descendantsAndSelf.Select(x => x.Id)); // Next find all other document types that have a reference to this content type - IEnumerable referenceToAllowedContentTypes = GetAll().Where(q => q.AllowedContentTypes.Any(p=>p.Id.Value==item.Id)); + IEnumerable referenceToAllowedContentTypes = GetAll().Where(q => q.AllowedContentTypes?.Any(p=>p.Id.Value==item.Id) ?? false); foreach (TItem reference in referenceToAllowedContentTypes) { - reference.AllowedContentTypes = reference.AllowedContentTypes.Where(p => p.Id.Value != item.Id); + reference.AllowedContentTypes = reference.AllowedContentTypes?.Where(p => p.Id.Value != item.Id); var changedRef = new List>() { new ContentTypeChange(reference, ContentTypeChangeTypes.RefreshMain) }; // Fire change event scope.Notifications.Publish(GetContentTypeChangedNotification(changedRef, eventMessages)); @@ -676,7 +683,7 @@ namespace Umbraco.Cms.Core.Services public TItem Copy(TItem original, string alias, string name, int parentId = -1) { - TItem parent = null; + TItem? parent = null; if (parentId > 0) { parent = Get(parentId); @@ -688,7 +695,7 @@ namespace Umbraco.Cms.Core.Services return Copy(original, alias, name, parent); } - public TItem Copy(TItem original, string alias, string name, TItem parent) + public TItem Copy(TItem original, string alias, string name, TItem? parent) { if (original == null) throw new ArgumentNullException(nameof(original)); if (alias == null) throw new ArgumentNullException(nameof(alias)); @@ -727,7 +734,7 @@ namespace Umbraco.Cms.Core.Services return clone; } - public Attempt> Copy(TItem copying, int containerId) + public Attempt?> Copy(TItem copying, int containerId) { var evtMsgs = EventMessagesFactory.Get(); @@ -780,7 +787,7 @@ namespace Umbraco.Cms.Core.Services #region Move - public Attempt> Move(TItem moving, int containerId) + public Attempt?> Move(TItem moving, int containerId) { EventMessages eventMessages = EventMessagesFactory.Get(); @@ -799,14 +806,14 @@ namespace Umbraco.Cms.Core.Services try { - EntityContainer container = null; + EntityContainer? container = null; if (containerId > 0) { container = _containerRepository.Get(containerId); if (container == null) throw new DataOperationException(MoveOperationStatusType.FailedParentNotFound); // causes rollback } - moveInfo.AddRange(Repository.Move(moving, container)); + moveInfo.AddRange(Repository.Move(moving, container!)); scope.Complete(); } catch (DataOperationException ex) @@ -834,7 +841,7 @@ namespace Umbraco.Cms.Core.Services protected Guid ContainerObjectType => EntityContainer.GetContainerObjectType(ContainedObjectType); - public Attempt> CreateContainer(int parentId, Guid key, string name, int userId = Cms.Core.Constants.Security.SuperUserId) + public Attempt?> CreateContainer(int parentId, Guid key, string name, int userId = Cms.Core.Constants.Security.SuperUserId) { EventMessages eventMessages = EventMessagesFactory.Get(); using (IScope scope = ScopeProvider.CreateScope()) @@ -876,7 +883,7 @@ namespace Umbraco.Cms.Core.Services } } - public Attempt SaveContainer(EntityContainer container, int userId = Cms.Core.Constants.Security.SuperUserId) + public Attempt SaveContainer(EntityContainer container, int userId = Cms.Core.Constants.Security.SuperUserId) { EventMessages eventMessages = EventMessagesFactory.Get(); @@ -917,7 +924,7 @@ namespace Umbraco.Cms.Core.Services return OperationResult.Attempt.Succeed(eventMessages); } - public EntityContainer GetContainer(int containerId) + public EntityContainer? GetContainer(int containerId) { using (var scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -967,14 +974,14 @@ namespace Umbraco.Cms.Core.Services } } - public Attempt DeleteContainer(int containerId, int userId = Cms.Core.Constants.Security.SuperUserId) + public Attempt DeleteContainer(int containerId, int userId = Cms.Core.Constants.Security.SuperUserId) { EventMessages eventMessages = EventMessagesFactory.Get(); using (IScope scope = ScopeProvider.CreateScope()) { scope.WriteLock(WriteLockIds); // also for containers - EntityContainer container = _containerRepository.Get(containerId); + EntityContainer? container = _containerRepository.Get(containerId); if (container == null) { return OperationResult.Attempt.NoOperation(eventMessages); @@ -1008,7 +1015,7 @@ namespace Umbraco.Cms.Core.Services } } - public Attempt> RenameContainer(int id, string name, int userId = Cms.Core.Constants.Security.SuperUserId) + public Attempt?> RenameContainer(int id, string name, int userId = Cms.Core.Constants.Security.SuperUserId) { EventMessages eventMessages = EventMessagesFactory.Get(); using (IScope scope = ScopeProvider.CreateScope()) @@ -1017,7 +1024,7 @@ namespace Umbraco.Cms.Core.Services try { - EntityContainer container = _containerRepository.Get(id); + EntityContainer? container = _containerRepository.Get(id); //throw if null, this will be caught by the catch and a failed returned if (container == null) diff --git a/src/Umbraco.Core/Services/ContentVersionService.cs b/src/Umbraco.Core/Services/ContentVersionService.cs index 8b3f18a89f..d2b50cc82a 100644 --- a/src/Umbraco.Core/Services/ContentVersionService.cs +++ b/src/Umbraco.Core/Services/ContentVersionService.cs @@ -175,7 +175,7 @@ namespace Umbraco.Cms.Core.Services } } - private void Audit(AuditType type, int userId, int objectId, string message = null, string parameters = null) + private void Audit(AuditType type, int userId, int objectId, string? message = null, string? parameters = null) { var entry = new AuditItem( objectId, diff --git a/src/Umbraco.Core/Services/DefaultContentVersionCleanupPolicy.cs b/src/Umbraco.Core/Services/DefaultContentVersionCleanupPolicy.cs index ee4bf6c952..61283c4a8c 100644 --- a/src/Umbraco.Core/Services/DefaultContentVersionCleanupPolicy.cs +++ b/src/Umbraco.Core/Services/DefaultContentVersionCleanupPolicy.cs @@ -83,7 +83,7 @@ namespace Umbraco.Cms.Core.Services } } - private ContentVersionCleanupPolicySettings GetOverridePolicy( + private ContentVersionCleanupPolicySettings? GetOverridePolicy( ContentVersionMeta version, IDictionary overrides) { diff --git a/src/Umbraco.Core/Services/DomainService.cs b/src/Umbraco.Core/Services/DomainService.cs index f0ad6d63ee..a0dc256fff 100644 --- a/src/Umbraco.Core/Services/DomainService.cs +++ b/src/Umbraco.Core/Services/DomainService.cs @@ -27,7 +27,7 @@ namespace Umbraco.Cms.Core.Services } } - public Attempt Delete(IDomain domain) + public Attempt Delete(IDomain domain) { EventMessages eventMessages = EventMessagesFactory.Get(); @@ -57,7 +57,7 @@ namespace Umbraco.Cms.Core.Services } } - public IDomain GetById(int id) + public IDomain? GetById(int id) { using (var scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -81,7 +81,7 @@ namespace Umbraco.Cms.Core.Services } } - public Attempt Save(IDomain domainEntity) + public Attempt Save(IDomain domainEntity) { EventMessages eventMessages = EventMessagesFactory.Get(); diff --git a/src/Umbraco.Core/Services/EntityService.cs b/src/Umbraco.Core/Services/EntityService.cs index 9169c6c96b..b971019be6 100644 --- a/src/Umbraco.Core/Services/EntityService.cs +++ b/src/Umbraco.Core/Services/EntityService.cs @@ -17,7 +17,7 @@ namespace Umbraco.Cms.Core.Services { private readonly IEntityRepository _entityRepository; private readonly Dictionary _objectTypes; - private IQuery _queryRootEntity; + private IQuery? _queryRootEntity; private readonly IIdKeyMap _idKeyMap; public EntityService(IScopeProvider provider, ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, IIdKeyMap idKeyMap, IEntityRepository entityRepository) @@ -28,13 +28,13 @@ namespace Umbraco.Cms.Core.Services _objectTypes = new Dictionary { - { typeof (IDataType).FullName, UmbracoObjectTypes.DataType }, - { typeof (IContent).FullName, UmbracoObjectTypes.Document }, - { typeof (IContentType).FullName, UmbracoObjectTypes.DocumentType }, - { typeof (IMedia).FullName, UmbracoObjectTypes.Media }, - { typeof (IMediaType).FullName, UmbracoObjectTypes.MediaType }, - { typeof (IMember).FullName, UmbracoObjectTypes.Member }, - { typeof (IMemberType).FullName, UmbracoObjectTypes.MemberType }, + { typeof (IDataType).FullName!, UmbracoObjectTypes.DataType }, + { typeof (IContent).FullName!, UmbracoObjectTypes.Document }, + { typeof (IContentType).FullName!, UmbracoObjectTypes.DocumentType }, + { typeof (IMedia).FullName!, UmbracoObjectTypes.Media }, + { typeof (IMediaType).FullName!, UmbracoObjectTypes.MediaType }, + { typeof (IMember).FullName!, UmbracoObjectTypes.Member }, + { typeof (IMemberType).FullName!, UmbracoObjectTypes.MemberType }, }; } @@ -47,7 +47,7 @@ namespace Umbraco.Cms.Core.Services #endregion // gets the object type, throws if not supported - private UmbracoObjectTypes GetObjectType(Type type) + private UmbracoObjectTypes GetObjectType(Type ?type) { if (type?.FullName == null || !_objectTypes.TryGetValue(type.FullName, out var objType)) throw new NotSupportedException($"Type \"{type?.FullName ?? ""}\" is not supported here."); @@ -230,7 +230,7 @@ namespace Umbraco.Cms.Core.Services } /// - public virtual IEntitySlim GetParent(int id) + public virtual IEntitySlim? GetParent(int id) { using (ScopeProvider.CreateScope(autoComplete: true)) { @@ -242,7 +242,7 @@ namespace Umbraco.Cms.Core.Services } /// - public virtual IEntitySlim GetParent(int id, UmbracoObjectTypes objectType) + public virtual IEntitySlim? GetParent(int id, UmbracoObjectTypes objectType) { using (ScopeProvider.CreateScope(autoComplete: true)) { @@ -298,7 +298,7 @@ namespace Umbraco.Cms.Core.Services /// public IEnumerable GetPagedChildren(int id, UmbracoObjectTypes objectType, long pageIndex, int pageSize, out long totalRecords, - IQuery filter = null, Ordering ordering = null) + IQuery? filter = null, Ordering? ordering = null) { using (ScopeProvider.CreateScope(autoComplete: true)) { @@ -310,7 +310,7 @@ namespace Umbraco.Cms.Core.Services /// public IEnumerable GetPagedDescendants(int id, UmbracoObjectTypes objectType, long pageIndex, int pageSize, out long totalRecords, - IQuery filter = null, Ordering ordering = null) + IQuery? filter = null, Ordering? ordering = null) { using (ScopeProvider.CreateScope(autoComplete: true)) { @@ -336,7 +336,7 @@ namespace Umbraco.Cms.Core.Services /// public IEnumerable GetPagedDescendants(IEnumerable ids, UmbracoObjectTypes objectType, long pageIndex, int pageSize, out long totalRecords, - IQuery filter = null, Ordering ordering = null) + IQuery? filter = null, Ordering? ordering = null) { totalRecords = 0; @@ -379,7 +379,7 @@ namespace Umbraco.Cms.Core.Services /// public IEnumerable GetPagedDescendants(UmbracoObjectTypes objectType, long pageIndex, int pageSize, out long totalRecords, - IQuery filter = null, Ordering ordering = null, bool includeTrashed = true) + IQuery? filter = null, Ordering? ordering = null, bool includeTrashed = true) { using (ScopeProvider.CreateScope(autoComplete: true)) { @@ -418,7 +418,7 @@ namespace Umbraco.Cms.Core.Services } /// - public virtual Type GetEntityType(int id) + public virtual Type? GetEntityType(int id) { var objectType = GetObjectType(id); return objectType.GetClrType(); @@ -443,7 +443,7 @@ namespace Umbraco.Cms.Core.Services } /// - public virtual IEnumerable GetAllPaths(UmbracoObjectTypes objectType, params int[] ids) + public virtual IEnumerable GetAllPaths(UmbracoObjectTypes objectType, params int[]? ids) { var entityType = objectType.GetClrType(); GetObjectType(entityType); diff --git a/src/Umbraco.Core/Services/EntityXmlSerializer.cs b/src/Umbraco.Core/Services/EntityXmlSerializer.cs index be4efe2082..e0f458db7b 100644 --- a/src/Umbraco.Core/Services/EntityXmlSerializer.cs +++ b/src/Umbraco.Core/Services/EntityXmlSerializer.cs @@ -100,7 +100,7 @@ namespace Umbraco.Cms.Core.Services public XElement Serialize( IMedia media, bool withDescendants = false, - Action onMediaItemSerialized = null) + Action? onMediaItemSerialized = null) { if (_mediaService == null) throw new ArgumentNullException(nameof(_mediaService)); if (_dataTypeService == null) throw new ArgumentNullException(nameof(_dataTypeService)); @@ -112,7 +112,7 @@ namespace Umbraco.Cms.Core.Services var nodeName = media.ContentType.Alias.ToSafeAlias(_shortStringHelper); const bool published = false; // always false for media - string urlValue = media.GetUrlSegment(_shortStringHelper, _urlSegmentProviders); + string? urlValue = media.GetUrlSegment(_shortStringHelper, _urlSegmentProviders); XElement xml = SerializeContentBase(media, urlValue, nodeName, published); @@ -594,7 +594,7 @@ namespace Umbraco.Cms.Core.Services } // exports an IContentBase (IContent, IMedia or IMember) as an XElement. - private XElement SerializeContentBase(IContentBase contentBase, string urlValue, string nodeName, bool published) + private XElement SerializeContentBase(IContentBase contentBase, string? urlValue, string nodeName, bool published) { var xml = new XElement(nodeName, new XAttribute("id", contentBase.Id.ToInvariantString()), @@ -657,7 +657,7 @@ namespace Umbraco.Cms.Core.Services } // exports an IMedia item descendants. - private void SerializeChildren(IEnumerable children, XElement xml, Action onMediaItemSerialized) + private void SerializeChildren(IEnumerable children, XElement xml, Action? onMediaItemSerialized) { foreach (var child in children) { diff --git a/src/Umbraco.Core/Services/FileService.cs b/src/Umbraco.Core/Services/FileService.cs index 7fc97e7c67..443ebf035c 100644 --- a/src/Umbraco.Core/Services/FileService.cs +++ b/src/Umbraco.Core/Services/FileService.cs @@ -65,7 +65,7 @@ namespace Umbraco.Cms.Core.Services } /// - public IStylesheet GetStylesheet(string path) + public IStylesheet? GetStylesheet(string path) { using (IScope scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -100,7 +100,7 @@ namespace Umbraco.Cms.Core.Services { using (IScope scope = ScopeProvider.CreateScope()) { - IStylesheet stylesheet = _stylesheetRepository.Get(path); + IStylesheet? stylesheet = _stylesheetRepository.Get(path); if (stylesheet == null) { scope.Complete(); @@ -186,7 +186,7 @@ namespace Umbraco.Cms.Core.Services } /// - public IScript GetScript(string name) + public IScript? GetScript(string name) { using (IScope scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -220,7 +220,7 @@ namespace Umbraco.Cms.Core.Services { using (IScope scope = ScopeProvider.CreateScope()) { - IScript script = _scriptRepository.Get(path); + IScript? script = _scriptRepository.Get(path); if (script == null) { scope.Complete(); @@ -304,7 +304,7 @@ namespace Umbraco.Cms.Core.Services /// /// The template created /// - public Attempt> CreateTemplateForContentType(string contentTypeAlias, string contentTypeName, int userId = Constants.Security.SuperUserId) + public Attempt?> CreateTemplateForContentType(string contentTypeAlias, string contentTypeName, int userId = Constants.Security.SuperUserId) { var template = new Template(_shortStringHelper, contentTypeName, //NOTE: We are NOT passing in the content type alias here, we want to use it's name since we don't @@ -322,7 +322,7 @@ namespace Umbraco.Cms.Core.Services // check that the template hasn't been created on disk before creating the content type // if it exists, set the new template content to the existing file content - string content = GetViewContent(contentTypeAlias); + string? content = GetViewContent(contentTypeAlias); if (content != null) { template.Content = content; @@ -330,7 +330,7 @@ namespace Umbraco.Cms.Core.Services using (IScope scope = ScopeProvider.CreateScope()) { - var savingEvent = new TemplateSavingNotification(template, eventMessages, true, contentTypeAlias); + var savingEvent = new TemplateSavingNotification(template, eventMessages, true, contentTypeAlias!); if (scope.Notifications.PublishCancelable(savingEvent)) { scope.Complete(); @@ -356,7 +356,7 @@ namespace Umbraco.Cms.Core.Services /// /// /// - public ITemplate CreateTemplateWithIdentity(string name, string alias, string content, ITemplate masterTemplate = null, int userId = Constants.Security.SuperUserId) + public ITemplate CreateTemplateWithIdentity(string name, string alias, string content, ITemplate? masterTemplate = null, int userId = Constants.Security.SuperUserId) { if (name == null) { @@ -418,7 +418,7 @@ namespace Umbraco.Cms.Core.Services /// /// The alias of the template. /// The object matching the alias, or null. - public ITemplate GetTemplate(string alias) + public ITemplate GetTemplate(string? alias) { using (IScope scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -431,7 +431,7 @@ namespace Umbraco.Cms.Core.Services /// /// The identifier of the template. /// The object matching the identifier, or null. - public ITemplate GetTemplate(int id) + public ITemplate? GetTemplate(int id) { using (IScope scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -444,7 +444,7 @@ namespace Umbraco.Cms.Core.Services /// /// The guid identifier of the template. /// The object matching the identifier, or null. - public ITemplate GetTemplate(Guid id) + public ITemplate? GetTemplate(Guid id) { using (IScope scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -566,14 +566,14 @@ namespace Umbraco.Cms.Core.Services } } - private string GetViewContent(string fileName) + private string? GetViewContent(string? fileName) { if (fileName.IsNullOrWhiteSpace()) { throw new ArgumentNullException(nameof(fileName)); } - if (!fileName.EndsWith(".cshtml")) + if (!fileName!.EndsWith(".cshtml")) { fileName = $"{fileName}.cshtml"; } @@ -622,7 +622,7 @@ namespace Umbraco.Cms.Core.Services #region Partial Views - public IEnumerable GetPartialViewSnippetNames(params string[] filterNames) + public IEnumerable GetPartialViewSnippetNames(params string[] filterNames) { var snippetPath = _hostingEnvironment.MapPathContentRoot($"{Constants.SystemDirectories.Umbraco}/PartialViewMacros/Templates/"); var files = Directory.GetFiles(snippetPath, "*.cshtml") @@ -631,8 +631,8 @@ namespace Umbraco.Cms.Core.Services .ToArray(); //Ensure the ones that are called 'Empty' are at the top - var empty = files.Where(x => Path.GetFileName(x).InvariantStartsWith("Empty")) - .OrderBy(x => x.Length) + var empty = files.Where(x => Path.GetFileName(x)?.InvariantStartsWith("Empty") ?? false) + .OrderBy(x => x?.Length) .ToArray(); return empty.Union(files.Except(empty)); @@ -664,7 +664,7 @@ namespace Umbraco.Cms.Core.Services } } - public IPartialView GetPartialView(string path) + public IPartialView? GetPartialView(string path) { using (IScope scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -672,7 +672,7 @@ namespace Umbraco.Cms.Core.Services } } - public IPartialView GetPartialViewMacro(string path) + public IPartialView? GetPartialViewMacro(string path) { using (IScope scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -680,13 +680,13 @@ namespace Umbraco.Cms.Core.Services } } - public Attempt CreatePartialView(IPartialView partialView, string snippetName = null, int userId = Constants.Security.SuperUserId) => + public Attempt CreatePartialView(IPartialView partialView, string? snippetName = null, int userId = Constants.Security.SuperUserId) => CreatePartialViewMacro(partialView, PartialViewType.PartialView, snippetName, userId); - public Attempt CreatePartialViewMacro(IPartialView partialView, string snippetName = null, int userId = Constants.Security.SuperUserId) => + public Attempt CreatePartialViewMacro(IPartialView partialView, string? snippetName = null, int userId = Constants.Security.SuperUserId) => CreatePartialViewMacro(partialView, PartialViewType.PartialViewMacro, snippetName, userId); - private Attempt CreatePartialViewMacro(IPartialView partialView, PartialViewType partialViewType, string snippetName = null, int userId = Constants.Security.SuperUserId) + private Attempt CreatePartialViewMacro(IPartialView partialView, PartialViewType partialViewType, string? snippetName = null, int userId = Constants.Security.SuperUserId) { string partialViewHeader; switch (partialViewType) @@ -701,7 +701,7 @@ namespace Umbraco.Cms.Core.Services throw new ArgumentOutOfRangeException(nameof(partialViewType)); } - string partialViewContent = null; + string? partialViewContent = null; if (snippetName.IsNullOrWhiteSpace() == false) { //create the file @@ -711,7 +711,7 @@ namespace Umbraco.Cms.Core.Services throw new InvalidOperationException("Could not load snippet with name " + snippetName); } - using (var snippetFile = new StreamReader(System.IO.File.OpenRead(snippetPathAttempt.Result))) + using (var snippetFile = new StreamReader(System.IO.File.OpenRead(snippetPathAttempt.Result!))) { var snippetContent = snippetFile.ReadToEnd().Trim(); @@ -767,7 +767,7 @@ namespace Umbraco.Cms.Core.Services using (IScope scope = ScopeProvider.CreateScope()) { IPartialViewRepository repository = GetPartialViewRepository(partialViewType); - IPartialView partialView = repository.Get(path); + IPartialView? partialView = repository.Get(path); if (partialView == null) { scope.Complete(); @@ -792,13 +792,13 @@ namespace Umbraco.Cms.Core.Services return true; } - public Attempt SavePartialView(IPartialView partialView, int userId = Constants.Security.SuperUserId) => + public Attempt SavePartialView(IPartialView partialView, int userId = Constants.Security.SuperUserId) => SavePartialView(partialView, PartialViewType.PartialView, userId); - public Attempt SavePartialViewMacro(IPartialView partialView, int userId = Constants.Security.SuperUserId) => + public Attempt SavePartialViewMacro(IPartialView partialView, int userId = Constants.Security.SuperUserId) => SavePartialView(partialView, PartialViewType.PartialViewMacro, userId); - private Attempt SavePartialView(IPartialView partialView, PartialViewType partialViewType, int userId = Constants.Security.SuperUserId) + private Attempt SavePartialView(IPartialView partialView, PartialViewType partialViewType, int userId = Constants.Security.SuperUserId) { using (IScope scope = ScopeProvider.CreateScope()) { @@ -807,7 +807,7 @@ namespace Umbraco.Cms.Core.Services if (scope.Notifications.PublishCancelable(savingNotification)) { scope.Complete(); - return Attempt.Fail(); + return Attempt.Fail(); } IPartialViewRepository repository = GetPartialViewRepository(partialViewType); @@ -828,9 +828,9 @@ namespace Umbraco.Cms.Core.Services return headerMatch.Replace(contents, string.Empty); } - internal Attempt TryGetSnippetPath(string fileName) + internal Attempt TryGetSnippetPath(string? fileName) { - if (fileName.EndsWith(".cshtml") == false) + if (fileName?.EndsWith(".cshtml") == false) { fileName += ".cshtml"; } @@ -963,7 +963,7 @@ namespace Umbraco.Cms.Core.Services throw new InvalidOperationException("Could not load snippet with name " + snippetName); } - using (var snippetFile = new StreamReader(System.IO.File.OpenRead(snippetPathAttempt.Result))) + using (var snippetFile = new StreamReader(System.IO.File.OpenRead(snippetPathAttempt.Result!))) { var snippetContent = snippetFile.ReadToEnd().Trim(); @@ -985,7 +985,7 @@ namespace Umbraco.Cms.Core.Services #endregion - private void Audit(AuditType type, int userId, int objectId, string entityType) => _auditRepository.Save(new AuditItem(objectId, type, userId, entityType)); + private void Audit(AuditType type, int userId, int objectId, string? entityType) => _auditRepository.Save(new AuditItem(objectId, type, userId, entityType)); // TODO: Method to change name and/or alias of view template } diff --git a/src/Umbraco.Core/Services/IContentService.cs b/src/Umbraco.Core/Services/IContentService.cs index fb9fd511fe..e16ef8cfa3 100644 --- a/src/Umbraco.Core/Services/IContentService.cs +++ b/src/Umbraco.Core/Services/IContentService.cs @@ -16,12 +16,12 @@ namespace Umbraco.Cms.Core.Services /// /// Gets a blueprint. /// - IContent GetBlueprintById(int id); + IContent? GetBlueprintById(int id); /// /// Gets a blueprint. /// - IContent GetBlueprintById(Guid id); + IContent? GetBlueprintById(Guid id); /// /// Gets blueprints for a content type. @@ -60,12 +60,12 @@ namespace Umbraco.Cms.Core.Services /// /// Gets a document. /// - IContent GetById(int id); + IContent? GetById(int id); /// /// Gets a document. /// - IContent GetById(Guid key); + IContent? GetById(Guid key); /// /// Gets publish/unpublish schedule for a content node. @@ -99,12 +99,12 @@ namespace Umbraco.Cms.Core.Services /// /// Gets the parent of a document. /// - IContent GetParent(int id); + IContent? GetParent(int id); /// /// Gets the parent of a document. /// - IContent GetParent(IContent content); + IContent? GetParent(IContent content); /// /// Gets ancestor documents of a document. @@ -310,7 +310,7 @@ namespace Umbraco.Cms.Core.Services /// /// Recursively copies all children. /// - IContent Copy(IContent content, int parentId, bool relateToOriginal, int userId = Constants.Security.SuperUserId); + IContent? Copy(IContent content, int parentId, bool relateToOriginal, int userId = Constants.Security.SuperUserId); /// /// Copies a document. @@ -318,7 +318,7 @@ namespace Umbraco.Cms.Core.Services /// /// Optionally recursively copies all children. /// - IContent Copy(IContent content, int parentId, bool relateToOriginal, bool recursive, int userId = Constants.Security.SuperUserId); + IContent? Copy(IContent content, int parentId, bool relateToOriginal, bool recursive, int userId = Constants.Security.SuperUserId); /// /// Moves a document to the recycle bin. @@ -510,7 +510,7 @@ namespace Umbraco.Cms.Core.Services /// /// Creates a document. /// - IContent Create(string name, IContent parent, string documentTypeAlias, int userId = Constants.Security.SuperUserId); + IContent Create(string name, IContent? parent, string documentTypeAlias, int userId = Constants.Security.SuperUserId); /// /// Creates and saves a document. diff --git a/src/Umbraco.Core/Services/IContentServiceBase.cs b/src/Umbraco.Core/Services/IContentServiceBase.cs index a62d039abb..86689807c4 100644 --- a/src/Umbraco.Core/Services/IContentServiceBase.cs +++ b/src/Umbraco.Core/Services/IContentServiceBase.cs @@ -7,8 +7,8 @@ namespace Umbraco.Cms.Core.Services public interface IContentServiceBase : IContentServiceBase where TItem: class, IContentBase { - TItem GetById(Guid key); - Attempt Save(IEnumerable contents, int userId = Constants.Security.SuperUserId); + IContent? GetById(Guid key); + Attempt Save(IEnumerable contents, int userId = Constants.Security.SuperUserId); } /// diff --git a/src/Umbraco.Core/Services/IContentTypeBaseServiceProvider.cs b/src/Umbraco.Core/Services/IContentTypeBaseServiceProvider.cs index 3c45722052..4b6a78850c 100644 --- a/src/Umbraco.Core/Services/IContentTypeBaseServiceProvider.cs +++ b/src/Umbraco.Core/Services/IContentTypeBaseServiceProvider.cs @@ -22,6 +22,6 @@ namespace Umbraco.Cms.Core.Services /// /// Gets the content type of an object. /// - IContentTypeComposition GetContentTypeOf(IContentBase contentBase); + IContentTypeComposition? GetContentTypeOf(IContentBase contentBase); } } diff --git a/src/Umbraco.Core/Services/IContentTypeServiceBase.cs b/src/Umbraco.Core/Services/IContentTypeServiceBase.cs index 7902774f4d..d6f24ba4e0 100644 --- a/src/Umbraco.Core/Services/IContentTypeServiceBase.cs +++ b/src/Umbraco.Core/Services/IContentTypeServiceBase.cs @@ -12,7 +12,7 @@ namespace Umbraco.Cms.Core.Services /// /// Gets a content type. /// - IContentTypeComposition Get(int id); + IContentTypeComposition? Get(int id); } /// @@ -25,12 +25,12 @@ namespace Umbraco.Cms.Core.Services /// /// Gets a content type. /// - new TItem Get(int id); + new TItem? Get(int id); /// /// Gets a content type. /// - TItem Get(Guid key); + TItem? Get(Guid key); /// /// Gets a content type. @@ -62,7 +62,7 @@ namespace Umbraco.Cms.Core.Services void Delete(IEnumerable item, int userId = Constants.Security.SuperUserId); - Attempt ValidateComposition(TItem compo); + Attempt ValidateComposition(TItem compo); /// /// Given the path of a content item, this will return true if the content item exists underneath a list view content item @@ -78,18 +78,18 @@ namespace Umbraco.Cms.Core.Services /// bool HasContainerInPath(params int[] ids); - Attempt> CreateContainer(int parentContainerId, Guid key, string name, int userId = Constants.Security.SuperUserId); - Attempt SaveContainer(EntityContainer container, int userId = Constants.Security.SuperUserId); - EntityContainer GetContainer(int containerId); + Attempt?> CreateContainer(int parentContainerId, Guid key, string name, int userId = Constants.Security.SuperUserId); + 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); - Attempt DeleteContainer(int containerId, int userId = Constants.Security.SuperUserId); - Attempt> RenameContainer(int id, string name, int userId = Constants.Security.SuperUserId); + Attempt DeleteContainer(int containerId, int userId = Constants.Security.SuperUserId); + Attempt?> RenameContainer(int id, string name, int userId = Constants.Security.SuperUserId); - Attempt> Move(TItem moving, int containerId); - Attempt> Copy(TItem copying, int containerId); + Attempt?> Move(TItem moving, int containerId); + Attempt?> Copy(TItem copying, int containerId); TItem Copy(TItem original, string alias, string name, int parentId = -1); TItem Copy(TItem original, string alias, string name, TItem parent); } diff --git a/src/Umbraco.Core/Services/IDomainService.cs b/src/Umbraco.Core/Services/IDomainService.cs index bd96df4391..4ed8d31ce4 100644 --- a/src/Umbraco.Core/Services/IDomainService.cs +++ b/src/Umbraco.Core/Services/IDomainService.cs @@ -6,11 +6,11 @@ namespace Umbraco.Cms.Core.Services public interface IDomainService : IService { bool Exists(string domainName); - Attempt Delete(IDomain domain); + Attempt Delete(IDomain domain); IDomain GetByName(string name); - IDomain GetById(int id); + IDomain? GetById(int id); IEnumerable GetAll(bool includeWildcards); IEnumerable GetAssignedDomains(int contentId, bool includeWildcards); - Attempt Save(IDomain domainEntity); + Attempt Save(IDomain domainEntity); } } diff --git a/src/Umbraco.Core/Services/IEntityService.cs b/src/Umbraco.Core/Services/IEntityService.cs index a5bc143fcf..cb72735c02 100644 --- a/src/Umbraco.Core/Services/IEntityService.cs +++ b/src/Umbraco.Core/Services/IEntityService.cs @@ -136,14 +136,14 @@ namespace Umbraco.Cms.Core.Services /// Gets the parent of an entity. /// /// The identifier of the entity. - IEntitySlim GetParent(int id); + IEntitySlim? GetParent(int id); /// /// Gets the parent of an entity. /// /// The identifier of the entity. /// The object type of the parent. - IEntitySlim GetParent(int id, UmbracoObjectTypes objectType); + IEntitySlim? GetParent(int id, UmbracoObjectTypes objectType); /// /// Gets the children of an entity. @@ -214,7 +214,7 @@ namespace Umbraco.Cms.Core.Services /// /// Gets the CLR type of an entity. /// - Type GetEntityType(int id); + Type? GetEntityType(int id); /// /// Gets the integer identifier corresponding to a unique Guid identifier. diff --git a/src/Umbraco.Core/Services/IFileService.cs b/src/Umbraco.Core/Services/IFileService.cs index 4a989b8ba5..301c54b954 100644 --- a/src/Umbraco.Core/Services/IFileService.cs +++ b/src/Umbraco.Core/Services/IFileService.cs @@ -10,7 +10,7 @@ namespace Umbraco.Cms.Core.Services /// public interface IFileService : IService { - IEnumerable GetPartialViewSnippetNames(params string[] filterNames); + IEnumerable GetPartialViewSnippetNames(params string[] filterNames); void CreatePartialViewFolder(string folderPath); void CreatePartialViewMacroFolder(string folderPath); void DeletePartialViewFolder(string folderPath); @@ -22,14 +22,14 @@ namespace Umbraco.Cms.Core.Services /// An enumerable list of objects IEnumerable GetPartialViews(params string[] names); - IPartialView GetPartialView(string path); - IPartialView GetPartialViewMacro(string path); + IPartialView? GetPartialView(string path); + IPartialView? GetPartialViewMacro(string path); Attempt CreatePartialView(IPartialView partialView, string? snippetName = null, int userId = Constants.Security.SuperUserId); Attempt CreatePartialViewMacro(IPartialView partialView, string? snippetName = null, int userId = Constants.Security.SuperUserId); bool DeletePartialView(string path, int userId = Constants.Security.SuperUserId); bool DeletePartialViewMacro(string path, int userId = Constants.Security.SuperUserId); - Attempt SavePartialView(IPartialView partialView, int userId = Constants.Security.SuperUserId); - Attempt SavePartialViewMacro(IPartialView partialView, int userId = Constants.Security.SuperUserId); + Attempt SavePartialView(IPartialView partialView, int userId = Constants.Security.SuperUserId); + Attempt SavePartialViewMacro(IPartialView partialView, int userId = Constants.Security.SuperUserId); /// /// Gets the content of a partial view as a stream. @@ -84,7 +84,7 @@ namespace Umbraco.Cms.Core.Services /// /// Path of the stylesheet incl. extension /// A object - IStylesheet GetStylesheet(string path); + IStylesheet? GetStylesheet(string path); /// /// Saves a @@ -145,7 +145,7 @@ namespace Umbraco.Cms.Core.Services /// /// Name of the script incl. extension /// A object - IScript GetScript(string name); + IScript? GetScript(string name); /// /// Saves a @@ -212,21 +212,21 @@ namespace Umbraco.Cms.Core.Services /// /// The alias of the template. /// The object matching the alias, or null. - ITemplate GetTemplate(string alias); + ITemplate GetTemplate(string? alias); /// /// Gets a object by its identifier. /// /// The identifier of the template. /// The object matching the identifier, or null. - ITemplate GetTemplate(int id); + ITemplate? GetTemplate(int id); /// /// Gets a object by its guid identifier. /// /// The guid identifier of the template. /// The object matching the identifier, or null. - ITemplate GetTemplate(Guid id); + ITemplate? GetTemplate(Guid id); /// /// Gets the template descendants @@ -251,7 +251,7 @@ namespace Umbraco.Cms.Core.Services /// /// The template created /// - Attempt> CreateTemplateForContentType(string contentTypeAlias, string contentTypeName, int userId = Constants.Security.SuperUserId); + Attempt?> CreateTemplateForContentType(string contentTypeAlias, string contentTypeName, int userId = Constants.Security.SuperUserId); ITemplate CreateTemplateWithIdentity(string name, string alias, string content, ITemplate? masterTemplate = null, int userId = Constants.Security.SuperUserId); diff --git a/src/Umbraco.Core/Services/IMembershipMemberService.cs b/src/Umbraco.Core/Services/IMembershipMemberService.cs index 6093c0a4fe..828751e7e6 100644 --- a/src/Umbraco.Core/Services/IMembershipMemberService.cs +++ b/src/Umbraco.Core/Services/IMembershipMemberService.cs @@ -83,7 +83,7 @@ namespace Umbraco.Cms.Core.Services /// An can be of type or /// Id to use for retrieval /// - T GetByProviderKey(object id); + IUser? GetByProviderKey(object id); /// /// Get an by email @@ -91,7 +91,7 @@ namespace Umbraco.Cms.Core.Services /// An can be of type or /// Email to use for retrieval /// - T GetByEmail(string email); + IUser? GetByEmail(string email); /// /// Get an by username diff --git a/src/Umbraco.Core/Services/IPropertyValidationService.cs b/src/Umbraco.Core/Services/IPropertyValidationService.cs index 0e3cb2bae0..466eb39c66 100644 --- a/src/Umbraco.Core/Services/IPropertyValidationService.cs +++ b/src/Umbraco.Core/Services/IPropertyValidationService.cs @@ -10,7 +10,7 @@ namespace Umbraco.Cms.Core.Services /// /// Validates the content item's properties pass validation rules /// - bool IsPropertyDataValid(IContent content, out IProperty[] invalidProperties, CultureImpact impact); + bool IsPropertyDataValid(IContent content, out IProperty[] invalidProperties, CultureImpact? impact); /// /// Gets a value indicating whether the property has valid values. diff --git a/src/Umbraco.Core/Services/IPublicAccessService.cs b/src/Umbraco.Core/Services/IPublicAccessService.cs index c064493425..327dcfab89 100644 --- a/src/Umbraco.Core/Services/IPublicAccessService.cs +++ b/src/Umbraco.Core/Services/IPublicAccessService.cs @@ -24,21 +24,21 @@ namespace Umbraco.Cms.Core.Services /// /// /// Returns null if no entry is found - PublicAccessEntry GetEntryForContent(string contentPath); + PublicAccessEntry? GetEntryForContent(string contentPath); /// /// Returns true if the content has an entry for it's path /// /// /// - Attempt IsProtected(IContent content); + Attempt IsProtected(IContent content); /// /// Returns true if the content has an entry based on a content path /// /// /// - Attempt IsProtected(string contentPath); + Attempt IsProtected(string contentPath); /// /// Adds a rule if the entry doesn't already exist @@ -47,7 +47,7 @@ namespace Umbraco.Cms.Core.Services /// /// /// - Attempt> AddRule(IContent content, string ruleType, string ruleValue); + Attempt?> AddRule(IContent content, string ruleType, string ruleValue); /// /// Removes a rule @@ -55,19 +55,19 @@ namespace Umbraco.Cms.Core.Services /// /// /// - Attempt RemoveRule(IContent content, string ruleType, string ruleValue); + Attempt RemoveRule(IContent content, string ruleType, string ruleValue); /// /// Saves the entry /// /// - Attempt Save(PublicAccessEntry entry); + Attempt Save(PublicAccessEntry entry); /// /// Deletes the entry and all associated rules /// /// - Attempt Delete(PublicAccessEntry entry); + Attempt Delete(PublicAccessEntry entry); } } diff --git a/src/Umbraco.Core/Services/IRelationService.cs b/src/Umbraco.Core/Services/IRelationService.cs index b1381e2319..b82432ffd6 100644 --- a/src/Umbraco.Core/Services/IRelationService.cs +++ b/src/Umbraco.Core/Services/IRelationService.cs @@ -12,28 +12,28 @@ namespace Umbraco.Cms.Core.Services /// /// Id of the /// A object - IRelation GetById(int id); + IRelation? GetById(int id); /// /// Gets a by its Id /// /// Id of the /// A object - IRelationType GetRelationTypeById(int id); + IRelationType? GetRelationTypeById(int id); /// /// Gets a by its Id /// /// Id of the /// A object - IRelationType GetRelationTypeById(Guid id); + IRelationType? GetRelationTypeById(Guid id); /// /// Gets a by its Alias /// /// Alias of the /// A object - IRelationType GetRelationTypeByAlias(string alias); + IRelationType? GetRelationTypeByAlias(string alias); /// /// Gets all objects @@ -140,7 +140,7 @@ namespace Umbraco.Cms.Core.Services /// The id of the child item. /// The RelationType. /// The relation or null - IRelation GetByParentAndChildId(int parentId, int childId, IRelationType relationType); + IRelation? GetByParentAndChildId(int parentId, int childId, IRelationType relationType); /// /// Gets a list of objects by the Name of the diff --git a/src/Umbraco.Core/Services/IUserService.cs b/src/Umbraco.Core/Services/IUserService.cs index 2c9b2eb938..2742bf4936 100644 --- a/src/Umbraco.Core/Services/IUserService.cs +++ b/src/Umbraco.Core/Services/IUserService.cs @@ -99,7 +99,7 @@ namespace Umbraco.Cms.Core.Services /// /// Id of the User to retrieve /// - IProfile GetProfileById(int id); + IProfile? GetProfileById(int id); /// /// Gets a profile by username @@ -113,7 +113,7 @@ namespace Umbraco.Cms.Core.Services /// /// Id of the user to retrieve /// - IUser GetUserById(int id); + IUser? GetUserById(int id); /// /// Gets a users by Id @@ -226,14 +226,14 @@ namespace Umbraco.Cms.Core.Services /// /// Name of the UserGroup to retrieve /// - IUserGroup GetUserGroupByAlias(string name); + IUserGroup? GetUserGroupByAlias(string name); /// /// Gets a UserGroup by its Id /// /// Id of the UserGroup to retrieve /// - IUserGroup GetUserGroupById(int id); + IUserGroup? GetUserGroupById(int id); /// /// Saves a UserGroup diff --git a/src/Umbraco.Core/Services/OperationResult.cs b/src/Umbraco.Core/Services/OperationResult.cs index 43985fdde2..9d4323553f 100644 --- a/src/Umbraco.Core/Services/OperationResult.cs +++ b/src/Umbraco.Core/Services/OperationResult.cs @@ -190,13 +190,13 @@ namespace Umbraco.Cms.Core.Services /// The event messages produced by the operation. /// The exception that caused the operation to fail. /// A new attempt instance. - public static Attempt Fail(EventMessages eventMessages, Exception exception) + public static Attempt Fail(EventMessages eventMessages, Exception exception) { eventMessages.Add(new EventMessage("", exception.Message, EventMessageType.Error)); return Core.Attempt.Fail(new OperationResult(OperationResultType.FailedExceptionThrown, eventMessages), exception); } - public static Attempt> Fail(EventMessages eventMessages, Exception exception) + public static Attempt?> Fail(EventMessages eventMessages, Exception exception) { return Core.Attempt.Fail(new OperationResult(OperationResultType.FailedExceptionThrown, eventMessages), exception); } @@ -207,7 +207,7 @@ namespace Umbraco.Cms.Core.Services return Core.Attempt.Fail(new OperationResult(statusType, eventMessages)); } - public static Attempt> Fail(TStatusType statusType, EventMessages eventMessages, Exception exception) + public static Attempt?> Fail(TStatusType statusType, EventMessages eventMessages, Exception exception) where TStatusType : struct { return Core.Attempt.Fail(new OperationResult(statusType, eventMessages), exception); @@ -225,13 +225,13 @@ namespace Umbraco.Cms.Core.Services return Core.Attempt.Fail(new OperationResult(statusType, eventMessages, value)); } - public static Attempt> Fail(TStatusType statusType, EventMessages eventMessages, Exception exception) + public static Attempt?> Fail(TStatusType statusType, EventMessages eventMessages, Exception exception) where TStatusType : struct { return Core.Attempt.Fail(new OperationResult(statusType, eventMessages), exception); } - public static Attempt> Fail(TStatusType statusType, EventMessages eventMessages, TValue value, Exception exception) + public static Attempt?> Fail(TStatusType statusType, EventMessages eventMessages, TValue value, Exception exception) where TStatusType : struct { return Core.Attempt.Fail(new OperationResult(statusType, eventMessages, value), exception); diff --git a/src/Umbraco.Core/Services/PropertyValidationService.cs b/src/Umbraco.Core/Services/PropertyValidationService.cs index 91ea968c2a..30aff6dc9a 100644 --- a/src/Umbraco.Core/Services/PropertyValidationService.cs +++ b/src/Umbraco.Core/Services/PropertyValidationService.cs @@ -49,9 +49,9 @@ namespace Umbraco.Cms.Core.Services IDataType dataType, object postedValue, bool isRequired, - string validationRegExp, - string isRequiredMessage, - string validationRegExpMessage) + string? validationRegExp, + string? isRequiredMessage, + string? validationRegExpMessage) { // Retrieve default messages used for required and regex validatation. We'll replace these // if set with custom ones if they've been provided for a given property. @@ -82,13 +82,17 @@ namespace Umbraco.Cms.Core.Services } /// - public bool IsPropertyDataValid(IContent content, out IProperty[] invalidProperties, CultureImpact impact) + public bool IsPropertyDataValid(IContent content, out IProperty[] invalidProperties, CultureImpact? impact) { // select invalid properties invalidProperties = content.Properties.Where(x => { var propertyTypeVaries = x.PropertyType.VariesByCulture(); + if (impact is null) + { + return false; + } // impacts invariant = validate invariant property, invariant culture if (impact.ImpactsOnlyInvariantCulture) return !(propertyTypeVaries || IsPropertyValid(x, null)); @@ -115,7 +119,7 @@ namespace Umbraco.Cms.Core.Services } /// - public bool IsPropertyValid(IProperty property, string culture = "*", string segment = "*") + public bool IsPropertyValid(IProperty property, string? culture = "*", string segment = "*") { //NOTE - the pvalue and vvalues logic in here is borrowed directly from the Property.Values setter so if you are wondering what that's all about, look there. // The underlying Property._pvalue and Property._vvalues are not exposed but we can re-create these values ourselves which is what it's doing. diff --git a/src/Umbraco.Core/Services/PublicAccessService.cs b/src/Umbraco.Core/Services/PublicAccessService.cs index 0d0d82c64c..0b4709873d 100644 --- a/src/Umbraco.Core/Services/PublicAccessService.cs +++ b/src/Umbraco.Core/Services/PublicAccessService.cs @@ -53,7 +53,7 @@ namespace Umbraco.Cms.Core.Services /// /// NOTE: This method get's called *very* often! This will return the results from cache /// - public PublicAccessEntry GetEntryForContent(string contentPath) + public PublicAccessEntry? GetEntryForContent(string contentPath) { //Get all ids in the path for the content item and ensure they all // parse to ints that are not -1. @@ -84,7 +84,7 @@ namespace Umbraco.Cms.Core.Services /// /// /// - public Attempt IsProtected(IContent content) + public Attempt IsProtected(IContent content) { var result = GetEntryForContent(content); return Attempt.If(result != null, result); @@ -95,7 +95,7 @@ namespace Umbraco.Cms.Core.Services /// /// /// - public Attempt IsProtected(string contentPath) + public Attempt IsProtected(string contentPath) { var result = GetEntryForContent(contentPath); return Attempt.If(result != null, result); @@ -108,10 +108,10 @@ namespace Umbraco.Cms.Core.Services /// /// /// - public Attempt> AddRule(IContent content, string ruleType, string ruleValue) + public Attempt?> AddRule(IContent content, string ruleType, string ruleValue) { var evtMsgs = EventMessagesFactory.Get(); - PublicAccessEntry entry; + PublicAccessEntry? entry; using (var scope = ScopeProvider.CreateScope()) { entry = _publicAccessRepository.GetMany().FirstOrDefault(x => x.ProtectedNodeId == content.Id); @@ -152,17 +152,17 @@ namespace Umbraco.Cms.Core.Services /// /// /// - public Attempt RemoveRule(IContent content, string ruleType, string ruleValue) + public Attempt RemoveRule(IContent content, string ruleType, string ruleValue) { var evtMsgs = EventMessagesFactory.Get(); - PublicAccessEntry entry; + PublicAccessEntry? entry; using (var scope = ScopeProvider.CreateScope()) { entry = _publicAccessRepository.GetMany().FirstOrDefault(x => x.ProtectedNodeId == content.Id); - if (entry == null) return Attempt.Fail(); // causes rollback // causes rollback + if (entry == null) return Attempt.Fail(); // causes rollback // causes rollback var existingRule = entry.Rules.FirstOrDefault(x => x.RuleType == ruleType && x.RuleValue == ruleValue); - if (existingRule == null) return Attempt.Fail(); // causes rollback // causes rollback + if (existingRule == null) return Attempt.Fail(); // causes rollback // causes rollback entry.RemoveRule(existingRule); @@ -186,7 +186,7 @@ namespace Umbraco.Cms.Core.Services /// Saves the entry /// /// - public Attempt Save(PublicAccessEntry entry) + public Attempt Save(PublicAccessEntry entry) { var evtMsgs = EventMessagesFactory.Get(); @@ -212,7 +212,7 @@ namespace Umbraco.Cms.Core.Services /// Deletes the entry and all associated rules /// /// - public Attempt Delete(PublicAccessEntry entry) + public Attempt Delete(PublicAccessEntry entry) { var evtMsgs = EventMessagesFactory.Get(); diff --git a/src/Umbraco.Core/Services/RedirectUrlService.cs b/src/Umbraco.Core/Services/RedirectUrlService.cs index 0914086289..0102da63b4 100644 --- a/src/Umbraco.Core/Services/RedirectUrlService.cs +++ b/src/Umbraco.Core/Services/RedirectUrlService.cs @@ -109,7 +109,7 @@ namespace Umbraco.Cms.Core.Services } } - public IRedirectUrl GetMostRecentRedirectUrl(string url, string culture) + public IRedirectUrl GetMostRecentRedirectUrl(string url, string? culture) { if (string.IsNullOrWhiteSpace(culture)) return GetMostRecentRedirectUrl(url); using (var scope = ScopeProvider.CreateScope(autoComplete: true)) diff --git a/src/Umbraco.Core/Services/RelationService.cs b/src/Umbraco.Core/Services/RelationService.cs index d4cf07e9d0..0e75601965 100644 --- a/src/Umbraco.Core/Services/RelationService.cs +++ b/src/Umbraco.Core/Services/RelationService.cs @@ -31,7 +31,7 @@ namespace Umbraco.Cms.Core.Services } /// - public IRelation GetById(int id) + public IRelation? GetById(int id) { using (var scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -40,7 +40,7 @@ namespace Umbraco.Cms.Core.Services } /// - public IRelationType GetRelationTypeById(int id) + public IRelationType? GetRelationTypeById(int id) { using (var scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -49,7 +49,7 @@ namespace Umbraco.Cms.Core.Services } /// - public IRelationType GetRelationTypeById(Guid id) + public IRelationType? GetRelationTypeById(Guid id) { using (var scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -58,7 +58,7 @@ namespace Umbraco.Cms.Core.Services } /// - public IRelationType GetRelationTypeByAlias(string alias) => GetRelationType(alias); + public IRelationType? GetRelationTypeByAlias(string alias) => GetRelationType(alias); /// public IEnumerable GetAllRelations(params int[] ids) @@ -98,7 +98,7 @@ namespace Umbraco.Cms.Core.Services public IEnumerable GetByParentId(int id) => GetByParentId(id, null); /// - public IEnumerable GetByParentId(int id, string relationTypeAlias) + public IEnumerable GetByParentId(int id, string? relationTypeAlias) { using (var scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -108,7 +108,7 @@ namespace Umbraco.Cms.Core.Services return _relationRepository.Get(qry1); } - var relationType = GetRelationType(relationTypeAlias); + var relationType = GetRelationType(relationTypeAlias!); if (relationType == null) return Enumerable.Empty(); @@ -127,7 +127,7 @@ namespace Umbraco.Cms.Core.Services public IEnumerable GetByChildId(int id) => GetByChildId(id, null); /// - public IEnumerable GetByChildId(int id, string relationTypeAlias) + public IEnumerable GetByChildId(int id, string? relationTypeAlias) { using (var scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -137,7 +137,7 @@ namespace Umbraco.Cms.Core.Services return _relationRepository.Get(qry1); } - var relationType = GetRelationType(relationTypeAlias); + var relationType = GetRelationType(relationTypeAlias!); if (relationType == null) return Enumerable.Empty(); @@ -176,7 +176,7 @@ namespace Umbraco.Cms.Core.Services } /// - public IRelation GetByParentAndChildId(int parentId, int childId, IRelationType relationType) + public IRelation? GetByParentAndChildId(int parentId, int childId, IRelationType relationType) { using (var scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -225,7 +225,7 @@ namespace Umbraco.Cms.Core.Services } /// - public IEnumerable GetPagedByRelationTypeId(int relationTypeId, long pageIndex, int pageSize, out long totalRecords, Ordering ordering = null) + public IEnumerable GetPagedByRelationTypeId(int relationTypeId, long pageIndex, int pageSize, out long totalRecords, Ordering? ordering = null) { using (var scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -566,7 +566,7 @@ namespace Umbraco.Cms.Core.Services #region Private Methods - private IRelationType GetRelationType(string relationTypeAlias) + private IRelationType? GetRelationType(string relationTypeAlias) { using (var scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -590,7 +590,7 @@ namespace Umbraco.Cms.Core.Services return relations; } - private void Audit(AuditType type, int userId, int objectId, string message = null) + private void Audit(AuditType type, int userId, int objectId, string? message = null) { _auditRepository.Save(new AuditItem(objectId, type, userId, ObjectTypes.GetName(UmbracoObjectTypes.RelationType), message)); } diff --git a/src/Umbraco.Core/Services/TagService.cs b/src/Umbraco.Core/Services/TagService.cs index a2bbc27cb6..0c07cd1afa 100644 --- a/src/Umbraco.Core/Services/TagService.cs +++ b/src/Umbraco.Core/Services/TagService.cs @@ -53,7 +53,7 @@ namespace Umbraco.Cms.Core.Services } /// - public IEnumerable GetTaggedContentByTag(string tag, string group = null, string? culture = null) + public IEnumerable GetTaggedContentByTag(string tag, string? group = null, string? culture = null) { using (ScopeProvider.CreateScope(autoComplete: true)) { @@ -71,7 +71,7 @@ namespace Umbraco.Cms.Core.Services } /// - public IEnumerable GetTaggedMediaByTag(string tag, string group = null, string? culture = null) + public IEnumerable GetTaggedMediaByTag(string tag, string? group = null, string? culture = null) { using (ScopeProvider.CreateScope(autoComplete: true)) { @@ -89,7 +89,7 @@ namespace Umbraco.Cms.Core.Services } /// - public IEnumerable GetTaggedMembersByTag(string tag, string group = null, string? culture = null) + public IEnumerable GetTaggedMembersByTag(string tag, string? group = null, string? culture = null) { using (ScopeProvider.CreateScope(autoComplete: true)) { @@ -98,7 +98,7 @@ namespace Umbraco.Cms.Core.Services } /// - public IEnumerable GetAllTags(string group = null, string? culture = null) + public IEnumerable GetAllTags(string? group = null, string? culture = null) { using (ScopeProvider.CreateScope(autoComplete: true)) { @@ -107,7 +107,7 @@ namespace Umbraco.Cms.Core.Services } /// - public IEnumerable GetAllContentTags(string group = null, string? culture = null) + public IEnumerable GetAllContentTags(string? group = null, string? culture = null) { using (ScopeProvider.CreateScope(autoComplete: true)) { @@ -116,7 +116,7 @@ namespace Umbraco.Cms.Core.Services } /// - public IEnumerable GetAllMediaTags(string group = null, string? culture = null) + public IEnumerable GetAllMediaTags(string? group = null, string? culture = null) { using (ScopeProvider.CreateScope(autoComplete: true)) { @@ -125,7 +125,7 @@ namespace Umbraco.Cms.Core.Services } /// - public IEnumerable GetAllMemberTags(string group = null, string? culture = null) + public IEnumerable GetAllMemberTags(string? group = null, string? culture = null) { using (ScopeProvider.CreateScope(autoComplete: true)) { @@ -134,7 +134,7 @@ namespace Umbraco.Cms.Core.Services } /// - public IEnumerable GetTagsForProperty(int contentId, string propertyTypeAlias, string group = null, string? culture = null) + public IEnumerable GetTagsForProperty(int contentId, string propertyTypeAlias, string? group = null, string? culture = null) { using (ScopeProvider.CreateScope(autoComplete: true)) { @@ -143,7 +143,7 @@ namespace Umbraco.Cms.Core.Services } /// - public IEnumerable GetTagsForEntity(int contentId, string group = null, string? culture = null) + public IEnumerable GetTagsForEntity(int contentId, string? group = null, string? culture = null) { using (ScopeProvider.CreateScope(autoComplete: true)) { @@ -152,7 +152,7 @@ namespace Umbraco.Cms.Core.Services } /// - public IEnumerable GetTagsForProperty(Guid contentId, string propertyTypeAlias, string group = null, string? culture = null) + public IEnumerable GetTagsForProperty(Guid contentId, string propertyTypeAlias, string? group = null, string? culture = null) { using (ScopeProvider.CreateScope(autoComplete: true)) { @@ -161,7 +161,7 @@ namespace Umbraco.Cms.Core.Services } /// - public IEnumerable GetTagsForEntity(Guid contentId, string group = null, string? culture = null) + public IEnumerable GetTagsForEntity(Guid contentId, string? group = null, string? culture = null) { using (ScopeProvider.CreateScope(autoComplete: true)) { diff --git a/src/Umbraco.Core/Services/UserService.cs b/src/Umbraco.Core/Services/UserService.cs index 47205a3b11..64aef06761 100644 --- a/src/Umbraco.Core/Services/UserService.cs +++ b/src/Umbraco.Core/Services/UserService.cs @@ -154,7 +154,7 @@ namespace Umbraco.Cms.Core.Services /// /// Id /// - public IUser GetById(int id) + public IUser? GetById(int id) { using (var scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -167,7 +167,7 @@ namespace Umbraco.Cms.Core.Services /// /// Id to use for retrieval /// - public IUser GetByProviderKey(object id) + public IUser? GetByProviderKey(object id) { var asInt = id.TryConvertTo(); return asInt.Success ? GetById(asInt.Result) : null; @@ -178,7 +178,7 @@ namespace Umbraco.Cms.Core.Services /// /// Email to use for retrieval /// - public IUser GetByEmail(string email) + public IUser? GetByEmail(string email) { using (var scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -517,22 +517,22 @@ namespace Umbraco.Cms.Core.Services } } - public IEnumerable GetAll(long pageIndex, int pageSize, out long totalRecords, string orderBy, Direction orderDirection, UserState[] userState = null, string[] userGroups = null, string filter = null) + public IEnumerable GetAll(long pageIndex, int pageSize, out long totalRecords, string orderBy, Direction orderDirection, UserState[]? userState = null, string[]? userGroups = null, string? filter = null) { - IQuery filterQuery = null; + IQuery? filterQuery = null; if (filter.IsNullOrWhiteSpace() == false) { - filterQuery = Query().Where(x => x.Name.Contains(filter) || x.Username.Contains(filter)); + filterQuery = Query().Where(x => x.Name.Contains(filter!) || x.Username.Contains(filter!)); } return GetAll(pageIndex, pageSize, out totalRecords, orderBy, orderDirection, userState, userGroups, null, filterQuery); } - public IEnumerable GetAll(long pageIndex, int pageSize, out long totalRecords, string orderBy, Direction orderDirection, UserState[] userState = null, string[] includeUserGroups = null, string[] excludeUserGroups = null, IQuery filter = null) + public IEnumerable GetAll(long pageIndex, int pageSize, out long totalRecords, string orderBy, Direction orderDirection, UserState[]? userState = null, string[]? includeUserGroups = null, string[]? excludeUserGroups = null, IQuery? filter = null) { using (var scope = ScopeProvider.CreateScope(autoComplete: true)) { - Expression> sort; + Expression> sort; switch (orderBy.ToUpperInvariant()) { case "USERNAME": @@ -631,7 +631,7 @@ namespace Umbraco.Cms.Core.Services /// /// Id of the User to retrieve /// - public IProfile GetProfileById(int id) + public IProfile? GetProfileById(int id) { //This is called a TON. Go get the full user from cache which should already be IProfile var fullUser = GetUserById(id); @@ -658,7 +658,7 @@ namespace Umbraco.Cms.Core.Services /// /// Id of the user to retrieve /// - public IUser GetUserById(int id) + public IUser? GetUserById(int id) { using (var scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -700,7 +700,7 @@ namespace Umbraco.Cms.Core.Services /// Id of the group /// Permissions as enumerable list of If nothing is specified all permissions are removed. /// Specify the nodes to replace permissions for. - public void ReplaceUserGroupPermissions(int groupId, IEnumerable permissions, params int[] entityIds) + public void ReplaceUserGroupPermissions(int groupId, IEnumerable? permissions, params int[] entityIds) { if (entityIds.Length == 0) return; @@ -713,8 +713,11 @@ namespace Umbraco.Cms.Core.Services scope.Complete(); var assigned = permissions?.Select(p => p.ToString(CultureInfo.InvariantCulture)).ToArray(); - var entityPermissions = entityIds.Select(x => new EntityPermission(groupId, x, assigned)).ToArray(); - scope.Notifications.Publish(new AssignedUserGroupPermissionsNotification(entityPermissions, evtMsgs)); + if (assigned is not null) + { + var entityPermissions = entityIds.Select(x => new EntityPermission(groupId, x, assigned)).ToArray(); + scope.Notifications.Publish(new AssignedUserGroupPermissionsNotification(entityPermissions, evtMsgs)); + } } } @@ -772,7 +775,7 @@ namespace Umbraco.Cms.Core.Services /// /// Alias of the UserGroup to retrieve /// - public IUserGroup GetUserGroupByAlias(string alias) + public IUserGroup? GetUserGroupByAlias(string alias) { if (string.IsNullOrWhiteSpace(alias)) throw new ArgumentException("Value cannot be null or whitespace.", "alias"); @@ -789,7 +792,7 @@ namespace Umbraco.Cms.Core.Services /// /// Id of the UserGroup to retrieve /// - public IUserGroup GetUserGroupById(int id) + public IUserGroup? GetUserGroupById(int id) { using (var scope = ScopeProvider.CreateScope(autoComplete: true)) { @@ -806,7 +809,7 @@ namespace Umbraco.Cms.Core.Services /// than all users will be removed from this group and only these users will be added /// /// Default is True otherwise set to False to not raise events - public void Save(IUserGroup userGroup, int[] userIds = null) + public void Save(IUserGroup userGroup, int[]? userIds = null) { var evtMsgs = EventMessagesFactory.Get(); @@ -957,11 +960,11 @@ namespace Umbraco.Cms.Core.Services /// /// User to check permissions for /// Path to check permissions for - public EntityPermissionSet GetPermissionsForPath(IUser user, string path) + public EntityPermissionSet GetPermissionsForPath(IUser user, string? path) { - var nodeIds = path.GetIdsFromPathReversed(); + var nodeIds = path?.GetIdsFromPathReversed(); - if (nodeIds.Length == 0 || user is null) + if (nodeIds is null || nodeIds.Length == 0 || user is null) return EntityPermissionSet.Empty(); //collect all permissions structures for all nodes for all groups belonging to the user @@ -1039,7 +1042,7 @@ namespace Umbraco.Cms.Core.Services //iterate deepest to shallowest foreach (var pathId in pathIds) { - EntityPermission[] permissionsForNodeAndGroup; + EntityPermission[]? permissionsForNodeAndGroup; if (byGroup.Value.TryGetValue(pathId, out permissionsForNodeAndGroup) == false) continue; @@ -1088,7 +1091,7 @@ namespace Umbraco.Cms.Core.Services /// Flag indicating if we want to include the default group permissions for each result if there are not explicit permissions set /// /// - internal static EntityPermission GetPermissionsForPathForGroup( + internal static EntityPermission? GetPermissionsForPathForGroup( IEnumerable pathPermissions, int[] pathIds, bool fallbackToDefaultPermissions = false) @@ -1099,7 +1102,7 @@ namespace Umbraco.Cms.Core.Services //then the permissions assigned to the path will be the 'deepest' node found that has permissions foreach (var id in pathIds) { - EntityPermission permission; + EntityPermission? permission; if (permissionsByEntityId.TryGetValue(id, out permission)) { //don't return the default permissions if that is the one assigned here (we'll do that below if nothing was found) diff --git a/src/Umbraco.Core/Xml/XPath/MacroNavigator.cs b/src/Umbraco.Core/Xml/XPath/MacroNavigator.cs index 439d2b1ca3..2e2819066b 100644 --- a/src/Umbraco.Core/Xml/XPath/MacroNavigator.cs +++ b/src/Umbraco.Core/Xml/XPath/MacroNavigator.cs @@ -129,7 +129,7 @@ namespace Umbraco.Cms.Core.Xml.XPath case StatePosition.ParameterAttribute: position = string.Format("At parameter attribute '{0}/{1}'.", _macro.Parameters[_state.ParameterIndex].Name, - _macro.Parameters[_state.ParameterIndex].Attributes[_state.ParameterAttributeIndex].Key); + _macro.Parameters[_state.ParameterIndex].Attributes?[_state.ParameterAttributeIndex].Key); break; case StatePosition.ParameterNavigator: position = string.Format("In parameter '{0}{1}' navigator.", @@ -195,7 +195,7 @@ namespace Umbraco.Cms.Core.Xml.XPath public MacroParameter(string name, XPathNavigator navigator, int maxNavigatorDepth = int.MaxValue, bool wrapNavigatorInNodes = false, - IEnumerable> attributes = null) + IEnumerable>? attributes = null) { Name = name; MaxNavigatorDepth = maxNavigatorDepth; @@ -210,11 +210,11 @@ namespace Umbraco.Cms.Core.Xml.XPath } public string Name { get; private set; } - public string StringValue { get; private set; } - public XPathNavigator NavigatorValue { get; private set; } + public string? StringValue { get; private set; } + public XPathNavigator? NavigatorValue { get; private set; } public int MaxNavigatorDepth { get; private set; } public bool WrapNavigatorInNodes { get; private set; } - public KeyValuePair[] Attributes { get; private set; } + public KeyValuePair[]? Attributes { get; private set; } } #endregion @@ -261,7 +261,7 @@ namespace Umbraco.Cms.Core.Xml.XPath } break; case StatePosition.ParameterNavigator: - isEmpty = _state.ParameterNavigator.IsEmptyElement; + isEmpty = _state.ParameterNavigator?.IsEmptyElement ?? true; break; case StatePosition.ParameterNodes: isEmpty = _macro.Parameters[_state.ParameterIndex].NavigatorValue == null; @@ -328,10 +328,10 @@ namespace Umbraco.Cms.Core.Xml.XPath name = _macro.Parameters[_state.ParameterIndex].Name; break; case StatePosition.ParameterAttribute: - name = _macro.Parameters[_state.ParameterIndex].Attributes[_state.ParameterAttributeIndex].Key; + name = _macro.Parameters[_state.ParameterIndex].Attributes?[_state.ParameterAttributeIndex].Key ?? string.Empty; break; case StatePosition.ParameterNavigator: - name = _state.ParameterNavigator.Name; + name = _state.ParameterNavigator?.Name ?? string.Empty; break; case StatePosition.ParameterNodes: name = "nodes"; @@ -400,7 +400,7 @@ namespace Umbraco.Cms.Core.Xml.XPath switch (_state.Position) { case StatePosition.ParameterNavigator: - succ = _state.ParameterNavigator.MoveToFirstAttribute(); + succ = _state.ParameterNavigator?.MoveToFirstAttribute() ?? false; break; case StatePosition.Parameter: if (_macro.Parameters[_state.ParameterIndex].Attributes != null) @@ -490,7 +490,7 @@ namespace Umbraco.Cms.Core.Xml.XPath else { // move to first doc child => increment depth, else (property child) do nothing - succ = _state.ParameterNavigator.MoveToFirstChild(); + succ = _state.ParameterNavigator?.MoveToFirstChild() ?? false; if (succ && IsDoc(_state.ParameterNavigator)) { ++_state.ParameterNavigatorDepth; @@ -502,7 +502,7 @@ namespace Umbraco.Cms.Core.Xml.XPath if (_macro.Parameters[_state.ParameterIndex].NavigatorValue != null) { // never use the raw parameter's navigator - _state.ParameterNavigator = _macro.Parameters[_state.ParameterIndex].NavigatorValue.Clone(); + _state.ParameterNavigator = _macro.Parameters[_state.ParameterIndex].NavigatorValue?.Clone(); _state.Position = StatePosition.ParameterNavigator; succ = true; DebugState(); @@ -594,13 +594,13 @@ namespace Umbraco.Cms.Core.Xml.XPath break; case StatePosition.ParameterNavigator: var wasDoc = IsDoc(_state.ParameterNavigator); - succ = _state.ParameterNavigator.MoveToNext(); + succ = _state.ParameterNavigator?.MoveToNext() ?? false; if (succ && !wasDoc && IsDoc(_state.ParameterNavigator)) { // move to first doc child => increment depth, else (another property child) do nothing if (_state.ParameterNavigatorDepth == _macro.Parameters[_state.ParameterIndex].MaxNavigatorDepth) { - _state.ParameterNavigator.MoveToPrevious(); + _state.ParameterNavigator?.MoveToPrevious(); succ = false; } else @@ -652,7 +652,7 @@ namespace Umbraco.Cms.Core.Xml.XPath break; case StatePosition.ParameterNavigator: var wasDoc = IsDoc(_state.ParameterNavigator); - succ = _state.ParameterNavigator.MoveToPrevious(); + succ = _state.ParameterNavigator?.MoveToPrevious() ?? false; if (succ && wasDoc && !IsDoc(_state.ParameterNavigator)) { // move from doc child back to property child => decrement depth @@ -688,10 +688,10 @@ namespace Umbraco.Cms.Core.Xml.XPath switch (_state.Position) { case StatePosition.ParameterNavigator: - succ = _state.ParameterNavigator.MoveToNextAttribute(); + succ = _state.ParameterNavigator?.MoveToNextAttribute() ?? false; break; case StatePosition.ParameterAttribute: - if (_state.ParameterAttributeIndex == _macro.Parameters[_state.ParameterIndex].Attributes.Length - 1) + if (_state.ParameterAttributeIndex == _macro.Parameters[_state.ParameterIndex].Attributes?.Length - 1) succ = false; else { @@ -745,7 +745,7 @@ namespace Umbraco.Cms.Core.Xml.XPath break; case StatePosition.ParameterNavigator: var wasDoc = IsDoc(_state.ParameterNavigator); - succ = _state.ParameterNavigator.MoveToParent(); + succ = _state.ParameterNavigator?.MoveToParent() ?? false; if (succ) { // move from doc child => decrement depth @@ -847,7 +847,7 @@ namespace Umbraco.Cms.Core.Xml.XPath type = XPathNodeType.Element; break; case StatePosition.ParameterNavigator: - type = _state.ParameterNavigator.NodeType; + type = _state.ParameterNavigator?.NodeType ?? XPathNodeType.Root; break; case StatePosition.ParameterAttribute: type = XPathNodeType.Attribute; @@ -888,7 +888,7 @@ namespace Umbraco.Cms.Core.Xml.XPath DebugEnter("Value"); string value; - XPathNavigator nav; + XPathNavigator? nav; switch (_state.Position) { case StatePosition.Parameter: @@ -906,10 +906,10 @@ namespace Umbraco.Cms.Core.Xml.XPath } break; case StatePosition.ParameterAttribute: - value = _macro.Parameters[_state.ParameterIndex].Attributes[_state.ParameterAttributeIndex].Value; + value = _macro.Parameters[_state.ParameterIndex].Attributes?[_state.ParameterAttributeIndex].Value ?? string.Empty; break; case StatePosition.ParameterNavigator: - value = _state.ParameterNavigator.Value; + value = _state.ParameterNavigator?.Value ?? string.Empty; break; case StatePosition.ParameterNodes: nav = _macro.Parameters[_state.ParameterIndex].NavigatorValue; @@ -923,7 +923,7 @@ namespace Umbraco.Cms.Core.Xml.XPath } break; case StatePosition.ParameterText: - value = _macro.Parameters[_state.ParameterIndex].StringValue; + value = _macro.Parameters[_state.ParameterIndex].StringValue ?? string.Empty; break; case StatePosition.Macro: case StatePosition.Root: @@ -938,8 +938,12 @@ namespace Umbraco.Cms.Core.Xml.XPath } } - private static bool IsDoc(XPathNavigator nav) + private static bool IsDoc(XPathNavigator? nav) { + if (nav is null) + { + return false; + } if (nav.NodeType != XPathNodeType.Element) return false; @@ -1002,7 +1006,7 @@ namespace Umbraco.Cms.Core.Xml.XPath if (Position == StatePosition.ParameterNavigator) { - ParameterNavigator = other.ParameterNavigator.Clone(); + ParameterNavigator = other.ParameterNavigator?.Clone(); ParameterNavigatorDepth = other.ParameterNavigatorDepth; ParameterAttributeIndex = other.ParameterAttributeIndex; } @@ -1023,11 +1027,15 @@ namespace Umbraco.Cms.Core.Xml.XPath public int ParameterAttributeIndex { get; set; } // gets or sets the element navigator - public XPathNavigator ParameterNavigator { get; set; } + public XPathNavigator? ParameterNavigator { get; set; } // gets a value indicating whether this state is at the same position as another one. public bool IsSamePosition(State other) { + if (other.ParameterNavigator is null || ParameterNavigator is null) + { + return false; + } return other.Position == Position && (Position != StatePosition.ParameterNavigator || other.ParameterNavigator.IsSamePosition(ParameterNavigator)) && other.ParameterIndex == ParameterIndex diff --git a/src/Umbraco.Core/Xml/XPath/NavigableNavigator.cs b/src/Umbraco.Core/Xml/XPath/NavigableNavigator.cs index a77f14bce8..c21ffda281 100644 --- a/src/Umbraco.Core/Xml/XPath/NavigableNavigator.cs +++ b/src/Umbraco.Core/Xml/XPath/NavigableNavigator.cs @@ -426,19 +426,19 @@ namespace Umbraco.Cms.Core.Xml.XPath get { DebugEnter("Name"); - string? name; + string name; switch (_state.Position) { case StatePosition.PropertyXml: - name = _state.XmlFragmentNavigator.Name; + name = _state.XmlFragmentNavigator?.Name ?? string.Empty; break; case StatePosition.Attribute: case StatePosition.PropertyElement: - name = _state.FieldIndex == -1 ? "id" : _state.CurrentFieldType?.Name; + name = _state.FieldIndex == -1 ? "id" : _state.CurrentFieldType?.Name ?? string.Empty; break; case StatePosition.Element: - name = _state.Content?.Type.Name; + name = _state.Content?.Type.Name ?? string.Empty; break; case StatePosition.PropertyText: name = string.Empty; @@ -854,7 +854,7 @@ namespace Umbraco.Cms.Core.Xml.XPath switch (_state.Position) { case StatePosition.PropertyXml: - succ = _state.XmlFragmentNavigator.MoveToNextAttribute(); + succ = _state.XmlFragmentNavigator?.MoveToNextAttribute() ?? false; break; case StatePosition.Attribute: if (_state.FieldIndex == _lastAttributeIndex) @@ -913,9 +913,9 @@ namespace Umbraco.Cms.Core.Xml.XPath succ = true; break; case StatePosition.PropertyXml: - if (_state.XmlFragmentNavigator.MoveToParent() == false) + if (_state.XmlFragmentNavigator?.MoveToParent() == false) throw new InvalidOperationException("Could not move to parent in fragment."); - if (_state.XmlFragmentNavigator.NodeType == XPathNodeType.Root) + if (_state.XmlFragmentNavigator?.NodeType == XPathNodeType.Root) { _state.XmlFragmentNavigator = null; _state.Position = StatePosition.PropertyElement; @@ -989,7 +989,7 @@ namespace Umbraco.Cms.Core.Xml.XPath switch (_state.Position) { case StatePosition.PropertyXml: - type = _state.XmlFragmentNavigator.NodeType; + type = _state.XmlFragmentNavigator?.NodeType ?? XPathNodeType.Root; break; case StatePosition.Attribute: type = XPathNodeType.Attribute; @@ -1029,19 +1029,19 @@ namespace Umbraco.Cms.Core.Xml.XPath get { DebugEnter("Value"); - string? value; + string value; switch (_state.Position) { case StatePosition.PropertyXml: - value = _state.XmlFragmentNavigator.Value; + value = _state.XmlFragmentNavigator?.Value ?? string.Empty; break; case StatePosition.Attribute: case StatePosition.PropertyText: case StatePosition.PropertyElement: if (_state.FieldIndex == -1) { - value = _state.Content?.Id.ToString(CultureInfo.InvariantCulture); + value = _state.Content?.Id.ToString(CultureInfo.InvariantCulture) ?? string.Empty; } else { @@ -1141,7 +1141,7 @@ namespace Umbraco.Cms.Core.Xml.XPath Depth = other.Depth; if (Position == StatePosition.PropertyXml) - XmlFragmentNavigator = other.XmlFragmentNavigator.Clone(); + XmlFragmentNavigator = other.XmlFragmentNavigator?.Clone(); // NielsK did //Parent = other.Parent;