diff --git a/src/Umbraco.Core/Attempt.cs b/src/Umbraco.Core/Attempt.cs index 0a8987726a..f9c254b9d4 100644 --- a/src/Umbraco.Core/Attempt.cs +++ b/src/Umbraco.Core/Attempt.cs @@ -51,9 +51,9 @@ namespace Umbraco.Cms.Core /// The type of the attempted operation result. /// The result of the attempt. /// The failed attempt. - public static Attempt Fail(TResult result) + public static Attempt Fail(TResult result) { - return Attempt.Fail(result); + return Attempt.Fail(result); } /// diff --git a/src/Umbraco.Core/Cache/AppCacheExtensions.cs b/src/Umbraco.Core/Cache/AppCacheExtensions.cs index dfb0a7ae72..f5e92cc116 100644 --- a/src/Umbraco.Core/Cache/AppCacheExtensions.cs +++ b/src/Umbraco.Core/Cache/AppCacheExtensions.cs @@ -31,13 +31,13 @@ namespace Umbraco.Extensions provider.Insert(cacheKey, () => getCacheItem(), timeout, isSliding, dependentFiles); } - public static IEnumerable GetCacheItemsByKeySearch(this IAppCache provider, string keyStartsWith) + public static IEnumerable GetCacheItemsByKeySearch(this IAppCache provider, string keyStartsWith) { var result = provider.SearchByKey(keyStartsWith); return result.Select(x => x.TryConvertTo().Result); } - public static IEnumerable GetCacheItemsByKeyExpression(this IAppCache provider, string regexString) + public static IEnumerable GetCacheItemsByKeyExpression(this IAppCache provider, string regexString) { var result = provider.SearchByRegex(regexString); return result.Select(x => x.TryConvertTo().Result); diff --git a/src/Umbraco.Core/Cache/AppPolicedCacheDictionary.cs b/src/Umbraco.Core/Cache/AppPolicedCacheDictionary.cs index 8239ee4abf..53e45bbb2e 100644 --- a/src/Umbraco.Core/Cache/AppPolicedCacheDictionary.cs +++ b/src/Umbraco.Core/Cache/AppPolicedCacheDictionary.cs @@ -37,8 +37,8 @@ namespace Umbraco.Cms.Core.Cache /// /// Tries to get a cache. /// - protected Attempt Get(TKey key) - => _caches.TryGetValue(key, out var cache) ? Attempt.Succeed(cache) : Attempt.Fail(); + protected Attempt Get(TKey key) + => _caches.TryGetValue(key, out var cache) ? Attempt.Succeed(cache) : Attempt.Fail(); /// /// Removes a cache. diff --git a/src/Umbraco.Core/Cache/DataTypeCacheRefresher.cs b/src/Umbraco.Core/Cache/DataTypeCacheRefresher.cs index ef2a3738e5..c512be301f 100644 --- a/src/Umbraco.Core/Cache/DataTypeCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/DataTypeCacheRefresher.cs @@ -64,9 +64,9 @@ namespace Umbraco.Cms.Core.Cache { _idKeyMap.ClearCache(payload.Id); - if (dataTypeCache.Success) + if (dataTypeCache.Success.HasValue && dataTypeCache.Success.Value) { - dataTypeCache.Result.Clear(RepositoryCacheKeys.GetKey(payload.Id)); + dataTypeCache.Result?.Clear(RepositoryCacheKeys.GetKey(payload.Id)); } } diff --git a/src/Umbraco.Core/Cache/IsolatedCaches.cs b/src/Umbraco.Core/Cache/IsolatedCaches.cs index 6d197489ca..7c273c9136 100644 --- a/src/Umbraco.Core/Cache/IsolatedCaches.cs +++ b/src/Umbraco.Core/Cache/IsolatedCaches.cs @@ -29,7 +29,7 @@ namespace Umbraco.Cms.Core.Cache /// /// Tries to get a cache. /// - public Attempt Get() + public Attempt Get() => Get(typeof(T)); /// diff --git a/src/Umbraco.Core/Cache/MacroCacheRefresher.cs b/src/Umbraco.Core/Cache/MacroCacheRefresher.cs index 77550b81d1..65a911c864 100644 --- a/src/Umbraco.Core/Cache/MacroCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/MacroCacheRefresher.cs @@ -52,9 +52,9 @@ namespace Umbraco.Cms.Core.Cache AppCaches.RuntimeCache.ClearByKey(alias); var macroRepoCache = AppCaches.IsolatedCaches.Get(); - if (macroRepoCache) + if (macroRepoCache.Success.HasValue && macroRepoCache.Success.Value) { - macroRepoCache.Result.Clear(RepositoryCacheKeys.GetKey(payload.Id)); + macroRepoCache.Result?.Clear(RepositoryCacheKeys.GetKey(payload.Id)); } } diff --git a/src/Umbraco.Core/Cache/MediaCacheRefresher.cs b/src/Umbraco.Core/Cache/MediaCacheRefresher.cs index c192296375..d4c4558dd4 100644 --- a/src/Umbraco.Core/Cache/MediaCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/MediaCacheRefresher.cs @@ -53,19 +53,19 @@ namespace Umbraco.Cms.Core.Cache if (payload.ChangeTypes == TreeChangeTypes.Remove) _idKeyMap.ClearCache(payload.Id); - if (!mediaCache) continue; + if (!mediaCache.Success.HasValue || !mediaCache.Success.Value) continue; // repository cache // it *was* done for each pathId but really that does not make sense // only need to do it for the current media - mediaCache.Result.Clear(RepositoryCacheKeys.GetKey(payload.Id)); - mediaCache.Result.Clear(RepositoryCacheKeys.GetKey(payload.Key)); + mediaCache.Result?.Clear(RepositoryCacheKeys.GetKey(payload.Id)); + mediaCache.Result?.Clear(RepositoryCacheKeys.GetKey(payload.Key)); // remove those that are in the branch if (payload.ChangeTypes.HasTypesAny(TreeChangeTypes.RefreshBranch | TreeChangeTypes.Remove)) { var pathid = "," + payload.Id + ","; - mediaCache.Result.ClearOfType((_, v) => v.Path.Contains(pathid)); + mediaCache.Result?.ClearOfType((_, v) => v.Path.Contains(pathid)); } } } diff --git a/src/Umbraco.Core/Cache/MemberCacheRefresher.cs b/src/Umbraco.Core/Cache/MemberCacheRefresher.cs index af073706ed..cdee79101a 100644 --- a/src/Umbraco.Core/Cache/MemberCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/MemberCacheRefresher.cs @@ -74,10 +74,10 @@ namespace Umbraco.Cms.Core.Cache foreach (var p in payloads) { _idKeyMap.ClearCache(p.Id); - if (memberCache) + if (memberCache.Success.HasValue && memberCache.Success.Value) { - memberCache.Result.Clear(RepositoryCacheKeys.GetKey(p.Id)); - memberCache.Result.Clear(RepositoryCacheKeys.GetKey(p.Username)); + memberCache.Result?.Clear(RepositoryCacheKeys.GetKey(p.Id)); + memberCache.Result?.Clear(RepositoryCacheKeys.GetKey(p.Username)); } } diff --git a/src/Umbraco.Core/Cache/RelationTypeCacheRefresher.cs b/src/Umbraco.Core/Cache/RelationTypeCacheRefresher.cs index aadae52ce6..e6ab6fa845 100644 --- a/src/Umbraco.Core/Cache/RelationTypeCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/RelationTypeCacheRefresher.cs @@ -33,7 +33,7 @@ namespace Umbraco.Cms.Core.Cache public override void Refresh(int id) { var cache = AppCaches.IsolatedCaches.Get(); - if (cache) cache.Result.Clear(RepositoryCacheKeys.GetKey(id)); + if (cache.Success.HasValue && cache.Success.Value) cache.Result?.Clear(RepositoryCacheKeys.GetKey(id)); base.Refresh(id); } @@ -46,7 +46,7 @@ namespace Umbraco.Cms.Core.Cache public override void Remove(int id) { var cache = AppCaches.IsolatedCaches.Get(); - if (cache) cache.Result.Clear(RepositoryCacheKeys.GetKey(id)); + if (cache.Success.HasValue && cache.Success.Value) cache.Result?.Clear(RepositoryCacheKeys.GetKey(id)); base.Remove(id); } diff --git a/src/Umbraco.Core/Cache/UserCacheRefresher.cs b/src/Umbraco.Core/Cache/UserCacheRefresher.cs index b8d271bbb3..2167910a6b 100644 --- a/src/Umbraco.Core/Cache/UserCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/UserCacheRefresher.cs @@ -39,13 +39,13 @@ namespace Umbraco.Cms.Core.Cache public override void Remove(int id) { var userCache = AppCaches.IsolatedCaches.Get(); - if (userCache) + if (userCache.Success.HasValue && userCache.Success.Value) { - userCache.Result.Clear(RepositoryCacheKeys.GetKey(id)); - userCache.Result.ClearByKey(CacheKeys.UserContentStartNodePathsPrefix + id); - userCache.Result.ClearByKey(CacheKeys.UserMediaStartNodePathsPrefix + id); - userCache.Result.ClearByKey(CacheKeys.UserAllContentStartNodesPrefix + id); - userCache.Result.ClearByKey(CacheKeys.UserAllMediaStartNodesPrefix + id); + userCache.Result?.Clear(RepositoryCacheKeys.GetKey(id)); + userCache.Result?.ClearByKey(CacheKeys.UserContentStartNodePathsPrefix + id); + userCache.Result?.ClearByKey(CacheKeys.UserMediaStartNodePathsPrefix + id); + userCache.Result?.ClearByKey(CacheKeys.UserAllContentStartNodesPrefix + id); + userCache.Result?.ClearByKey(CacheKeys.UserAllMediaStartNodesPrefix + id); } diff --git a/src/Umbraco.Core/Cache/UserGroupCacheRefresher.cs b/src/Umbraco.Core/Cache/UserGroupCacheRefresher.cs index 3ec88b1ea5..9ecd569e14 100644 --- a/src/Umbraco.Core/Cache/UserGroupCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/UserGroupCacheRefresher.cs @@ -34,9 +34,9 @@ namespace Umbraco.Cms.Core.Cache { ClearAllIsolatedCacheByEntityType(); var userGroupCache = AppCaches.IsolatedCaches.Get(); - if (userGroupCache) + if (userGroupCache.Success.HasValue && userGroupCache.Success.Value) { - userGroupCache.Result.ClearByKey(CacheKeys.UserGroupGetByAliasCacheKeyPrefix); + userGroupCache.Result?.ClearByKey(CacheKeys.UserGroupGetByAliasCacheKeyPrefix); } //We'll need to clear all user cache too @@ -54,10 +54,10 @@ namespace Umbraco.Cms.Core.Cache public override void Remove(int id) { var userGroupCache = AppCaches.IsolatedCaches.Get(); - if (userGroupCache) + if (userGroupCache.Success.HasValue && userGroupCache.Success.Value) { - userGroupCache.Result.Clear(RepositoryCacheKeys.GetKey(id)); - userGroupCache.Result.ClearByKey(CacheKeys.UserGroupGetByAliasCacheKeyPrefix); + userGroupCache.Result?.Clear(RepositoryCacheKeys.GetKey(id)); + userGroupCache.Result?.ClearByKey(CacheKeys.UserGroupGetByAliasCacheKeyPrefix); } //we don't know what user's belong to this group without doing a look up so we'll need to just clear them all diff --git a/src/Umbraco.Core/Collections/StackQueue.cs b/src/Umbraco.Core/Collections/StackQueue.cs index 22cfa3978c..98516a38b8 100644 --- a/src/Umbraco.Core/Collections/StackQueue.cs +++ b/src/Umbraco.Core/Collections/StackQueue.cs @@ -40,8 +40,8 @@ namespace Umbraco.Core.Collections return obj!; } - public T? PeekStack() => _linkedList.First.Value; + public T? PeekStack() => _linkedList.First is not null ? _linkedList.First.Value : default; - public T? PeekQueue() => _linkedList.Last.Value; + public T? PeekQueue() => _linkedList.Last is not null ? _linkedList.Last.Value : default; } } diff --git a/src/Umbraco.Core/Collections/TopoGraph.cs b/src/Umbraco.Core/Collections/TopoGraph.cs index b568d1bc49..11fd155684 100644 --- a/src/Umbraco.Core/Collections/TopoGraph.cs +++ b/src/Umbraco.Core/Collections/TopoGraph.cs @@ -32,6 +32,7 @@ namespace Umbraco.Cms.Core.Collections /// The type of the keys. /// The type of the items. public class TopoGraph : TopoGraph + where TKey : notnull { private readonly Func _getKey; private readonly Func?> _getDependencies; @@ -122,7 +123,7 @@ namespace Umbraco.Cms.Core.Collections { foreach (var key in keys) { - TItem value; + TItem? value; if (_items.TryGetValue(key, out value)) yield return value; else if (throwOnMissing) diff --git a/src/Umbraco.Core/Composing/ComposerGraph.cs b/src/Umbraco.Core/Composing/ComposerGraph.cs index 9e61414029..510d59b374 100644 --- a/src/Umbraco.Core/Composing/ComposerGraph.cs +++ b/src/Umbraco.Core/Composing/ComposerGraph.cs @@ -337,7 +337,7 @@ namespace Umbraco.Cms.Core.Composing { foreach (Type type in types) { - ConstructorInfo ctor = type.GetConstructor(Array.Empty()); + ConstructorInfo? ctor = type.GetConstructor(Array.Empty()); if (ctor == null) { diff --git a/src/Umbraco.Core/Composing/ITypeFinder.cs b/src/Umbraco.Core/Composing/ITypeFinder.cs index 55e9da31fd..7d59b68869 100644 --- a/src/Umbraco.Core/Composing/ITypeFinder.cs +++ b/src/Umbraco.Core/Composing/ITypeFinder.cs @@ -9,7 +9,7 @@ namespace Umbraco.Cms.Core.Composing /// public interface ITypeFinder { - Type GetTypeByName(string name); + Type? GetTypeByName(string name); /// /// Return a list of found local Assemblies that Umbraco should scan for type finding diff --git a/src/Umbraco.Core/Composing/ReferenceResolver.cs b/src/Umbraco.Core/Composing/ReferenceResolver.cs index ed2a0c0059..5b7c5ffde9 100644 --- a/src/Umbraco.Core/Composing/ReferenceResolver.cs +++ b/src/Umbraco.Core/Composing/ReferenceResolver.cs @@ -55,7 +55,7 @@ namespace Umbraco.Cms.Core.Composing // for Umbraco dependencies/transitive dependencies foreach(var dir in assemblyLocations) { - foreach(var dll in Directory.EnumerateFiles(dir, "*.dll")) + foreach(var dll in Directory.EnumerateFiles(dir ?? string.Empty, "*.dll")) { AssemblyName? assemblyName = null; try @@ -83,7 +83,7 @@ namespace Umbraco.Cms.Core.Composing continue; // don't include this item if it's Umbraco Core - if (Constants.Composing.UmbracoCoreAssemblyNames.Any(x=>assemblyName.FullName.StartsWith(x) || assemblyName.Name.EndsWith(".Views"))) + if (Constants.Composing.UmbracoCoreAssemblyNames.Any(x=>assemblyName.FullName.StartsWith(x) || (assemblyName.Name?.EndsWith(".Views") ?? false))) continue; var assembly = Assembly.Load(assemblyName); @@ -105,7 +105,7 @@ namespace Umbraco.Cms.Core.Composing } - private IEnumerable GetAssemblyFolders(IEnumerable assemblies) + private IEnumerable GetAssemblyFolders(IEnumerable assemblies) { return assemblies.Select(x => Path.GetDirectoryName(GetAssemblyLocation(x))).Distinct(); } @@ -133,12 +133,12 @@ namespace Umbraco.Cms.Core.Composing classification = Classification.Unknown; _classifications[assembly] = classification; - if (TypeFinder.KnownAssemblyExclusionFilter.Any(f => assembly.FullName.StartsWith(f, StringComparison.InvariantCultureIgnoreCase))) + if (TypeFinder.KnownAssemblyExclusionFilter.Any(f => assembly.FullName?.StartsWith(f, StringComparison.InvariantCultureIgnoreCase) ?? false)) { // if its part of the filter it doesn't reference umbraco classification = Classification.DoesNotReferenceUmbraco; } - else if (_umbracoAssemblies.Contains(assembly.GetName().Name)) + else if (_umbracoAssemblies.Contains(assembly.GetName().Name!)) { classification = Classification.IsUmbraco; } diff --git a/src/Umbraco.Core/Composing/TypeFinder.cs b/src/Umbraco.Core/Composing/TypeFinder.cs index 6f21845399..e66b30cf07 100644 --- a/src/Umbraco.Core/Composing/TypeFinder.cs +++ b/src/Umbraco.Core/Composing/TypeFinder.cs @@ -20,7 +20,7 @@ namespace Umbraco.Cms.Core.Composing private volatile HashSet? _localFilteredAssemblyCache; private readonly object _localFilteredAssemblyCacheLocker = new object(); private readonly List _notifiedLoadExceptionAssemblies = new List(); - private static readonly ConcurrentDictionary s_typeNamesCache = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary s_typeNamesCache = new ConcurrentDictionary(); private readonly ITypeFinderConfig? _typeFinderConfig; // used for benchmark tests @@ -62,13 +62,13 @@ namespace Umbraco.Cms.Core.Composing var name = a.GetName().Name; // simple name of the assembly return AssembliesAcceptingLoadExceptions.Any(pattern => { - if (pattern.Length > name.Length) + if (pattern.Length > name?.Length) return false; // pattern longer than name - if (pattern.Length == name.Length) + if (pattern.Length == name?.Length) return pattern.InvariantEquals(name); // same length, must be identical if (pattern[pattern.Length] != '.') return false; // pattern is shorter than name, must end with dot - return name.StartsWith(pattern); // and name must start with pattern + return name?.StartsWith(pattern) ?? false; // and name must start with pattern }); } @@ -110,7 +110,7 @@ namespace Umbraco.Cms.Core.Composing return GetAllAssemblies() .Where(x => excludeFromResults.Contains(x) == false && x.GlobalAssemblyCache == false - && exclusionFilter.Any(f => x.FullName.StartsWith(f)) == false); + && exclusionFilter.Any(f => x.FullName?.StartsWith(f) ?? false) == false); } // TODO: Kill this @@ -241,7 +241,7 @@ namespace Umbraco.Cms.Core.Composing /// /// /// - public virtual Type GetTypeByName(string name) + public virtual Type? GetTypeByName(string name) { //NOTE: This will not find types in dynamic assemblies unless those assemblies are already loaded @@ -332,7 +332,7 @@ namespace Umbraco.Cms.Core.Composing && x.GetCustomAttributes(attributeType, false).Any())); // marked with the attribute } - if (assembly != attributeType.Assembly && assemblyTypes.Where(attributeType.IsAssignableFrom).Any() == false) + if (assembly != attributeType.Assembly && assemblyTypes?.Where(attributeType.IsAssignableFrom).Any() == false) continue; if (QueryWithReferencingAssemblies) @@ -407,7 +407,7 @@ namespace Umbraco.Cms.Core.Composing && (additionalFilter == null || additionalFilter(x)))); // filter } - if (assembly != baseType.Assembly && assemblyTypes.All(x => x.IsSealed)) + if (assembly != baseType.Assembly && (assemblyTypes?.All(x => x.IsSealed) ?? false)) continue; if (QueryWithReferencingAssemblies) @@ -462,7 +462,7 @@ namespace Umbraco.Cms.Core.Composing // log a warning, and return what we can lock (_notifiedLoadExceptionAssemblies) { - if (_notifiedLoadExceptionAssemblies.Contains(a.FullName) == false) + if (a.FullName is not null && _notifiedLoadExceptionAssemblies.Contains(a.FullName) == false) { _notifiedLoadExceptionAssemblies.Add(a.FullName); _logger.LogWarning(ex, "Could not load all types from {TypeName}.", a.GetName().Name); diff --git a/src/Umbraco.Core/Composing/TypeHelper.cs b/src/Umbraco.Core/Composing/TypeHelper.cs index d683e313be..95ac68cf04 100644 --- a/src/Umbraco.Core/Composing/TypeHelper.cs +++ b/src/Umbraco.Core/Composing/TypeHelper.cs @@ -29,7 +29,7 @@ namespace Umbraco.Cms.Core.Composing /// Based on a type we'll check if it is IEnumerable{T} (or similar) and if so we'll return a List{T}, this will also deal with array types and return List{T} for those too. /// If it cannot be done, null is returned. /// - public static IList CreateGenericEnumerableFromObject(object obj) + public static IList? CreateGenericEnumerableFromObject(object obj) { var type = obj.GetType(); @@ -48,16 +48,20 @@ namespace Umbraco.Cms.Core.Composing //if it is a IEnumerable<>, IList or ICollection<> we'll use a List<> var genericType = typeof(List<>).MakeGenericType(type.GetGenericArguments()); //pass in obj to fill the list - return (IList)Activator.CreateInstance(genericType, obj); + return (IList?)Activator.CreateInstance(genericType, obj); } } if (type.IsArray) { //if its an array, we'll use a List<> - var genericType = typeof(List<>).MakeGenericType(type.GetElementType()); - //pass in obj to fill the list - return (IList)Activator.CreateInstance(genericType, obj); + var typeArguments = type.GetElementType(); + if (typeArguments is not null) + { + Type genericType = typeof(List<>).MakeGenericType(typeArguments); + //pass in obj to fill the list + return (IList?)Activator.CreateInstance(genericType, obj); + } } return null; @@ -93,7 +97,7 @@ namespace Umbraco.Cms.Core.Composing // should only be scanning those assemblies because any other assembly will definitely not // contain sub type's of the one we're currently looking for var name = assembly.GetName().Name; - return assemblies.Where(x => x == assembly || HasReference(x, name)).ToList(); + return assemblies.Where(x => x == assembly || name is not null ? HasReference(x, name!) : false).ToList(); } /// @@ -145,10 +149,10 @@ namespace Umbraco.Cms.Core.Composing /// The term 'lowest' refers to the most base class of the type collection. /// If a base type is not found amongst the type collection then an invalid attempt is returned. /// - public static Attempt GetLowestBaseType(params Type[] types) + public static Attempt GetLowestBaseType(params Type[] types) { if (types.Length == 0) - return Attempt.Fail(); + return Attempt.Fail(); if (types.Length == 1) return Attempt.Succeed(types[0]); @@ -167,7 +171,7 @@ namespace Umbraco.Cms.Core.Composing } } - return Attempt.Fail(); + return Attempt.Fail(); } /// @@ -235,7 +239,7 @@ namespace Umbraco.Cms.Core.Composing /// /// /// - public static PropertyInfo GetProperty(Type type, string name, + public static PropertyInfo? GetProperty(Type type, string name, bool mustRead = true, bool mustWrite = true, bool includeIndexed = false, diff --git a/src/Umbraco.Core/Composing/TypeLoader.cs b/src/Umbraco.Core/Composing/TypeLoader.cs index 3d47054520..2b55f78860 100644 --- a/src/Umbraco.Core/Composing/TypeLoader.cs +++ b/src/Umbraco.Core/Composing/TypeLoader.cs @@ -244,17 +244,17 @@ namespace Umbraco.Cms.Core.Composing private const int FileDeleteTimeout = 4000; // milliseconds // internal for tests - public Attempt> TryGetCached(Type? baseType, Type? attributeType) + public Attempt?> TryGetCached(Type? baseType, Type? attributeType) { var cache = _runtimeCache.GetCacheItem(CacheKey, ReadCacheSafe, TimeSpan.FromSeconds(ListFileCacheDuration))!; cache.TryGetValue( - (baseType == null ? string.Empty : baseType.FullName, attributeType == null ? string.Empty : attributeType.FullName), - out IEnumerable types); + (baseType == null ? string.Empty : baseType.FullName ?? string.Empty, attributeType == null ? string.Empty : attributeType.FullName ?? string.Empty), + out IEnumerable? types); return types == null - ? Attempt>.Fail() + ? Attempt?>.Fail() : Attempt.Succeed(types); } @@ -406,7 +406,7 @@ namespace Umbraco.Cms.Core.Composing // internal for tests internal void UpdateCache() { - void TimerRelease(object o) + void TimerRelease(object? o) { lock (_timerLock) { @@ -780,7 +780,7 @@ namespace Umbraco.Cms.Core.Composing else { // successfully retrieved types from the file cache: load - foreach (var type in cacheResult.Result) + foreach (var type in cacheResult.Result!) { var resolvedType = TypeFinder.GetTypeByName(type); if (resolvedType != null) diff --git a/src/Umbraco.Core/Configuration/ConfigConnectionString.cs b/src/Umbraco.Core/Configuration/ConfigConnectionString.cs index 899a95a2da..85c9332b30 100644 --- a/src/Umbraco.Core/Configuration/ConfigConnectionString.cs +++ b/src/Umbraco.Core/Configuration/ConfigConnectionString.cs @@ -81,7 +81,7 @@ namespace Umbraco.Cms.Core.Configuration private static string ParseProviderName(DbConnectionStringBuilder builder) { if ((builder.TryGetValue("Data Source", out var dataSource) || builder.TryGetValue("DataSource", out dataSource)) && - dataSource?.ToString().EndsWith(".sdf", StringComparison.OrdinalIgnoreCase) == true) + dataSource?.ToString()?.EndsWith(".sdf", StringComparison.OrdinalIgnoreCase) == true) { return Constants.DbProviderNames.SqlCe; } diff --git a/src/Umbraco.Core/Configuration/Grid/GridEditorsConfig.cs b/src/Umbraco.Core/Configuration/Grid/GridEditorsConfig.cs index abaee9b0f7..3abc688c01 100644 --- a/src/Umbraco.Core/Configuration/Grid/GridEditorsConfig.cs +++ b/src/Umbraco.Core/Configuration/Grid/GridEditorsConfig.cs @@ -58,9 +58,12 @@ namespace Umbraco.Cms.Core.Configuration.Grid var resourceStream = assembly.GetManifestResourceStream( "Umbraco.Cms.Core.EmbeddedResources.Grid.grid.editors.config.js"); - using var reader = new StreamReader(resourceStream, Encoding.UTF8); - var sourceString = reader.ReadToEnd(); - editors.AddRange(_jsonSerializer.Deserialize>(sourceString)); + if (resourceStream is not null) + { + using var reader = new StreamReader(resourceStream, Encoding.UTF8); + var sourceString = reader.ReadToEnd(); + editors.AddRange(_jsonSerializer.Deserialize>(sourceString)); + } } // add manifest editors, skip duplicates diff --git a/src/Umbraco.Core/Configuration/IUmbracoVersion.cs b/src/Umbraco.Core/Configuration/IUmbracoVersion.cs index a7aae5e0cf..e59fc2117d 100644 --- a/src/Umbraco.Core/Configuration/IUmbracoVersion.cs +++ b/src/Umbraco.Core/Configuration/IUmbracoVersion.cs @@ -8,12 +8,12 @@ namespace Umbraco.Cms.Core.Configuration /// /// Gets the non-semantic version of the Umbraco code. /// - Version Version { get; } + Version? Version { get; } /// /// Gets the semantic version comments of the Umbraco code. /// - string Comment { get; } + string? Comment { get; } /// /// Gets the assembly version of the Umbraco code. @@ -23,7 +23,7 @@ namespace Umbraco.Cms.Core.Configuration /// Is the one that the CLR checks for compatibility. Therefore, it changes only on /// hard-breaking changes (for instance, on new major versions). /// - Version AssemblyVersion { get; } + Version? AssemblyVersion { get; } /// /// Gets the assembly file version of the Umbraco code. @@ -31,7 +31,7 @@ namespace Umbraco.Cms.Core.Configuration /// /// The assembly version is the value of the . /// - Version AssemblyFileVersion { get; } + Version? AssemblyFileVersion { get; } /// /// Gets the semantic version of the Umbraco code. @@ -40,7 +40,7 @@ namespace Umbraco.Cms.Core.Configuration /// The semantic version is the value of the . /// It is the full version of Umbraco, including comments. /// - SemVersion SemanticVersion { get; } + SemVersion? SemanticVersion { get; } } } diff --git a/src/Umbraco.Core/Configuration/UmbracoVersion.cs b/src/Umbraco.Core/Configuration/UmbracoVersion.cs index 2c0ba395ef..010fc3fb58 100644 --- a/src/Umbraco.Core/Configuration/UmbracoVersion.cs +++ b/src/Umbraco.Core/Configuration/UmbracoVersion.cs @@ -18,11 +18,11 @@ namespace Umbraco.Cms.Core.Configuration AssemblyVersion = umbracoCoreAssembly.GetName().Version; // gets the value indicated by the AssemblyFileVersion attribute - AssemblyFileVersion = System.Version.Parse(umbracoCoreAssembly.GetCustomAttribute().Version); + AssemblyFileVersion = System.Version.Parse(umbracoCoreAssembly.GetCustomAttribute()?.Version ?? string.Empty); // gets the value indicated by the AssemblyInformationalVersion attribute // this is the true semantic version of the Umbraco Cms - SemanticVersion = SemVersion.Parse(umbracoCoreAssembly.GetCustomAttribute().InformationalVersion); + SemanticVersion = SemVersion.Parse(umbracoCoreAssembly.GetCustomAttribute()?.InformationalVersion ?? string.Empty); // gets the non-semantic version Version = SemanticVersion.GetVersion(3); @@ -31,12 +31,12 @@ namespace Umbraco.Cms.Core.Configuration /// /// Gets the non-semantic version of the Umbraco code. /// - public Version Version { get; } + public Version? Version { get; } /// /// Gets the semantic version comments of the Umbraco code. /// - public string Comment => SemanticVersion.Prerelease; + public string? Comment => SemanticVersion?.Prerelease; /// /// Gets the assembly version of the Umbraco code. @@ -46,7 +46,7 @@ namespace Umbraco.Cms.Core.Configuration /// Is the one that the CLR checks for compatibility. Therefore, it changes only on /// hard-breaking changes (for instance, on new major versions). /// - public Version AssemblyVersion { get; } + public Version? AssemblyVersion { get; } /// /// Gets the assembly file version of the Umbraco code. @@ -54,7 +54,7 @@ namespace Umbraco.Cms.Core.Configuration /// /// The assembly version is the value of the . /// - public Version AssemblyFileVersion { get; } + public Version? AssemblyFileVersion { get; } /// /// Gets the semantic version of the Umbraco code. @@ -63,6 +63,6 @@ namespace Umbraco.Cms.Core.Configuration /// The semantic version is the value of the . /// It is the full version of Umbraco, including comments. /// - public SemVersion SemanticVersion { get; } + public SemVersion? SemanticVersion { get; } } } diff --git a/src/Umbraco.Core/ContentApps/ContentAppFactoryCollection.cs b/src/Umbraco.Core/ContentApps/ContentAppFactoryCollection.cs index eaaad72eb6..e4a5eedf18 100644 --- a/src/Umbraco.Core/ContentApps/ContentAppFactoryCollection.cs +++ b/src/Umbraco.Core/ContentApps/ContentAppFactoryCollection.cs @@ -42,10 +42,14 @@ namespace Umbraco.Cms.Core.ContentApps foreach (var app in apps) { - if (aliases.Contains(app!.Alias)) - (dups ?? (dups = new List())).Add(app.Alias); - else - aliases.Add(app.Alias); + if (app.Alias is not null) + { + + if (aliases.Contains(app.Alias)) + (dups ?? (dups = new List())).Add(app.Alias); + else + aliases.Add(app.Alias); + } } if (dups != null) diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs index d5a1d7bf4b..df499a8925 100644 --- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs @@ -104,7 +104,7 @@ namespace Umbraco.Cms.Core.DependencyInjection { Type typeOfBuilder = typeof(TBuilder); - if (_builders.TryGetValue(typeOfBuilder, out ICollectionBuilder o)) + if (_builders.TryGetValue(typeOfBuilder, out ICollectionBuilder? o)) { return (TBuilder)o; } @@ -130,7 +130,7 @@ namespace Umbraco.Cms.Core.DependencyInjection Services.AddSingleton(Profiler); // Register as singleton to allow injection everywhere. - Services.AddSingleton(p => p.GetService); + Services.AddSingleton(p => p.GetService!); Services.AddSingleton(); Services.AddLazySupport(); diff --git a/src/Umbraco.Core/DependencyInjection/UniqueServiceDescriptor.cs b/src/Umbraco.Core/DependencyInjection/UniqueServiceDescriptor.cs index 239604eb52..538f3f1dda 100644 --- a/src/Umbraco.Core/DependencyInjection/UniqueServiceDescriptor.cs +++ b/src/Umbraco.Core/DependencyInjection/UniqueServiceDescriptor.cs @@ -25,7 +25,7 @@ namespace Umbraco.Cms.Core.DependencyInjection } /// - public override bool Equals(object obj) => Equals(obj as UniqueServiceDescriptor); + public override bool Equals(object? obj) => Equals(obj as UniqueServiceDescriptor); /// public bool Equals(UniqueServiceDescriptor? other) => other != null && Lifetime == other.Lifetime && EqualityComparer.Default.Equals(ServiceType, other.ServiceType) && EqualityComparer.Default.Equals(ImplementationType, other.ImplementationType) && EqualityComparer.Default.Equals(ImplementationInstance, other.ImplementationInstance) && EqualityComparer?>.Default.Equals(ImplementationFactory, other.ImplementationFactory); @@ -36,9 +36,22 @@ namespace Umbraco.Cms.Core.DependencyInjection int hashCode = 493849952; hashCode = (hashCode * -1521134295) + Lifetime.GetHashCode(); hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(ServiceType); - hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(ImplementationType); - hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(ImplementationInstance); - hashCode = (hashCode * -1521134295) + EqualityComparer?>.Default.GetHashCode(ImplementationFactory); + + if (ImplementationType is not null) + { + hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(ImplementationType); + } + + if (ImplementationInstance is not null) + { + hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(ImplementationInstance); + } + + if (ImplementationFactory is not null) + { + hashCode = (hashCode * -1521134295) + EqualityComparer?>.Default.GetHashCode(ImplementationFactory); + } + return hashCode; } } diff --git a/src/Umbraco.Core/Deploy/ArtifactBase.cs b/src/Umbraco.Core/Deploy/ArtifactBase.cs index b0cd0f6753..ff5287d0b8 100644 --- a/src/Umbraco.Core/Deploy/ArtifactBase.cs +++ b/src/Umbraco.Core/Deploy/ArtifactBase.cs @@ -46,7 +46,7 @@ namespace Umbraco.Cms.Core.Deploy public IEnumerable? Dependencies { get => _dependencies; - set => _dependencies = value.OrderBy(x => x.Udi); + set => _dependencies = value?.OrderBy(x => x.Udi); } #endregion diff --git a/src/Umbraco.Core/Dictionary/UmbracoCultureDictionary.cs b/src/Umbraco.Core/Dictionary/UmbracoCultureDictionary.cs index d06989b6f8..d4d81c76c7 100644 --- a/src/Umbraco.Core/Dictionary/UmbracoCultureDictionary.cs +++ b/src/Umbraco.Core/Dictionary/UmbracoCultureDictionary.cs @@ -21,7 +21,7 @@ namespace Umbraco.Cms.Core.Dictionary { private readonly ILocalizationService _localizationService; private readonly IAppCache _requestCache; - private readonly CultureInfo _specificCulture; + private readonly CultureInfo? _specificCulture; /// /// Default constructor which will use the current thread's culture @@ -115,13 +115,13 @@ namespace Umbraco.Cms.Core.Dictionary return result; } - private ILanguage Language + private ILanguage? Language { get { //ensure it's stored/retrieved from request cache //NOTE: This is no longer necessary since these are cached at the runtime level, but we can leave it here for now. - return _requestCache.GetCacheItem(typeof (DefaultCultureDictionary).Name + "Culture" + Culture.Name, + return _requestCache.GetCacheItem(typeof (DefaultCultureDictionary).Name + "Culture" + Culture.Name, () => { // find a language that matches the current culture or any of its parent cultures var culture = Culture; diff --git a/src/Umbraco.Core/Editors/UserEditorAuthorizationHelper.cs b/src/Umbraco.Core/Editors/UserEditorAuthorizationHelper.cs index c5d8d01449..1ecb90b119 100644 --- a/src/Umbraco.Core/Editors/UserEditorAuthorizationHelper.cs +++ b/src/Umbraco.Core/Editors/UserEditorAuthorizationHelper.cs @@ -36,7 +36,7 @@ namespace Umbraco.Cms.Core.Editors /// The start media ids of the user being saved (can be null or empty) /// The user aliases of the user being saved (can be null or empty) /// - public Attempt IsAuthorized(IUser currentUser, + public Attempt IsAuthorized(IUser currentUser, IUser savingUser, IEnumerable startContentIds, IEnumerable startMediaIds, IEnumerable userGroupAliases) @@ -74,7 +74,7 @@ namespace Umbraco.Cms.Core.Editors // c) an admin can manage any group or section access if (currentIsAdmin) - return Attempt.Succeed(); + return Attempt.Succeed(); if (userGroupAliases != null) { @@ -117,10 +117,10 @@ namespace Umbraco.Cms.Core.Editors } } - return Attempt.Succeed(); + return Attempt.Succeed(); } - private Attempt AuthorizePath(IUser currentUser, IEnumerable? startContentIds, IEnumerable? startMediaIds) + private Attempt AuthorizePath(IUser currentUser, IEnumerable? startContentIds, IEnumerable? startMediaIds) { if (startContentIds != null) { @@ -164,7 +164,7 @@ namespace Umbraco.Cms.Core.Editors } } - return Attempt.Succeed(); + return Attempt.Succeed(); } } } diff --git a/src/Umbraco.Core/Events/CancellableEnumerableObjectEventArgs.cs b/src/Umbraco.Core/Events/CancellableEnumerableObjectEventArgs.cs index e70338b3bc..c9958a5fc9 100644 --- a/src/Umbraco.Core/Events/CancellableEnumerableObjectEventArgs.cs +++ b/src/Umbraco.Core/Events/CancellableEnumerableObjectEventArgs.cs @@ -30,15 +30,15 @@ namespace Umbraco.Cms.Core.Events : base(eventObject) { } - public bool Equals(CancellableEnumerableObjectEventArgs other) + public bool Equals(CancellableEnumerableObjectEventArgs? other) { - if (other is null) return false; + if (other is null || other.EventObject is null) return false; if (ReferenceEquals(this, other)) return true; - return EventObject.SequenceEqual(other.EventObject); + return EventObject?.SequenceEqual(other.EventObject) ?? false; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is null) return false; if (ReferenceEquals(this, obj)) return true; @@ -48,7 +48,12 @@ namespace Umbraco.Cms.Core.Events public override int GetHashCode() { - return HashCodeHelper.GetHashCode(EventObject); + if (EventObject is not null) + { + return HashCodeHelper.GetHashCode(EventObject); + } + + return base.GetHashCode(); } } } diff --git a/src/Umbraco.Core/Events/CancellableEventArgs.cs b/src/Umbraco.Core/Events/CancellableEventArgs.cs index a6be7fa3e8..2fb27c291f 100644 --- a/src/Umbraco.Core/Events/CancellableEventArgs.cs +++ b/src/Umbraco.Core/Events/CancellableEventArgs.cs @@ -10,7 +10,7 @@ namespace Umbraco.Cms.Core.Events public class CancellableEventArgs : EventArgs, IEquatable { private bool _cancel; - private IDictionary _eventState; + private IDictionary? _eventState; private static readonly ReadOnlyDictionary EmptyAdditionalData = new ReadOnlyDictionary(new Dictionary()); @@ -108,14 +108,14 @@ namespace Umbraco.Cms.Core.Events set => _eventState = value; } - public bool Equals(CancellableEventArgs other) + public bool Equals(CancellableEventArgs? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return Equals(AdditionalData, other.AdditionalData); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; diff --git a/src/Umbraco.Core/Events/CancellableObjectEventArgs.cs b/src/Umbraco.Core/Events/CancellableObjectEventArgs.cs index 9c96732888..2697b773c2 100644 --- a/src/Umbraco.Core/Events/CancellableObjectEventArgs.cs +++ b/src/Umbraco.Core/Events/CancellableObjectEventArgs.cs @@ -7,30 +7,30 @@ namespace Umbraco.Cms.Core.Events /// public abstract class CancellableObjectEventArgs : CancellableEventArgs { - protected CancellableObjectEventArgs(object eventObject, bool canCancel, EventMessages messages, IDictionary additionalData) + protected CancellableObjectEventArgs(object? eventObject, bool canCancel, EventMessages messages, IDictionary additionalData) : base(canCancel, messages, additionalData) { EventObject = eventObject; } - protected CancellableObjectEventArgs(object eventObject, bool canCancel, EventMessages eventMessages) + protected CancellableObjectEventArgs(object? eventObject, bool canCancel, EventMessages eventMessages) : base(canCancel, eventMessages) { EventObject = eventObject; } - protected CancellableObjectEventArgs(object eventObject, EventMessages eventMessages) + protected CancellableObjectEventArgs(object? eventObject, EventMessages eventMessages) : this(eventObject, true, eventMessages) { } - protected CancellableObjectEventArgs(object eventObject, bool canCancel) + protected CancellableObjectEventArgs(object? eventObject, bool canCancel) : base(canCancel) { EventObject = eventObject; } - protected CancellableObjectEventArgs(object eventObject) + protected CancellableObjectEventArgs(object? eventObject) : this(eventObject, true) { } @@ -41,6 +41,6 @@ namespace Umbraco.Cms.Core.Events /// /// This is protected so that inheritors can expose it with their own name /// - public object EventObject { get; set; } + public object? EventObject { get; set; } } } diff --git a/src/Umbraco.Core/Events/CancellableObjectEventArgsOfTEventObject.cs b/src/Umbraco.Core/Events/CancellableObjectEventArgsOfTEventObject.cs index 1d90effe2a..939fd8e11b 100644 --- a/src/Umbraco.Core/Events/CancellableObjectEventArgsOfTEventObject.cs +++ b/src/Umbraco.Core/Events/CancellableObjectEventArgsOfTEventObject.cs @@ -9,27 +9,27 @@ namespace Umbraco.Cms.Core.Events /// The type of the exposed, impacted object. public class CancellableObjectEventArgs : CancellableObjectEventArgs, IEquatable> { - public CancellableObjectEventArgs(TEventObject eventObject, bool canCancel, EventMessages messages, IDictionary additionalData) + public CancellableObjectEventArgs(TEventObject? eventObject, bool canCancel, EventMessages messages, IDictionary additionalData) : base(eventObject, canCancel, messages, additionalData) { } - public CancellableObjectEventArgs(TEventObject eventObject, bool canCancel, EventMessages eventMessages) + public CancellableObjectEventArgs(TEventObject? eventObject, bool canCancel, EventMessages eventMessages) : base(eventObject, canCancel, eventMessages) { } - public CancellableObjectEventArgs(TEventObject eventObject, EventMessages eventMessages) + public CancellableObjectEventArgs(TEventObject? eventObject, EventMessages eventMessages) : base(eventObject, eventMessages) { } - public CancellableObjectEventArgs(TEventObject eventObject, bool canCancel) + public CancellableObjectEventArgs(TEventObject? eventObject, bool canCancel) : base(eventObject, canCancel) { } - public CancellableObjectEventArgs(TEventObject eventObject) + public CancellableObjectEventArgs(TEventObject? eventObject) : base(eventObject) { } @@ -40,20 +40,20 @@ namespace Umbraco.Cms.Core.Events /// /// This is protected so that inheritors can expose it with their own name /// - protected new TEventObject EventObject + protected new TEventObject? EventObject { - get => (TEventObject) base.EventObject; + get => (TEventObject?) base.EventObject; set => base.EventObject = value; } - public bool Equals(CancellableObjectEventArgs other) + public bool Equals(CancellableObjectEventArgs? other) { if (other is null) return false; if (ReferenceEquals(this, other)) return true; return base.Equals(other) && EqualityComparer.Default.Equals(EventObject, other.EventObject); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is null) return false; if (ReferenceEquals(this, obj)) return true; @@ -65,7 +65,12 @@ namespace Umbraco.Cms.Core.Events { unchecked { - return (base.GetHashCode() * 397) ^ EqualityComparer.Default.GetHashCode(EventObject); + if (EventObject is not null) + { + return (base.GetHashCode() * 397) ^ EqualityComparer.Default.GetHashCode(EventObject); + } + + return base.GetHashCode() * 397; } } diff --git a/src/Umbraco.Core/Events/CopyEventArgs.cs b/src/Umbraco.Core/Events/CopyEventArgs.cs index c4985513cb..6a4969710a 100644 --- a/src/Umbraco.Core/Events/CopyEventArgs.cs +++ b/src/Umbraco.Core/Events/CopyEventArgs.cs @@ -35,7 +35,7 @@ namespace Umbraco.Cms.Core.Events /// /// The original entity /// - public TEntity Original + public TEntity? Original { get { return EventObject; } } @@ -47,14 +47,14 @@ namespace Umbraco.Cms.Core.Events public bool RelateToOriginal { get; set; } - public bool Equals(CopyEventArgs other) + public bool Equals(CopyEventArgs? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return base.Equals(other) && EqualityComparer.Default.Equals(Copy, other.Copy) && ParentId == other.ParentId && RelateToOriginal == other.RelateToOriginal; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; @@ -67,7 +67,11 @@ namespace Umbraco.Cms.Core.Events unchecked { int hashCode = base.GetHashCode(); - hashCode = (hashCode * 397) ^ EqualityComparer.Default.GetHashCode(Copy); + if (Copy is not null) + { + hashCode = (hashCode * 397) ^ EqualityComparer.Default.GetHashCode(Copy); + } + hashCode = (hashCode * 397) ^ ParentId; hashCode = (hashCode * 397) ^ RelateToOriginal.GetHashCode(); return hashCode; diff --git a/src/Umbraco.Core/Events/DeleteEventArgs.cs b/src/Umbraco.Core/Events/DeleteEventArgs.cs index 0a3f76eeb8..ce4e2a79bb 100644 --- a/src/Umbraco.Core/Events/DeleteEventArgs.cs +++ b/src/Umbraco.Core/Events/DeleteEventArgs.cs @@ -97,7 +97,7 @@ namespace Umbraco.Cms.Core.Events /// /// Returns all entities that were deleted during the operation /// - public IEnumerable DeletedEntities + public IEnumerable? DeletedEntities { get => EventObject; set => EventObject = value; @@ -108,14 +108,14 @@ namespace Umbraco.Cms.Core.Events /// public List MediaFilesToDelete { get; private set; } - public bool Equals(DeleteEventArgs other) + public bool Equals(DeleteEventArgs? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return base.Equals(other) && MediaFilesToDelete.SequenceEqual(other.MediaFilesToDelete); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; @@ -166,14 +166,14 @@ namespace Umbraco.Cms.Core.Events /// public int Id { get; private set; } - public bool Equals(DeleteEventArgs other) + public bool Equals(DeleteEventArgs? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return base.Equals(other) && Id == other.Id; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; diff --git a/src/Umbraco.Core/Events/EventAggregator.Notifications.cs b/src/Umbraco.Core/Events/EventAggregator.Notifications.cs index 58ccb06ed0..85483c99d5 100644 --- a/src/Umbraco.Core/Events/EventAggregator.Notifications.cs +++ b/src/Umbraco.Core/Events/EventAggregator.Notifications.cs @@ -16,30 +16,30 @@ namespace Umbraco.Cms.Core.Events /// public partial class EventAggregator : IEventAggregator { - private static readonly ConcurrentDictionary s_notificationAsyncHandlers - = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary s_notificationAsyncHandlers + = new ConcurrentDictionary(); - private static readonly ConcurrentDictionary s_notificationHandlers - = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary s_notificationHandlers + = new ConcurrentDictionary(); - private Task PublishNotificationAsync(INotification notification, CancellationToken cancellationToken = default) + private Task? PublishNotificationAsync(INotification notification, CancellationToken cancellationToken = default) { Type notificationType = notification.GetType(); - NotificationAsyncHandlerWrapper asyncHandler = s_notificationAsyncHandlers.GetOrAdd( + NotificationAsyncHandlerWrapper? asyncHandler = s_notificationAsyncHandlers.GetOrAdd( notificationType, - t => (NotificationAsyncHandlerWrapper)Activator.CreateInstance(typeof(NotificationAsyncHandlerWrapperImpl<>).MakeGenericType(notificationType))); + t => (NotificationAsyncHandlerWrapper?)Activator.CreateInstance(typeof(NotificationAsyncHandlerWrapperImpl<>).MakeGenericType(notificationType))); - return asyncHandler.HandleAsync(notification, cancellationToken, _serviceFactory, PublishCoreAsync); + return asyncHandler?.HandleAsync(notification, cancellationToken, _serviceFactory, PublishCoreAsync); } private void PublishNotification(INotification notification) { Type notificationType = notification.GetType(); - NotificationHandlerWrapper asyncHandler = s_notificationHandlers.GetOrAdd( + NotificationHandlerWrapper? asyncHandler = s_notificationHandlers.GetOrAdd( notificationType, - t => (NotificationHandlerWrapper)Activator.CreateInstance(typeof(NotificationHandlerWrapperImpl<>).MakeGenericType(notificationType))); + t => (NotificationHandlerWrapper?)Activator.CreateInstance(typeof(NotificationHandlerWrapperImpl<>).MakeGenericType(notificationType))); - asyncHandler.Handle(notification, _serviceFactory, PublishCore); + asyncHandler?.Handle(notification, _serviceFactory, PublishCore); } private async Task PublishCoreAsync( diff --git a/src/Umbraco.Core/Events/EventAggregator.cs b/src/Umbraco.Core/Events/EventAggregator.cs index f762d62109..d5e81af9c1 100644 --- a/src/Umbraco.Core/Events/EventAggregator.cs +++ b/src/Umbraco.Core/Events/EventAggregator.cs @@ -30,7 +30,7 @@ namespace Umbraco.Cms.Core.Events => _serviceFactory = serviceFactory; /// - public Task PublishAsync(TNotification notification, CancellationToken cancellationToken = default) + public Task? PublishAsync(TNotification notification, CancellationToken cancellationToken = default) where TNotification : INotification { // TODO: Introduce codegen efficient Guard classes to reduce noise. @@ -54,7 +54,11 @@ namespace Umbraco.Cms.Core.Events } PublishNotification(notification); - Task.WaitAll(PublishNotificationAsync(notification)); + var task = PublishNotificationAsync(notification); + if (task is not null) + { + Task.WaitAll(task); + } } public bool PublishCancelable(TCancelableNotification notification) @@ -72,12 +76,17 @@ namespace Umbraco.Cms.Core.Events public async Task PublishCancelableAsync(TCancelableNotification notification) where TCancelableNotification : ICancelableNotification { - if (notification == null) + if (notification is null) { throw new ArgumentNullException(nameof(notification)); } - await PublishAsync(notification); + Task? task = PublishAsync(notification); + if (task is not null) + { + await task; + } + return notification.Cancel; } } diff --git a/src/Umbraco.Core/Events/EventDefinition.cs b/src/Umbraco.Core/Events/EventDefinition.cs index 0b28900ada..b803db5989 100644 --- a/src/Umbraco.Core/Events/EventDefinition.cs +++ b/src/Umbraco.Core/Events/EventDefinition.cs @@ -27,11 +27,11 @@ namespace Umbraco.Cms.Core.Events public class EventDefinition : EventDefinitionBase { - private readonly EventHandler _trackedEvent; + private readonly EventHandler _trackedEvent; private readonly object _sender; - private readonly TEventArgs _args; + private readonly TEventArgs? _args; - public EventDefinition(EventHandler trackedEvent, object sender, TEventArgs args, string eventName = null) + public EventDefinition(EventHandler trackedEvent, object sender, TEventArgs? args, string? eventName = null) : base(sender, args, eventName) { _trackedEvent = trackedEvent; @@ -50,11 +50,11 @@ namespace Umbraco.Cms.Core.Events public class EventDefinition : EventDefinitionBase { - private readonly TypedEventHandler _trackedEvent; - private readonly TSender _sender; + private readonly TypedEventHandler _trackedEvent; + private readonly TSender? _sender; private readonly TEventArgs _args; - public EventDefinition(TypedEventHandler trackedEvent, TSender sender, TEventArgs args, string eventName = null) + public EventDefinition(TypedEventHandler trackedEvent, TSender? sender, TEventArgs args, string? eventName = null) : base(sender, args, eventName) { _trackedEvent = trackedEvent; diff --git a/src/Umbraco.Core/Events/EventDefinitionBase.cs b/src/Umbraco.Core/Events/EventDefinitionBase.cs index 7dfd8a647c..4223924234 100644 --- a/src/Umbraco.Core/Events/EventDefinitionBase.cs +++ b/src/Umbraco.Core/Events/EventDefinitionBase.cs @@ -6,7 +6,7 @@ namespace Umbraco.Cms.Core.Events { public abstract class EventDefinitionBase : IEventDefinition, IEquatable { - protected EventDefinitionBase(object sender, object args, string? eventName = null) + protected EventDefinitionBase(object? sender, object? args, string? eventName = null) { Sender = sender ?? throw new ArgumentNullException(nameof(sender)); Args = args ?? throw new ArgumentNullException(nameof(args)); @@ -20,8 +20,8 @@ namespace Umbraco.Cms.Core.Events if (findResult.Success == false) throw new AmbiguousMatchException("Could not automatically find the event name, the event name will need to be explicitly registered for this event definition. " + $"Sender: {sender.GetType()} Args: {args.GetType()}" - + " Error: " + findResult.Result.Error); - EventName = findResult.Result.Name; + + " Error: " + findResult.Result?.Error); + EventName = findResult.Result?.Name; } } @@ -31,14 +31,14 @@ namespace Umbraco.Cms.Core.Events public abstract void RaiseEvent(); - public bool Equals(EventDefinitionBase other) + public bool Equals(EventDefinitionBase? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return Args.Equals(other.Args) && string.Equals(EventName, other.EventName) && Sender.Equals(other.Sender); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; @@ -51,7 +51,10 @@ namespace Umbraco.Cms.Core.Events unchecked { var hashCode = Args.GetHashCode(); - hashCode = (hashCode * 397) ^ EventName.GetHashCode(); + if (EventName is not null) + { + hashCode = (hashCode * 397) ^ EventName.GetHashCode(); + } hashCode = (hashCode * 397) ^ Sender.GetHashCode(); return hashCode; } diff --git a/src/Umbraco.Core/Events/EventNameExtractor.cs b/src/Umbraco.Core/Events/EventNameExtractor.cs index cbff67d491..c74d2e293e 100644 --- a/src/Umbraco.Core/Events/EventNameExtractor.cs +++ b/src/Umbraco.Core/Events/EventNameExtractor.cs @@ -34,7 +34,7 @@ namespace Umbraco.Cms.Core.Events /// /// null if not found or an ambiguous match /// - public static Attempt FindEvent(Type senderType, Type argsType, Func exclude) + public static Attempt FindEvent(Type senderType, Type argsType, Func exclude) { var events = FindEvents(senderType, argsType, exclude); @@ -61,15 +61,15 @@ namespace Umbraco.Cms.Core.Events return t.GetEvents(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy) //we can only look for events handlers with generic types because that is the only // way that we can try to find a matching event based on the arg type passed in - .Where(x => x.EventHandlerType.IsGenericType) - .Select(x => new EventInfoArgs(x, x.EventHandlerType.GetGenericArguments())) + .Where(x => x.EventHandlerType?.IsGenericType ?? false) + .Select(x => new EventInfoArgs(x, x.EventHandlerType!.GetGenericArguments())) //we are only looking for event handlers that have more than one generic argument .Where(x => { if (x.GenericArgs.Length == 1) return true; //special case for our own TypedEventHandler - if (x.EventInfo.EventHandlerType.GetGenericTypeDefinition() == typeof(TypedEventHandler<,>) && x.GenericArgs.Length == 2) + if (x.EventInfo.EventHandlerType?.GetGenericTypeDefinition() == typeof(TypedEventHandler<,>) && x.GenericArgs.Length == 2) { return true; } @@ -85,7 +85,7 @@ namespace Umbraco.Cms.Core.Events return true; //special case for our own TypedEventHandler - if (x.EventInfo.EventHandlerType.GetGenericTypeDefinition() == typeof(TypedEventHandler<,>) + if (x.EventInfo.EventHandlerType?.GetGenericTypeDefinition() == typeof(TypedEventHandler<,>) && x.GenericArgs.Length == 2 && x.GenericArgs[1] == tuple.Item2) { @@ -110,7 +110,7 @@ namespace Umbraco.Cms.Core.Events /// /// null if not found or an ambiguous match /// - public static Attempt FindEvent(object sender, object args, Func exclude) + public static Attempt FindEvent(object sender, object args, Func exclude) { return FindEvent(sender.GetType(), args.GetType(), exclude); } diff --git a/src/Umbraco.Core/Events/EventNameExtractorResult.cs b/src/Umbraco.Core/Events/EventNameExtractorResult.cs index bdfd884401..2f5498c33f 100644 --- a/src/Umbraco.Core/Events/EventNameExtractorResult.cs +++ b/src/Umbraco.Core/Events/EventNameExtractorResult.cs @@ -3,14 +3,14 @@ public class EventNameExtractorResult { public EventNameExtractorError? Error { get; private set; } - public string Name { get; private set; } + public string? Name { get; private set; } - public EventNameExtractorResult(string name) + public EventNameExtractorResult(string? name) { Name = name; } - public EventNameExtractorResult(EventNameExtractorError error) + public EventNameExtractorResult(EventNameExtractorError? error) { Error = error; } diff --git a/src/Umbraco.Core/Events/IEventAggregator.cs b/src/Umbraco.Core/Events/IEventAggregator.cs index c654bb6c86..77197b121f 100644 --- a/src/Umbraco.Core/Events/IEventAggregator.cs +++ b/src/Umbraco.Core/Events/IEventAggregator.cs @@ -20,7 +20,7 @@ namespace Umbraco.Cms.Core.Events /// The notification object. /// An optional cancellation token. /// A task that represents the publish operation. - Task PublishAsync(TNotification notification, CancellationToken cancellationToken = default) + Task? PublishAsync(TNotification notification, CancellationToken cancellationToken = default) where TNotification : INotification; /// diff --git a/src/Umbraco.Core/Events/IEventDefinition.cs b/src/Umbraco.Core/Events/IEventDefinition.cs index 09985f833a..e3918113e1 100644 --- a/src/Umbraco.Core/Events/IEventDefinition.cs +++ b/src/Umbraco.Core/Events/IEventDefinition.cs @@ -4,7 +4,7 @@ { object Sender { get; } object Args { get; } - string EventName { get; } + string? EventName { get; } void RaiseEvent(); } diff --git a/src/Umbraco.Core/Events/IEventDispatcher.cs b/src/Umbraco.Core/Events/IEventDispatcher.cs index bef94b6d4a..d8d140090d 100644 --- a/src/Umbraco.Core/Events/IEventDispatcher.cs +++ b/src/Umbraco.Core/Events/IEventDispatcher.cs @@ -71,7 +71,7 @@ namespace Umbraco.Cms.Core.Events /// The event data. /// The optional name of the event. /// See general remarks on the interface. - void Dispatch(EventHandler eventHandler, object sender, TArgs args, string? name = null); + void Dispatch(EventHandler eventHandler, object sender, TArgs args, string? name = null); /// /// Dispatches an event. @@ -81,7 +81,7 @@ namespace Umbraco.Cms.Core.Events /// The event data. /// The optional name of the event. /// See general remarks on the interface. - void Dispatch(TypedEventHandler eventHandler, TSender sender, TArgs args, string? name = null); + void Dispatch(TypedEventHandler eventHandler, TSender sender, TArgs args, string? name = null); /// /// Notifies the dispatcher that the scope is exiting. diff --git a/src/Umbraco.Core/Events/IEventMessagesFactory.cs b/src/Umbraco.Core/Events/IEventMessagesFactory.cs index 6b3e4fe0af..6abf6e8d41 100644 --- a/src/Umbraco.Core/Events/IEventMessagesFactory.cs +++ b/src/Umbraco.Core/Events/IEventMessagesFactory.cs @@ -7,6 +7,6 @@ { EventMessages Get(); - EventMessages GetOrDefault(); + EventMessages? GetOrDefault(); } } diff --git a/src/Umbraco.Core/Events/MoveEventArgs.cs b/src/Umbraco.Core/Events/MoveEventArgs.cs index dfb42fcc96..2f65056353 100644 --- a/src/Umbraco.Core/Events/MoveEventArgs.cs +++ b/src/Umbraco.Core/Events/MoveEventArgs.cs @@ -6,7 +6,7 @@ namespace Umbraco.Cms.Core.Events { public class MoveEventArgs : CancellableObjectEventArgs, IEquatable> { - private IEnumerable> _moveInfoCollection; + private IEnumerable>? _moveInfoCollection; /// /// Constructor accepting a collection of MoveEventInfo objects @@ -19,7 +19,7 @@ namespace Umbraco.Cms.Core.Events public MoveEventArgs(bool canCancel, EventMessages eventMessages, params MoveEventInfo[] moveInfo) : base(default, canCancel, eventMessages) { - if (moveInfo.FirstOrDefault() == null) + if (moveInfo.FirstOrDefault() is null) { throw new ArgumentException("moveInfo argument must contain at least one item"); } @@ -39,7 +39,7 @@ namespace Umbraco.Cms.Core.Events public MoveEventArgs(EventMessages eventMessages, params MoveEventInfo[] moveInfo) : base(default, eventMessages) { - if (moveInfo.FirstOrDefault() == null) + if (moveInfo.FirstOrDefault() is null) { throw new ArgumentException("moveInfo argument must contain at least one item"); } @@ -59,7 +59,7 @@ namespace Umbraco.Cms.Core.Events public MoveEventArgs(bool canCancel, params MoveEventInfo[] moveInfo) : base(default, canCancel) { - if (moveInfo.FirstOrDefault() == null) + if (moveInfo.FirstOrDefault() is null) { throw new ArgumentException("moveInfo argument must contain at least one item"); } @@ -78,7 +78,7 @@ namespace Umbraco.Cms.Core.Events public MoveEventArgs(params MoveEventInfo[] moveInfo) : base(default) { - if (moveInfo.FirstOrDefault() == null) + if (moveInfo.FirstOrDefault() is null) { throw new ArgumentException("moveInfo argument must contain at least one item"); } @@ -92,13 +92,13 @@ namespace Umbraco.Cms.Core.Events /// /// Gets all MoveEventInfo objects used to create the object /// - public IEnumerable> MoveInfoCollection + public IEnumerable>? MoveInfoCollection { get { return _moveInfoCollection; } set { - var first = value.FirstOrDefault(); - if (first == null) + var first = value?.FirstOrDefault(); + if (first is null) { throw new InvalidOperationException("MoveInfoCollection must have at least one item"); } @@ -110,14 +110,14 @@ namespace Umbraco.Cms.Core.Events } } - public bool Equals(MoveEventArgs other) + public bool Equals(MoveEventArgs? other) { if (other is null) return false; if (ReferenceEquals(this, other)) return true; - return base.Equals(other) && MoveInfoCollection.Equals(other.MoveInfoCollection); + return base.Equals(other) && (MoveInfoCollection?.Equals(other.MoveInfoCollection) ?? false); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is null) return false; if (ReferenceEquals(this, obj)) return true; @@ -129,7 +129,12 @@ namespace Umbraco.Cms.Core.Events { unchecked { - return (base.GetHashCode() * 397) ^ MoveInfoCollection.GetHashCode(); + if (MoveInfoCollection is not null) + { + return (base.GetHashCode() * 397) ^ MoveInfoCollection.GetHashCode(); + } + + return base.GetHashCode() * 397; } } diff --git a/src/Umbraco.Core/Events/MoveEventInfo.cs b/src/Umbraco.Core/Events/MoveEventInfo.cs index 9abcbd2c68..126a3fd230 100644 --- a/src/Umbraco.Core/Events/MoveEventInfo.cs +++ b/src/Umbraco.Core/Events/MoveEventInfo.cs @@ -16,14 +16,14 @@ namespace Umbraco.Cms.Core.Events public string OriginalPath { get; set; } public int NewParentId { get; set; } - public bool Equals(MoveEventInfo other) + public bool Equals(MoveEventInfo? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return EqualityComparer.Default.Equals(Entity, other.Entity) && NewParentId == other.NewParentId && string.Equals(OriginalPath, other.OriginalPath); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; @@ -35,7 +35,7 @@ namespace Umbraco.Cms.Core.Events { unchecked { - var hashCode = EqualityComparer.Default.GetHashCode(Entity); + var hashCode = Entity is not null ? EqualityComparer.Default.GetHashCode(Entity) : base.GetHashCode(); hashCode = (hashCode * 397) ^ NewParentId; hashCode = (hashCode * 397) ^ OriginalPath.GetHashCode(); return hashCode; diff --git a/src/Umbraco.Core/Events/NewEventArgs.cs b/src/Umbraco.Core/Events/NewEventArgs.cs index a659787547..d3e8436d0e 100644 --- a/src/Umbraco.Core/Events/NewEventArgs.cs +++ b/src/Umbraco.Core/Events/NewEventArgs.cs @@ -14,7 +14,7 @@ namespace Umbraco.Cms.Core.Events ParentId = parentId; } - public NewEventArgs(TEntity eventObject, bool canCancel, string @alias, TEntity parent, EventMessages eventMessages) + public NewEventArgs(TEntity eventObject, bool canCancel, string @alias, TEntity? parent, EventMessages eventMessages) : base(eventObject, canCancel, eventMessages) { Alias = alias; @@ -28,7 +28,7 @@ namespace Umbraco.Cms.Core.Events ParentId = parentId; } - public NewEventArgs(TEntity eventObject, string @alias, TEntity parent, EventMessages eventMessages) + public NewEventArgs(TEntity eventObject, string @alias, TEntity? parent, EventMessages eventMessages) : base(eventObject, eventMessages) { Alias = alias; @@ -43,7 +43,7 @@ namespace Umbraco.Cms.Core.Events ParentId = parentId; } - public NewEventArgs(TEntity eventObject, bool canCancel, string @alias, TEntity parent) + public NewEventArgs(TEntity eventObject, bool canCancel, string @alias, TEntity? parent) : base(eventObject, canCancel) { Alias = alias; @@ -56,7 +56,7 @@ namespace Umbraco.Cms.Core.Events ParentId = parentId; } - public NewEventArgs(TEntity eventObject, string @alias, TEntity parent) + public NewEventArgs(TEntity eventObject, string @alias, TEntity? parent) : base(eventObject) { Alias = alias; @@ -66,7 +66,7 @@ namespace Umbraco.Cms.Core.Events /// /// The entity being created /// - public TEntity Entity + public TEntity? Entity { get { return EventObject; } } @@ -84,21 +84,21 @@ namespace Umbraco.Cms.Core.Events /// /// Gets or Sets the parent IContent object. /// - public TEntity Parent { get; private set; } + public TEntity? Parent { get; private set; } - public bool Equals(NewEventArgs other) + public bool Equals(NewEventArgs? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return base.Equals(other) && string.Equals(Alias, other.Alias) && EqualityComparer.Default.Equals(Parent, other.Parent) && ParentId == other.ParentId; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != this.GetType()) return false; - return Equals((NewEventArgs) obj); + return Equals((NewEventArgs?) obj); } public override int GetHashCode() @@ -107,7 +107,11 @@ namespace Umbraco.Cms.Core.Events { int hashCode = base.GetHashCode(); hashCode = (hashCode * 397) ^ Alias.GetHashCode(); - hashCode = (hashCode * 397) ^ EqualityComparer.Default.GetHashCode(Parent); + if (Parent is not null) + { + hashCode = (hashCode * 397) ^ EqualityComparer.Default.GetHashCode(Parent); + } + hashCode = (hashCode * 397) ^ ParentId; return hashCode; } diff --git a/src/Umbraco.Core/Events/PassThroughEventDispatcher.cs b/src/Umbraco.Core/Events/PassThroughEventDispatcher.cs index 0b2e72cc7f..d2dafb24f9 100644 --- a/src/Umbraco.Core/Events/PassThroughEventDispatcher.cs +++ b/src/Umbraco.Core/Events/PassThroughEventDispatcher.cs @@ -11,14 +11,14 @@ namespace Umbraco.Cms.Core.Events /// whatever happens, and the transaction could roll back in the end. internal class PassThroughEventDispatcher : IEventDispatcher { - public bool DispatchCancelable(EventHandler eventHandler, object sender, CancellableEventArgs args, string eventName = null) + public bool DispatchCancelable(EventHandler eventHandler, object sender, CancellableEventArgs args, string? eventName = null) { if (eventHandler == null) return args.Cancel; eventHandler(sender, args); return args.Cancel; } - public bool DispatchCancelable(EventHandler eventHandler, object sender, TArgs args, string eventName = null) + public bool DispatchCancelable(EventHandler eventHandler, object sender, TArgs args, string? eventName = null) where TArgs : CancellableEventArgs { if (eventHandler == null) return args.Cancel; @@ -26,7 +26,7 @@ namespace Umbraco.Cms.Core.Events return args.Cancel; } - public bool DispatchCancelable(TypedEventHandler eventHandler, TSender sender, TArgs args, string eventName = null) + public bool DispatchCancelable(TypedEventHandler eventHandler, TSender sender, TArgs args, string? eventName = null) where TArgs : CancellableEventArgs { if (eventHandler == null) return args.Cancel; @@ -34,17 +34,17 @@ namespace Umbraco.Cms.Core.Events return args.Cancel; } - public void Dispatch(EventHandler eventHandler, object sender, EventArgs args, string eventName = null) + public void Dispatch(EventHandler eventHandler, object sender, EventArgs args, string? eventName = null) { eventHandler?.Invoke(sender, args); } - public void Dispatch(EventHandler eventHandler, object sender, TArgs args, string eventName = null) + public void Dispatch(EventHandler eventHandler, object sender, TArgs args, string? eventName = null) { eventHandler?.Invoke(sender, args); } - public void Dispatch(TypedEventHandler eventHandler, TSender sender, TArgs args, string eventName = null) + public void Dispatch(TypedEventHandler eventHandler, TSender sender, TArgs args, string? eventName = null) { eventHandler?.Invoke(sender, args); } diff --git a/src/Umbraco.Core/Events/PublishEventArgs.cs b/src/Umbraco.Core/Events/PublishEventArgs.cs index 101458b897..80b6dcd8c7 100644 --- a/src/Umbraco.Core/Events/PublishEventArgs.cs +++ b/src/Umbraco.Core/Events/PublishEventArgs.cs @@ -90,16 +90,16 @@ namespace Umbraco.Cms.Core.Events /// /// Returns all entities that were published during the operation /// - public IEnumerable PublishedEntities => EventObject; + public IEnumerable? PublishedEntities => EventObject; - public bool Equals(PublishEventArgs other) + public bool Equals(PublishEventArgs? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return base.Equals(other); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; diff --git a/src/Umbraco.Core/Events/QueuingEventDispatcherBase.cs b/src/Umbraco.Core/Events/QueuingEventDispatcherBase.cs index 784390ebe7..332de83c8e 100644 --- a/src/Umbraco.Core/Events/QueuingEventDispatcherBase.cs +++ b/src/Umbraco.Core/Events/QueuingEventDispatcherBase.cs @@ -20,7 +20,7 @@ namespace Umbraco.Cms.Core.Events public abstract class QueuingEventDispatcherBase : IEventDispatcher { //events will be enlisted in the order they are raised - private List _events; + private List? _events; private readonly bool _raiseCancelable; protected QueuingEventDispatcherBase(bool raiseCancelable) @@ -30,7 +30,7 @@ namespace Umbraco.Cms.Core.Events private List Events => _events ?? (_events = new List()); - public bool DispatchCancelable(EventHandler eventHandler, object sender, CancellableEventArgs args, string eventName = null) + public bool DispatchCancelable(EventHandler eventHandler, object sender, CancellableEventArgs args, string? eventName = null) { if (eventHandler == null) return args.Cancel; if (_raiseCancelable == false) return args.Cancel; @@ -38,7 +38,7 @@ namespace Umbraco.Cms.Core.Events return args.Cancel; } - public bool DispatchCancelable(EventHandler eventHandler, object sender, TArgs args, string eventName = null) + public bool DispatchCancelable(EventHandler eventHandler, object sender, TArgs args, string? eventName = null) where TArgs : CancellableEventArgs { if (eventHandler == null) return args.Cancel; @@ -47,7 +47,7 @@ namespace Umbraco.Cms.Core.Events return args.Cancel; } - public bool DispatchCancelable(TypedEventHandler eventHandler, TSender sender, TArgs args, string eventName = null) + public bool DispatchCancelable(TypedEventHandler eventHandler, TSender sender, TArgs args, string? eventName = null) where TArgs : CancellableEventArgs { if (eventHandler == null) return args.Cancel; @@ -56,19 +56,19 @@ namespace Umbraco.Cms.Core.Events return args.Cancel; } - public void Dispatch(EventHandler eventHandler, object sender, EventArgs args, string eventName = null) + public void Dispatch(EventHandler eventHandler, object sender, EventArgs args, string? eventName = null) { if (eventHandler == null) return; Events.Add(new EventDefinition(eventHandler, sender, args, eventName)); } - public void Dispatch(EventHandler eventHandler, object sender, TArgs args, string eventName = null) + public void Dispatch(EventHandler eventHandler, object sender, TArgs args, string? eventName = null) { if (eventHandler == null) return; Events.Add(new EventDefinition(eventHandler, sender, args, eventName)); } - public void Dispatch(TypedEventHandler eventHandler, TSender sender, TArgs args, string eventName = null) + public void Dispatch(TypedEventHandler eventHandler, TSender sender, TArgs args, string? eventName = null) { if (eventHandler == null) return; Events.Add(new EventDefinition(eventHandler, sender, args, eventName)); @@ -106,8 +106,8 @@ namespace Umbraco.Cms.Core.Events private class EventDefinitionInfos { - public IEventDefinition EventDefinition { get; set; } - public Type[] SupersedeTypes { get; set; } + public IEventDefinition? EventDefinition { get; set; } + public Type[]? SupersedeTypes { get; set; } } // this is way too convoluted, the supersede attribute is used only on DeleteEventargs to specify @@ -158,7 +158,7 @@ namespace Umbraco.Cms.Core.Events }; var args = def.Args as CancellableObjectEventArgs; - if (args == null) + if (args is not null) { // not a cancellable event arg, include event definition in result result.Add(def); @@ -167,12 +167,12 @@ namespace Umbraco.Cms.Core.Events { // event object can either be a single object or an enumerable of objects // try to get as an enumerable, get null if it's not - var eventObjects = TypeHelper.CreateGenericEnumerableFromObject(args.EventObject); + var eventObjects = args?.EventObject is not null ? TypeHelper.CreateGenericEnumerableFromObject(args.EventObject) : null; if (eventObjects == null) { // single object, cast as an IEntity // if cannot cast, cannot filter, nothing - just include event definition in result - var eventEntity = args.EventObject as IEntity; + var eventEntity = args?.EventObject as IEntity; if (eventEntity == null) { result.Add(def); @@ -188,7 +188,7 @@ namespace Umbraco.Cms.Core.Events // track result arguments // include event definition in result - resultArgs.Add(args); + resultArgs.Add(args!); result.Add(def); } } @@ -222,12 +222,15 @@ namespace Umbraco.Cms.Core.Events if (toRemove.Count > 0) { // re-assign if changed - args.EventObject = eventObjects; + if (args is not null) + { + args.EventObject = eventObjects; + } } // track result arguments // include event definition in result - resultArgs.Add(args); + resultArgs.Add(args!); result.Add(def); } } @@ -256,7 +259,7 @@ namespace Umbraco.Cms.Core.Events { // event object can either be a single object or an enumerable of objects // try to get as an enumerable, get null if it's not - var eventObjects = TypeHelper.CreateGenericEnumerableFromObject(arg.EventObject); + var eventObjects = arg.EventObject is not null ? TypeHelper.CreateGenericEnumerableFromObject(arg.EventObject) : null; if (eventObjects == null) { // single object @@ -291,13 +294,13 @@ namespace Umbraco.Cms.Core.Events private static bool IsSuperceeded(IEntity entity, EventDefinitionInfos infos, List> entities) { //var argType = meta.EventArgsType; - var argType = infos.EventDefinition.Args.GetType(); + var argType = infos.EventDefinition?.Args.GetType(); // look for other instances of the same entity, coming from an event args that supersedes other event args, // ie is marked with the attribute, and is not this event args (cannot supersede itself) var superceeding = entities - .Where(x => x.Item2.SupersedeTypes.Length > 0 // has the attribute - && x.Item2.EventDefinition.Args.GetType() != argType // is not the same + .Where(x => x.Item2.SupersedeTypes?.Length > 0 // has the attribute + && x.Item2.EventDefinition?.Args.GetType() != argType // is not the same && Equals(x.Item1, entity)) // same entity .ToArray(); @@ -306,27 +309,27 @@ namespace Umbraco.Cms.Core.Events return false; // delete event args does NOT supersedes 'unpublished' event - if (argType.IsGenericType && argType.GetGenericTypeDefinition() == typeof(PublishEventArgs<>) && infos.EventDefinition.EventName == "Unpublished") + if ((argType?.IsGenericType ?? false) && argType.GetGenericTypeDefinition() == typeof(PublishEventArgs<>) && infos.EventDefinition?.EventName == "Unpublished") return false; // found occurrences, need to determine if this event args is superseded - if (argType.IsGenericType) + if (argType?.IsGenericType ?? false) { // generic, must compare type arguments var supercededBy = superceeding.FirstOrDefault(x => - x.Item2.SupersedeTypes.Any(y => + x.Item2.SupersedeTypes?.Any(y => // superseding a generic type which has the same generic type definition // (but ... no matter the generic type parameters? could be different?) y.IsGenericTypeDefinition && y == argType.GetGenericTypeDefinition() // or superceeding a non-generic type which is ... (but... how is this ever possible? argType *is* generic? - || y.IsGenericTypeDefinition == false && y == argType)); + || y.IsGenericTypeDefinition == false && y == argType) ?? false); return supercededBy != null; } else { // non-generic, can compare types 1:1 var supercededBy = superceeding.FirstOrDefault(x => - x.Item2.SupersedeTypes.Any(y => y == argType)); + x.Item2.SupersedeTypes?.Any(y => y == argType) ?? false); return supercededBy != null; } } diff --git a/src/Umbraco.Core/Events/RecycleBinEventArgs.cs b/src/Umbraco.Core/Events/RecycleBinEventArgs.cs index a1791618bc..ee0d43a07a 100644 --- a/src/Umbraco.Core/Events/RecycleBinEventArgs.cs +++ b/src/Umbraco.Core/Events/RecycleBinEventArgs.cs @@ -38,14 +38,14 @@ namespace Umbraco.Cms.Core.Events /// public bool IsMediaRecycleBin => NodeObjectType == Constants.ObjectTypes.Media; - public bool Equals(RecycleBinEventArgs other) + public bool Equals(RecycleBinEventArgs? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return base.Equals(other) && NodeObjectType.Equals(other.NodeObjectType) && RecycleBinEmptiedSuccessfully == other.RecycleBinEmptiedSuccessfully; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; diff --git a/src/Umbraco.Core/Events/RollbackEventArgs.cs b/src/Umbraco.Core/Events/RollbackEventArgs.cs index c83b209e05..96b67ba769 100644 --- a/src/Umbraco.Core/Events/RollbackEventArgs.cs +++ b/src/Umbraco.Core/Events/RollbackEventArgs.cs @@ -13,7 +13,7 @@ /// /// The entity being rolledback /// - public TEntity Entity + public TEntity? Entity { get { return EventObject; } } diff --git a/src/Umbraco.Core/Events/SaveEventArgs.cs b/src/Umbraco.Core/Events/SaveEventArgs.cs index 173c9fe2d6..3424962a54 100644 --- a/src/Umbraco.Core/Events/SaveEventArgs.cs +++ b/src/Umbraco.Core/Events/SaveEventArgs.cs @@ -112,6 +112,6 @@ namespace Umbraco.Cms.Core.Events /// /// Returns all entities that were saved during the operation /// - public IEnumerable SavedEntities => EventObject; + public IEnumerable? SavedEntities => EventObject; } } diff --git a/src/Umbraco.Core/Events/ScopedNotificationPublisher.cs b/src/Umbraco.Core/Events/ScopedNotificationPublisher.cs index 7261b514bf..cdd8707a79 100644 --- a/src/Umbraco.Core/Events/ScopedNotificationPublisher.cs +++ b/src/Umbraco.Core/Events/ScopedNotificationPublisher.cs @@ -50,7 +50,12 @@ namespace Umbraco.Cms.Core.Events return false; } - await _eventAggregator.PublishAsync(notification); + var task = _eventAggregator.PublishAsync(notification); + if (task is not null) + { + await task; + } + return notification.Cancel; } diff --git a/src/Umbraco.Core/Events/SendToPublishEventArgs.cs b/src/Umbraco.Core/Events/SendToPublishEventArgs.cs index b74c0846f0..9b4e078149 100644 --- a/src/Umbraco.Core/Events/SendToPublishEventArgs.cs +++ b/src/Umbraco.Core/Events/SendToPublishEventArgs.cs @@ -13,7 +13,7 @@ /// /// The entity being sent to publish /// - public TEntity Entity + public TEntity? Entity { get { return EventObject; } } diff --git a/src/Umbraco.Core/Events/TransientEventMessagesFactory.cs b/src/Umbraco.Core/Events/TransientEventMessagesFactory.cs index 1179a6316e..2c8dde89a2 100644 --- a/src/Umbraco.Core/Events/TransientEventMessagesFactory.cs +++ b/src/Umbraco.Core/Events/TransientEventMessagesFactory.cs @@ -10,7 +10,7 @@ return new EventMessages(); } - public EventMessages GetOrDefault() + public EventMessages? GetOrDefault() { return null; } diff --git a/src/Umbraco.Core/Events/UserNotificationsHandler.cs b/src/Umbraco.Core/Events/UserNotificationsHandler.cs index d626df7dab..61ac33a5c0 100644 --- a/src/Umbraco.Core/Events/UserNotificationsHandler.cs +++ b/src/Umbraco.Core/Events/UserNotificationsHandler.cs @@ -150,7 +150,7 @@ namespace Umbraco.Cms.Core.Events globalSettings.OnChange(x => _globalSettings = x); } - public void Notify(IAction action, params IContent[] entities) + public void Notify(IAction? action, params IContent[] entities) { var user = _backOfficeSecurityAccessor?.BackOfficeSecurity?.CurrentUser; @@ -169,7 +169,7 @@ namespace Umbraco.Cms.Core.Events SendNotification(user, entities, action, _hostingEnvironment.ApplicationMainUrl); } - private void SendNotification(IUser sender, IEnumerable entities, IAction action, Uri siteUri) + private void SendNotification(IUser sender, IEnumerable entities, IAction? action, Uri siteUri) { if (sender == null) throw new ArgumentNullException(nameof(sender)); @@ -185,8 +185,8 @@ namespace Umbraco.Cms.Core.Events _notificationService.SendNotifications( sender, contentVariantGroup, - action.Letter.ToString(CultureInfo.InvariantCulture), - _textService.Localize("actions", action.Alias), + action?.Letter.ToString(CultureInfo.InvariantCulture), + _textService.Localize("actions", action?.Alias), siteUri, ((IUser user, NotificationEmailSubjectParams subject) x) => _textService.Localize( diff --git a/src/Umbraco.Core/Exceptions/BootFailedException.cs b/src/Umbraco.Core/Exceptions/BootFailedException.cs index 5f546c7b9d..9c4e484741 100644 --- a/src/Umbraco.Core/Exceptions/BootFailedException.cs +++ b/src/Umbraco.Core/Exceptions/BootFailedException.cs @@ -67,7 +67,7 @@ namespace Umbraco.Cms.Core.Exceptions // would that be the correct way to do it? //ExceptionDispatchInfo.Capture(bootFailedException).Throw(); - Exception e = bootFailedException; + Exception? e = bootFailedException; var m = new StringBuilder(); m.Append(DefaultMessage); while (e != null) diff --git a/src/Umbraco.Core/Exceptions/DataOperationException.cs b/src/Umbraco.Core/Exceptions/DataOperationException.cs index f4146758bd..0b56cfb72c 100644 --- a/src/Umbraco.Core/Exceptions/DataOperationException.cs +++ b/src/Umbraco.Core/Exceptions/DataOperationException.cs @@ -21,7 +21,7 @@ namespace Umbraco.Cms.Core.Exceptions /// /// This object should be serializable to prevent a to be thrown. /// - public T Operation { get; private set; } + public T? Operation { get; private set; } /// /// Initializes a new instance of the class. @@ -74,7 +74,7 @@ namespace Umbraco.Cms.Core.Exceptions protected DataOperationException(SerializationInfo info, StreamingContext context) : base(info, context) { - Operation = (T)Enum.Parse(typeof(T), info.GetString(nameof(Operation))); + Operation = (T)Enum.Parse(typeof(T), info.GetString(nameof(Operation)) ?? string.Empty); } /// @@ -90,7 +90,7 @@ namespace Umbraco.Cms.Core.Exceptions throw new ArgumentNullException(nameof(info)); } - info.AddValue(nameof(Operation), Enum.GetName(typeof(T), Operation)); + info.AddValue(nameof(Operation), Operation is not null ? Enum.GetName(typeof(T), Operation) : string.Empty); base.GetObjectData(info, context); } diff --git a/src/Umbraco.Core/Exceptions/InvalidCompositionException.cs b/src/Umbraco.Core/Exceptions/InvalidCompositionException.cs index 21e5cc03ed..ba8c2b6106 100644 --- a/src/Umbraco.Core/Exceptions/InvalidCompositionException.cs +++ b/src/Umbraco.Core/Exceptions/InvalidCompositionException.cs @@ -18,7 +18,7 @@ namespace Umbraco.Cms.Core.Exceptions /// /// The content type alias. /// - public string ContentTypeAlias { get; } + public string? ContentTypeAlias { get; } /// /// Gets the added composition alias. @@ -26,7 +26,7 @@ namespace Umbraco.Cms.Core.Exceptions /// /// The added composition alias. /// - public string AddedCompositionAlias { get; } + public string? AddedCompositionAlias { get; } /// /// Gets the property type aliases. @@ -34,7 +34,7 @@ namespace Umbraco.Cms.Core.Exceptions /// /// The property type aliases. /// - public string[] PropertyTypeAliases { get; } + public string[]? PropertyTypeAliases { get; } /// /// Gets the property group aliases. @@ -42,7 +42,7 @@ namespace Umbraco.Cms.Core.Exceptions /// /// The property group aliases. /// - public string[] PropertyGroupAliases { get; } + public string[]? PropertyGroupAliases { get; } /// /// Initializes a new instance of the class. @@ -65,7 +65,7 @@ namespace Umbraco.Cms.Core.Exceptions /// The content type alias. /// The added composition alias. /// The property type aliases. - public InvalidCompositionException(string contentTypeAlias, string addedCompositionAlias, string[] propertyTypeAliases) + public InvalidCompositionException(string contentTypeAlias, string? addedCompositionAlias, string[] propertyTypeAliases) : this(contentTypeAlias, addedCompositionAlias, propertyTypeAliases, new string[0]) { } @@ -76,7 +76,7 @@ namespace Umbraco.Cms.Core.Exceptions /// The added composition alias. /// The property type aliases. /// The property group aliases. - public InvalidCompositionException(string contentTypeAlias, string addedCompositionAlias, string[] propertyTypeAliases, string[] propertyGroupAliases) + public InvalidCompositionException(string contentTypeAlias, string? addedCompositionAlias, string[] propertyTypeAliases, string[] propertyGroupAliases) : this(FormatMessage(contentTypeAlias, addedCompositionAlias, propertyTypeAliases, propertyGroupAliases)) { ContentTypeAlias = contentTypeAlias; @@ -85,7 +85,7 @@ namespace Umbraco.Cms.Core.Exceptions PropertyGroupAliases = propertyGroupAliases; } - private static string FormatMessage(string contentTypeAlias, string addedCompositionAlias, string[] propertyTypeAliases, string[] propertyGroupAliases) + private static string FormatMessage(string contentTypeAlias, string? addedCompositionAlias, string[] propertyTypeAliases, string[] propertyGroupAliases) { var sb = new StringBuilder(); @@ -138,8 +138,8 @@ namespace Umbraco.Cms.Core.Exceptions { ContentTypeAlias = info.GetString(nameof(ContentTypeAlias)); AddedCompositionAlias = info.GetString(nameof(AddedCompositionAlias)); - PropertyTypeAliases = (string[])info.GetValue(nameof(PropertyTypeAliases), typeof(string[])); - PropertyGroupAliases = (string[])info.GetValue(nameof(PropertyGroupAliases), typeof(string[])); + PropertyTypeAliases = (string[]?)info.GetValue(nameof(PropertyTypeAliases), typeof(string[])); + PropertyGroupAliases = (string[] ?)info.GetValue(nameof(PropertyGroupAliases), typeof(string[])); } /// diff --git a/src/Umbraco.Core/Handlers/AuditNotificationsHandler.cs b/src/Umbraco.Core/Handlers/AuditNotificationsHandler.cs index 502268ead0..fbc91d812d 100644 --- a/src/Umbraco.Core/Handlers/AuditNotificationsHandler.cs +++ b/src/Umbraco.Core/Handlers/AuditNotificationsHandler.cs @@ -65,7 +65,7 @@ namespace Umbraco.Cms.Core.Handlers private string PerformingIp => _ipResolver.GetCurrentRequestIpAddress(); - private string FormatEmail(IMember member) => member == null ? string.Empty : member.Email.IsNullOrWhiteSpace() ? "" : $"<{member.Email}>"; + private string FormatEmail(IMember? member) => member == null ? string.Empty : member.Email.IsNullOrWhiteSpace() ? "" : $"<{member.Email}>"; private string FormatEmail(IUser user) => user == null ? string.Empty : user.Email.IsNullOrWhiteSpace() ? "" : $"<{user.Email}>"; @@ -223,10 +223,10 @@ namespace Umbraco.Cms.Core.Handlers { var performingUser = CurrentPerformingUser; var perms = notification.EntityPermissions; - foreach (var perm in perms) + foreach (EntityPermission perm in perms) { var group = _userService.GetUserGroupById(perm.UserGroupId); - var assigned = string.Join(", ", perm?.AssignedPermissions ?? Array.Empty()); + var assigned = string.Join(", ", perm.AssignedPermissions ?? Array.Empty()); var entity = _entityService.Get(perm.EntityId); _auditService.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp, diff --git a/src/Umbraco.Core/HealthChecks/Checks/Configuration/NotificationEmailCheck.cs b/src/Umbraco.Core/HealthChecks/Checks/Configuration/NotificationEmailCheck.cs index 8d76f1cf4e..9cb5639205 100644 --- a/src/Umbraco.Core/HealthChecks/Checks/Configuration/NotificationEmailCheck.cs +++ b/src/Umbraco.Core/HealthChecks/Checks/Configuration/NotificationEmailCheck.cs @@ -46,7 +46,7 @@ namespace Umbraco.Cms.Core.HealthChecks.Checks.Configuration }; /// - public override string CurrentValue => _contentSettings.CurrentValue.Notifications.Email; + public override string CurrentValue => _contentSettings.CurrentValue.Notifications.Email ?? string.Empty; /// public override string CheckSuccessMessage => diff --git a/src/Umbraco.Core/HealthChecks/Checks/Permissions/FolderAndFilePermissionsCheck.cs b/src/Umbraco.Core/HealthChecks/Checks/Permissions/FolderAndFilePermissionsCheck.cs index 03d7dd45f6..d10dc8fedd 100644 --- a/src/Umbraco.Core/HealthChecks/Checks/Permissions/FolderAndFilePermissionsCheck.cs +++ b/src/Umbraco.Core/HealthChecks/Checks/Permissions/FolderAndFilePermissionsCheck.cs @@ -51,7 +51,7 @@ namespace Umbraco.Cms.Core.HealthChecks.Checks.Permissions })); } - private string GetErrorDescription(KeyValuePair> status) + private string? GetErrorDescription(KeyValuePair> status) { if (!status.Value.Any()) { @@ -73,7 +73,7 @@ namespace Umbraco.Cms.Core.HealthChecks.Checks.Permissions private string GetMessage(KeyValuePair> status) => _textService.Localize("permissions", status.Key); - private string GetReadMoreLink(KeyValuePair> status) + private string? GetReadMoreLink(KeyValuePair> status) { if (!status.Value.Any()) { diff --git a/src/Umbraco.Core/HealthChecks/Checks/Security/ExcessiveHeadersCheck.cs b/src/Umbraco.Core/HealthChecks/Checks/Security/ExcessiveHeadersCheck.cs index d5eac03038..dbbf6b701f 100644 --- a/src/Umbraco.Core/HealthChecks/Checks/Security/ExcessiveHeadersCheck.cs +++ b/src/Umbraco.Core/HealthChecks/Checks/Security/ExcessiveHeadersCheck.cs @@ -24,7 +24,7 @@ namespace Umbraco.Cms.Core.HealthChecks.Checks.Security { private readonly ILocalizedTextService _textService; private readonly IHostingEnvironment _hostingEnvironment; - private static HttpClient s_httpClient; + private static HttpClient? s_httpClient; /// /// Initializes a new instance of the class. @@ -65,7 +65,7 @@ namespace Umbraco.Cms.Core.HealthChecks.Checks.Security var headersToCheckFor = new List {"Server", "X-Powered-By", "X-AspNet-Version", "X-AspNetMvc-Version" }; // Ignore if server header is present and it's set to cloudflare - if (allHeaders.InvariantContains("Server") && response.Headers.TryGetValues("Server", out var serverHeaders) && serverHeaders.FirstOrDefault().InvariantEquals("cloudflare")) + if (allHeaders.InvariantContains("Server") && response.Headers.TryGetValues("Server", out var serverHeaders) && (serverHeaders.FirstOrDefault()?.InvariantEquals("cloudflare") ?? false)) { headersToCheckFor.Remove("Server"); } diff --git a/src/Umbraco.Core/HealthChecks/Checks/Security/HttpsCheck.cs b/src/Umbraco.Core/HealthChecks/Checks/Security/HttpsCheck.cs index 02c726c0c7..0b58ca4b40 100644 --- a/src/Umbraco.Core/HealthChecks/Checks/Security/HttpsCheck.cs +++ b/src/Umbraco.Core/HealthChecks/Checks/Security/HttpsCheck.cs @@ -33,7 +33,7 @@ namespace Umbraco.Cms.Core.HealthChecks.Checks.Security private readonly IOptionsMonitor _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; - private static HttpClient s_httpClient; + private static HttpClient? s_httpClient; private static HttpClient HttpClient => s_httpClient ??= new HttpClient(new HttpClientHandler() { @@ -67,7 +67,7 @@ namespace Umbraco.Cms.Core.HealthChecks.Checks.Security public override HealthCheckStatus ExecuteAction(HealthCheckAction action) => throw new InvalidOperationException("HttpsCheck action requested is either not executable or does not exist"); - private static bool ServerCertificateCustomValidation(HttpRequestMessage requestMessage, X509Certificate2 certificate, X509Chain chain, SslPolicyErrors sslErrors) + private static bool ServerCertificateCustomValidation(HttpRequestMessage requestMessage, X509Certificate2? certificate, X509Chain? chain, SslPolicyErrors sslErrors) { if (certificate is not null) { @@ -98,10 +98,10 @@ namespace Umbraco.Cms.Core.HealthChecks.Checks.Security if (response.StatusCode == HttpStatusCode.OK) { // Got a valid response, check now if the certificate is expiring within the specified amount of days - int daysToExpiry = 0; + int? daysToExpiry = 0; if (request.Properties.TryGetValue(HttpPropertyKeyCertificateDaysToExpiry, out var certificateDaysToExpiry)) { - daysToExpiry = (int)certificateDaysToExpiry; + daysToExpiry = (int?)certificateDaysToExpiry; } if (daysToExpiry <= 0) diff --git a/src/Umbraco.Core/HealthChecks/Checks/Services/SmtpCheck.cs b/src/Umbraco.Core/HealthChecks/Checks/Services/SmtpCheck.cs index bc9f7fcaba..302a5829f6 100644 --- a/src/Umbraco.Core/HealthChecks/Checks/Services/SmtpCheck.cs +++ b/src/Umbraco.Core/HealthChecks/Checks/Services/SmtpCheck.cs @@ -51,7 +51,7 @@ namespace Umbraco.Cms.Core.HealthChecks.Checks.Services { var success = false; - SmtpSettings smtpSettings = _globalSettings.CurrentValue.Smtp; + SmtpSettings? smtpSettings = _globalSettings.CurrentValue.Smtp; string message; if (smtpSettings == null) diff --git a/src/Umbraco.Core/HealthChecks/HealthCheck.cs b/src/Umbraco.Core/HealthChecks/HealthCheck.cs index 010a093ca3..59d6f912fa 100644 --- a/src/Umbraco.Core/HealthChecks/HealthCheck.cs +++ b/src/Umbraco.Core/HealthChecks/HealthCheck.cs @@ -35,10 +35,10 @@ namespace Umbraco.Cms.Core.HealthChecks public string Name { get; private set; } [DataMember(Name = "description")] - public string Description { get; private set; } + public string? Description { get; private set; } [DataMember(Name = "group")] - public string Group { get; private set; } + public string? Group { get; private set; } /// /// Get the status for this health check diff --git a/src/Umbraco.Core/HealthChecks/HealthCheckAction.cs b/src/Umbraco.Core/HealthChecks/HealthCheckAction.cs index bced91e985..06bc05f44a 100644 --- a/src/Umbraco.Core/HealthChecks/HealthCheckAction.cs +++ b/src/Umbraco.Core/HealthChecks/HealthCheckAction.cs @@ -27,7 +27,7 @@ namespace Umbraco.Cms.Core.HealthChecks /// The alias of the action - this is used by the Health Check instance to execute the action /// [DataMember(Name = "alias")] - public string Alias { get; set; } + public string? Alias { get; set; } /// /// The Id of the Health Check instance @@ -36,21 +36,21 @@ namespace Umbraco.Cms.Core.HealthChecks /// This is used to find the Health Check instance to execute this action /// [DataMember(Name = "healthCheckId")] - public Guid HealthCheckId { get; set; } + public Guid? HealthCheckId { get; set; } /// /// This could be used if the status has a custom view that specifies some parameters to be sent to the server /// when an action needs to be executed /// [DataMember(Name = "actionParameters")] - public Dictionary ActionParameters { get; set; } + public Dictionary? ActionParameters { get; set; } /// /// The name of the action - this is used to name the fix button /// [DataMember(Name = "name")] - private string _name; - public string Name + private string? _name; + public string? Name { get { return _name; } set { _name = value; } @@ -60,7 +60,7 @@ namespace Umbraco.Cms.Core.HealthChecks /// The description of the action - this is used to give a description before executing the action /// [DataMember(Name = "description")] - public string Description { get; set; } + public string? Description { get; set; } /// /// Indicates if a value is required to rectify the issue @@ -72,18 +72,18 @@ namespace Umbraco.Cms.Core.HealthChecks /// Indicates if a value required, how it is validated /// [DataMember(Name = "providedValueValidation")] - public string ProvidedValueValidation { get; set; } + public string? ProvidedValueValidation { get; set; } /// /// Indicates if a value required, and is validated by a regex, what the regex to use is /// [DataMember(Name = "providedValueValidationRegex")] - public string ProvidedValueValidationRegex { get; set; } + public string? ProvidedValueValidationRegex { get; set; } /// /// Provides a value to rectify the issue /// [DataMember(Name = "providedValue")] - public string ProvidedValue { get; set; } + public string? ProvidedValue { get; set; } } } diff --git a/src/Umbraco.Core/HealthChecks/HealthCheckAttribute.cs b/src/Umbraco.Core/HealthChecks/HealthCheckAttribute.cs index 596d41c372..0fa6647971 100644 --- a/src/Umbraco.Core/HealthChecks/HealthCheckAttribute.cs +++ b/src/Umbraco.Core/HealthChecks/HealthCheckAttribute.cs @@ -15,9 +15,9 @@ namespace Umbraco.Cms.Core.HealthChecks } public string Name { get; private set; } - public string Description { get; set; } + public string? Description { get; set; } - public string Group { get; set; } + public string? Group { get; set; } public Guid Id { get; private set; } diff --git a/src/Umbraco.Core/HealthChecks/HealthCheckResults.cs b/src/Umbraco.Core/HealthChecks/HealthCheckResults.cs index dd073f32f5..bde90627c7 100644 --- a/src/Umbraco.Core/HealthChecks/HealthCheckResults.cs +++ b/src/Umbraco.Core/HealthChecks/HealthCheckResults.cs @@ -138,7 +138,7 @@ namespace Umbraco.Cms.Core.HealthChecks .Replace("", "*"); } - public Dictionary> GetResultsForStatus(StatusResultType resultType) + public Dictionary>? GetResultsForStatus(StatusResultType resultType) { switch (resultType) { diff --git a/src/Umbraco.Core/HealthChecks/HealthCheckStatus.cs b/src/Umbraco.Core/HealthChecks/HealthCheckStatus.cs index fc787803d2..49428fe899 100644 --- a/src/Umbraco.Core/HealthChecks/HealthCheckStatus.cs +++ b/src/Umbraco.Core/HealthChecks/HealthCheckStatus.cs @@ -27,7 +27,7 @@ namespace Umbraco.Cms.Core.HealthChecks /// The status description if one is necessary /// [DataMember(Name = "description")] - public string Description { get; set; } + public string? Description { get; set; } /// /// This is optional but would allow a developer to specify a path to an angular HTML view @@ -35,7 +35,7 @@ namespace Umbraco.Cms.Core.HealthChecks /// to configure how an action is executed /// [DataMember(Name = "view")] - public string View { get; set; } + public string? View { get; set; } /// /// The status type @@ -53,6 +53,6 @@ namespace Umbraco.Cms.Core.HealthChecks /// This is optional but would allow a developer to specify a link that is shown as a "read more" button. /// [DataMember(Name = "readMoreLink")] - public string ReadMoreLink { get; set; } + public string? ReadMoreLink { get; set; } } } diff --git a/src/Umbraco.Core/HealthChecks/NotificationMethods/EmailNotificationMethod.cs b/src/Umbraco.Core/HealthChecks/NotificationMethods/EmailNotificationMethod.cs index de6df973e3..94867d8882 100644 --- a/src/Umbraco.Core/HealthChecks/NotificationMethods/EmailNotificationMethod.cs +++ b/src/Umbraco.Core/HealthChecks/NotificationMethods/EmailNotificationMethod.cs @@ -13,11 +13,11 @@ namespace Umbraco.Cms.Core.HealthChecks.NotificationMethods [HealthCheckNotificationMethod("email")] public class EmailNotificationMethod : NotificationMethodBase { - private readonly ILocalizedTextService _textService; - private readonly IHostingEnvironment _hostingEnvironment; - private readonly IEmailSender _emailSender; - private readonly IMarkdownToHtmlConverter _markdownToHtmlConverter; - private ContentSettings _contentSettings; + private readonly ILocalizedTextService? _textService; + private readonly IHostingEnvironment? _hostingEnvironment; + private readonly IEmailSender? _emailSender; + private readonly IMarkdownToHtmlConverter? _markdownToHtmlConverter; + private ContentSettings? _contentSettings; public EmailNotificationMethod( ILocalizedTextService textService, @@ -46,7 +46,7 @@ namespace Umbraco.Cms.Core.HealthChecks.NotificationMethods contentSettings.OnChange(x => _contentSettings = x); } - public string RecipientEmail { get; } + public string? RecipientEmail { get; } public override async Task SendAsync(HealthCheckResults results) { @@ -60,32 +60,36 @@ namespace Umbraco.Cms.Core.HealthChecks.NotificationMethods return; } - var message = _textService.Localize("healthcheck","scheduledHealthCheckEmailBody", new[] + var message = _textService?.Localize("healthcheck","scheduledHealthCheckEmailBody", new[] { DateTime.Now.ToShortDateString(), DateTime.Now.ToShortTimeString(), - _markdownToHtmlConverter.ToHtml(results, Verbosity) + _markdownToHtmlConverter?.ToHtml(results, Verbosity) }); // Include the umbraco Application URL host in the message subject so that // you can identify the site that these results are for. - var host = _hostingEnvironment.ApplicationMainUrl?.ToString(); + var host = _hostingEnvironment?.ApplicationMainUrl?.ToString(); - var subject = _textService.Localize("healthcheck","scheduledHealthCheckEmailSubject", new[] { host }); + var subject = _textService?.Localize("healthcheck","scheduledHealthCheckEmailSubject", new[] { host }); var mailMessage = CreateMailMessage(subject, message); - await _emailSender.SendAsync(mailMessage, Constants.Web.EmailTypes.HealthCheck); + Task? task = _emailSender?.SendAsync(mailMessage, Constants.Web.EmailTypes.HealthCheck); + if (task is not null) + { + await task; + } } - private EmailMessage CreateMailMessage(string subject, string message) + private EmailMessage CreateMailMessage(string? subject, string? message) { - var to = _contentSettings.Notifications.Email; + var to = _contentSettings?.Notifications.Email; if (string.IsNullOrWhiteSpace(subject)) subject = "Umbraco Health Check Status"; - var isBodyHtml = message.IsNullOrWhiteSpace() == false && message.Contains("<") && message.Contains(" Settings { get; } + public IDictionary? Settings { get; } protected bool ShouldSend(HealthCheckResults results) { diff --git a/src/Umbraco.Core/IO/CleanFolderResult.cs b/src/Umbraco.Core/IO/CleanFolderResult.cs index a49c9a5b0c..d2bed317a6 100644 --- a/src/Umbraco.Core/IO/CleanFolderResult.cs +++ b/src/Umbraco.Core/IO/CleanFolderResult.cs @@ -12,7 +12,7 @@ namespace Umbraco.Cms.Core.IO public CleanFolderResultStatus Status { get; private set; } - public IReadOnlyCollection Errors { get; private set; } + public IReadOnlyCollection? Errors { get; private set; } public static CleanFolderResult Success() { diff --git a/src/Umbraco.Core/IO/DefaultViewContentProvider.cs b/src/Umbraco.Core/IO/DefaultViewContentProvider.cs index 7c42255971..e78118da62 100644 --- a/src/Umbraco.Core/IO/DefaultViewContentProvider.cs +++ b/src/Umbraco.Core/IO/DefaultViewContentProvider.cs @@ -5,7 +5,7 @@ namespace Umbraco.Cms.Core.IO { public class DefaultViewContentProvider : IDefaultViewContentProvider { - public string GetDefaultFileContent(string layoutPageAlias = null, string modelClassName = null, string modelNamespace = null, string modelNamespaceAlias = null) + public string GetDefaultFileContent(string? layoutPageAlias = null, string? modelClassName = null, string? modelNamespace = null, string? modelNamespaceAlias = null) { var content = new StringBuilder(); diff --git a/src/Umbraco.Core/IO/FileSystemExtensions.cs b/src/Umbraco.Core/IO/FileSystemExtensions.cs index 23be195e4b..fce1b36801 100644 --- a/src/Umbraco.Core/IO/FileSystemExtensions.cs +++ b/src/Umbraco.Core/IO/FileSystemExtensions.cs @@ -60,9 +60,13 @@ namespace Umbraco.Extensions public static void CopyFile(this IFileSystem fs, string path, string newPath) { - using (var stream = fs.OpenFile(path)) + using (Stream? stream = fs.OpenFile(path)) { - fs.AddFile(newPath, stream); + if (stream is not null) + { + fs.AddFile(newPath, stream); + } + } } diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs index 1b4db6acec..5a4c92d509 100644 --- a/src/Umbraco.Core/IO/FileSystems.cs +++ b/src/Umbraco.Core/IO/FileSystems.cs @@ -22,21 +22,21 @@ namespace Umbraco.Cms.Core.IO // wrappers for shadow support - private ShadowWrapper _macroPartialFileSystem; - private ShadowWrapper _partialViewsFileSystem; - private ShadowWrapper _stylesheetsFileSystem; - private ShadowWrapper _scriptsFileSystem; - private ShadowWrapper _mvcViewsFileSystem; + private ShadowWrapper? _macroPartialFileSystem; + private ShadowWrapper? _partialViewsFileSystem; + private ShadowWrapper? _stylesheetsFileSystem; + private ShadowWrapper? _scriptsFileSystem; + private ShadowWrapper? _mvcViewsFileSystem; // well-known file systems lazy initialization private object _wkfsLock = new object(); private bool _wkfsInitialized; - private object _wkfsObject; // unused + private object? _wkfsObject; // unused // shadow support private readonly List _shadowWrappers = new List(); private readonly object _shadowLocker = new object(); - private static string _shadowCurrentId; // static - unique!! + private static string? _shadowCurrentId; // static - unique!! #region Constructor // DI wants a public ctor @@ -79,7 +79,7 @@ namespace Umbraco.Cms.Core.IO /// Used be Scope provider to take control over the filesystems, should never be used for anything else. /// [EditorBrowsable(EditorBrowsableState.Never)] - public Func IsScoped { get; set; } = () => false; + public Func? IsScoped { get; set; } = () => false; #endregion @@ -88,7 +88,7 @@ namespace Umbraco.Cms.Core.IO /// /// Gets the macro partials filesystem. /// - public IFileSystem MacroPartialsFileSystem + public IFileSystem? MacroPartialsFileSystem { get { @@ -104,7 +104,7 @@ namespace Umbraco.Cms.Core.IO /// /// Gets the partial views filesystem. /// - public IFileSystem PartialViewsFileSystem + public IFileSystem? PartialViewsFileSystem { get { @@ -120,7 +120,7 @@ namespace Umbraco.Cms.Core.IO /// /// Gets the stylesheets filesystem. /// - public IFileSystem StylesheetsFileSystem + public IFileSystem? StylesheetsFileSystem { get { @@ -136,7 +136,7 @@ namespace Umbraco.Cms.Core.IO /// /// Gets the scripts filesystem. /// - public IFileSystem ScriptsFileSystem + public IFileSystem? ScriptsFileSystem { get { @@ -152,7 +152,7 @@ namespace Umbraco.Cms.Core.IO /// /// Gets the MVC views filesystem. /// - public IFileSystem MvcViewsFileSystem + public IFileSystem? MvcViewsFileSystem { get { @@ -211,7 +211,7 @@ namespace Umbraco.Cms.Core.IO // need to return something to LazyInitializer.EnsureInitialized // but it does not really matter what we return - here, null - private object CreateWellKnownFileSystems() + private object? CreateWellKnownFileSystems() { var logger = _loggerFactory.CreateLogger(); @@ -345,7 +345,7 @@ namespace Umbraco.Cms.Core.IO { lock (_shadowLocker) { - var wrapper = new ShadowWrapper(filesystem, _ioHelper, _hostingEnvironment, _loggerFactory, shadowPath,() => IsScoped()); + var wrapper = new ShadowWrapper(filesystem, _ioHelper, _hostingEnvironment, _loggerFactory, shadowPath,() => IsScoped?.Invoke()); if (_shadowCurrentId != null) { wrapper.Shadow(_shadowCurrentId); diff --git a/src/Umbraco.Core/IO/IDefaultViewContentProvider.cs b/src/Umbraco.Core/IO/IDefaultViewContentProvider.cs index 8c1a775d7c..a2937f3f8e 100644 --- a/src/Umbraco.Core/IO/IDefaultViewContentProvider.cs +++ b/src/Umbraco.Core/IO/IDefaultViewContentProvider.cs @@ -2,7 +2,7 @@ namespace Umbraco.Cms.Core.IO { public interface IDefaultViewContentProvider { - string GetDefaultFileContent(string layoutPageAlias = null, string modelClassName = null, - string modelNamespace = null, string modelNamespaceAlias = null); + string GetDefaultFileContent(string? layoutPageAlias = null, string? modelClassName = null, + string? modelNamespace = null, string? modelNamespaceAlias = null); } } diff --git a/src/Umbraco.Core/IO/IFileSystem.cs b/src/Umbraco.Core/IO/IFileSystem.cs index 281ffd0e14..53c37dbe05 100644 --- a/src/Umbraco.Core/IO/IFileSystem.cs +++ b/src/Umbraco.Core/IO/IFileSystem.cs @@ -82,7 +82,7 @@ namespace Umbraco.Cms.Core.IO /// /// . /// - Stream OpenFile(string path); + Stream? OpenFile(string path); /// /// Deletes the specified file. diff --git a/src/Umbraco.Core/IO/IMediaPathScheme.cs b/src/Umbraco.Core/IO/IMediaPathScheme.cs index 5daf5490a8..da9a06d1b1 100644 --- a/src/Umbraco.Core/IO/IMediaPathScheme.cs +++ b/src/Umbraco.Core/IO/IMediaPathScheme.cs @@ -14,7 +14,7 @@ namespace Umbraco.Cms.Core.IO /// The (content, media) item unique identifier. /// The property type unique identifier. /// The file name. - /// + /// /// The filesystem-relative complete file path. string GetFilePath(MediaFileManager fileManager, Guid itemGuid, Guid propertyGuid, string filename); @@ -28,6 +28,6 @@ namespace Umbraco.Cms.Core.IO /// The directory, and anything below it, will be deleted. /// Can return null (or empty) when no directory should be deleted. /// - string GetDeleteDirectory(MediaFileManager fileSystem, string filepath); + string? GetDeleteDirectory(MediaFileManager fileSystem, string filepath); } } diff --git a/src/Umbraco.Core/IO/IViewHelper.cs b/src/Umbraco.Core/IO/IViewHelper.cs index d53dcbf2b9..19805a0fad 100644 --- a/src/Umbraco.Core/IO/IViewHelper.cs +++ b/src/Umbraco.Core/IO/IViewHelper.cs @@ -7,7 +7,7 @@ namespace Umbraco.Cms.Core.IO bool ViewExists(ITemplate t); string GetFileContents(ITemplate t); string CreateView(ITemplate t, bool overWrite = false); - string UpdateViewFile(ITemplate t, string currentAlias = null); + string UpdateViewFile(ITemplate t, string? currentAlias = null); string ViewPath(string alias); } } diff --git a/src/Umbraco.Core/IO/MediaFileManager.cs b/src/Umbraco.Core/IO/MediaFileManager.cs index 3754b8d076..73a451f118 100644 --- a/src/Umbraco.Core/IO/MediaFileManager.cs +++ b/src/Umbraco.Core/IO/MediaFileManager.cs @@ -75,7 +75,7 @@ namespace Umbraco.Cms.Core.IO var directory = _mediaPathScheme.GetDeleteDirectory(this, file); if (!directory.IsNullOrWhiteSpace()) { - FileSystem.DeleteDirectory(directory, true); + FileSystem.DeleteDirectory(directory!, true); } } catch (Exception e) @@ -138,7 +138,7 @@ namespace Umbraco.Cms.Core.IO return null; } - Stream stream = FileSystem.OpenFile(mediaFilePath!); + Stream? stream = FileSystem.OpenFile(mediaFilePath!); if (stream != null) { return stream; diff --git a/src/Umbraco.Core/IO/MediaPathSchemes/CombinedGuidsMediaPathScheme.cs b/src/Umbraco.Core/IO/MediaPathSchemes/CombinedGuidsMediaPathScheme.cs index b4127e080d..5adc81276b 100644 --- a/src/Umbraco.Core/IO/MediaPathSchemes/CombinedGuidsMediaPathScheme.cs +++ b/src/Umbraco.Core/IO/MediaPathSchemes/CombinedGuidsMediaPathScheme.cs @@ -23,6 +23,6 @@ namespace Umbraco.Cms.Core.IO.MediaPathSchemes } /// - public string GetDeleteDirectory(MediaFileManager fileSystem, string filepath) => Path.GetDirectoryName(filepath); + public string GetDeleteDirectory(MediaFileManager fileSystem, string filepath) => Path.GetDirectoryName(filepath)!; } } diff --git a/src/Umbraco.Core/IO/MediaPathSchemes/TwoGuidsMediaPathScheme.cs b/src/Umbraco.Core/IO/MediaPathSchemes/TwoGuidsMediaPathScheme.cs index ebce899697..1ee821e3ed 100644 --- a/src/Umbraco.Core/IO/MediaPathSchemes/TwoGuidsMediaPathScheme.cs +++ b/src/Umbraco.Core/IO/MediaPathSchemes/TwoGuidsMediaPathScheme.cs @@ -20,7 +20,7 @@ namespace Umbraco.Cms.Core.IO.MediaPathSchemes /// public string GetDeleteDirectory(MediaFileManager fileManager, string filepath) { - return Path.GetDirectoryName(filepath); + return Path.GetDirectoryName(filepath)!; } } } diff --git a/src/Umbraco.Core/IO/MediaPathSchemes/UniqueMediaPathScheme.cs b/src/Umbraco.Core/IO/MediaPathSchemes/UniqueMediaPathScheme.cs index c247c37032..a3fe36bde9 100644 --- a/src/Umbraco.Core/IO/MediaPathSchemes/UniqueMediaPathScheme.cs +++ b/src/Umbraco.Core/IO/MediaPathSchemes/UniqueMediaPathScheme.cs @@ -32,6 +32,6 @@ namespace Umbraco.Cms.Core.IO.MediaPathSchemes /// race conditions. We'd need to implement locks in for /// this. /// - public string GetDeleteDirectory(MediaFileManager fileManager, string filepath) => null; + public string? GetDeleteDirectory(MediaFileManager fileManager, string filepath) => null; } } diff --git a/src/Umbraco.Core/IO/ShadowFileSystem.cs b/src/Umbraco.Core/IO/ShadowFileSystem.cs index cc4e792d98..b921445663 100644 --- a/src/Umbraco.Core/IO/ShadowFileSystem.cs +++ b/src/Umbraco.Core/IO/ShadowFileSystem.cs @@ -37,8 +37,13 @@ namespace Umbraco.Cms.Core.IO } else { - using (var stream = _sfs.OpenFile(kvp.Key)) - _fs.AddFile(kvp.Key, stream, true); + using (Stream? stream = _sfs.OpenFile(kvp.Key)) + { + if (stream is not null) + { + _fs.AddFile(kvp.Key, stream, true); + } + } } } catch (Exception e) @@ -68,7 +73,7 @@ namespace Umbraco.Cms.Core.IO throw new AggregateException("Failed to apply all changes (see exceptions).", exceptions); } - private Dictionary _nodes; + private Dictionary? _nodes; private Dictionary Nodes => _nodes ?? (_nodes = new Dictionary()); @@ -164,7 +169,7 @@ namespace Umbraco.Cms.Core.IO public bool DirectoryExists(string path) { - ShadowNode sf; + ShadowNode? sf; if (Nodes.TryGetValue(NormPath(path), out sf)) return sf.IsDir && sf.IsExist; return _fs.DirectoryExists(path); @@ -177,7 +182,7 @@ namespace Umbraco.Cms.Core.IO public void AddFile(string path, Stream stream, bool overrideIfExists) { - ShadowNode sf; + ShadowNode? sf; var normPath = NormPath(path); if (Nodes.TryGetValue(normPath, out sf) && sf.IsExist && (sf.IsDir || overrideIfExists == false)) throw new InvalidOperationException(string.Format("A file at path '{0}' already exists", path)); @@ -186,7 +191,7 @@ namespace Umbraco.Cms.Core.IO for (var i = 0; i < parts.Length - 1; i++) { var dirPath = string.Join("/", parts.Take(i + 1)); - ShadowNode sd; + ShadowNode? sd; if (Nodes.TryGetValue(dirPath, out sd)) { if (sd.IsFile) throw new InvalidOperationException("Invalid path."); @@ -209,7 +214,7 @@ namespace Umbraco.Cms.Core.IO return GetFiles(path, null); } - public IEnumerable GetFiles(string path, string filter) + public IEnumerable GetFiles(string path, string? filter) { var normPath = NormPath(path); var shadows = Nodes.Where(kvp => IsChild(normPath, kvp.Key)).ToArray(); @@ -222,9 +227,9 @@ namespace Umbraco.Cms.Core.IO .Distinct(); } - public Stream OpenFile(string path) + public Stream? OpenFile(string path) { - ShadowNode sf; + ShadowNode? sf; if (Nodes.TryGetValue(NormPath(path), out sf)) return sf.IsDir || sf.IsDelete ? null : _sfs.OpenFile(path); return _fs.OpenFile(path); @@ -238,7 +243,7 @@ namespace Umbraco.Cms.Core.IO public bool FileExists(string path) { - ShadowNode sf; + ShadowNode? sf; if (Nodes.TryGetValue(NormPath(path), out sf)) return sf.IsFile && sf.IsExist; return _fs.FileExists(path); @@ -251,9 +256,9 @@ namespace Umbraco.Cms.Core.IO public string GetFullPath(string path) { - ShadowNode sf; + ShadowNode? sf; if (Nodes.TryGetValue(NormPath(path), out sf)) - return sf.IsDir || sf.IsDelete ? null : _sfs.GetFullPath(path); + return sf.IsDir || sf.IsDelete ? string.Empty : _sfs.GetFullPath(path); return _fs.GetFullPath(path); } @@ -264,7 +269,7 @@ namespace Umbraco.Cms.Core.IO public DateTimeOffset GetLastModified(string path) { - ShadowNode sf; + ShadowNode? sf; if (Nodes.TryGetValue(NormPath(path), out sf) == false) return _fs.GetLastModified(path); if (sf.IsDelete) throw new InvalidOperationException("Invalid path."); return _sfs.GetLastModified(path); @@ -272,7 +277,7 @@ namespace Umbraco.Cms.Core.IO public DateTimeOffset GetCreated(string path) { - ShadowNode sf; + ShadowNode? sf; if (Nodes.TryGetValue(NormPath(path), out sf) == false) return _fs.GetCreated(path); if (sf.IsDelete) throw new InvalidOperationException("Invalid path."); return _sfs.GetCreated(path); @@ -280,7 +285,7 @@ namespace Umbraco.Cms.Core.IO public long GetSize(string path) { - ShadowNode sf; + ShadowNode? sf; if (Nodes.TryGetValue(NormPath(path), out sf) == false) return _fs.GetSize(path); @@ -292,7 +297,7 @@ namespace Umbraco.Cms.Core.IO public void AddFile(string path, string physicalPath, bool overrideIfExists = true, bool copy = false) { - ShadowNode sf; + ShadowNode? sf; var normPath = NormPath(path); if (Nodes.TryGetValue(normPath, out sf) && sf.IsExist && (sf.IsDir || overrideIfExists == false)) throw new InvalidOperationException(string.Format("A file at path '{0}' already exists", path)); @@ -301,7 +306,7 @@ namespace Umbraco.Cms.Core.IO for (var i = 0; i < parts.Length - 1; i++) { var dirPath = string.Join("/", parts.Take(i + 1)); - ShadowNode sd; + ShadowNode? sd; if (Nodes.TryGetValue(dirPath, out sd)) { if (sd.IsFile) throw new InvalidOperationException("Invalid path."); @@ -324,7 +329,7 @@ namespace Umbraco.Cms.Core.IO { private readonly string _pattern; private readonly bool _caseInsensitive; - private Regex _regex; + private Regex? _regex; private static Regex metaRegex = new Regex("[\\+\\{\\\\\\[\\|\\(\\)\\.\\^\\$]"); private static Regex questRegex = new Regex("\\?"); @@ -375,7 +380,7 @@ namespace Umbraco.Cms.Core.IO public bool IsMatch(string input) { EnsureRegex(_pattern); - return _regex.IsMatch(input); + return _regex?.IsMatch(input) ?? false; } } } diff --git a/src/Umbraco.Core/IO/ShadowWrapper.cs b/src/Umbraco.Core/IO/ShadowWrapper.cs index cda61cf7b5..408b64959c 100644 --- a/src/Umbraco.Core/IO/ShadowWrapper.cs +++ b/src/Umbraco.Core/IO/ShadowWrapper.cs @@ -12,16 +12,16 @@ namespace Umbraco.Cms.Core.IO { private static readonly string ShadowFsPath = Constants.SystemDirectories.TempData.EnsureEndsWith('/') + "ShadowFs"; - private readonly Func _isScoped; + private readonly Func? _isScoped; private readonly IFileSystem _innerFileSystem; private readonly string _shadowPath; - private ShadowFileSystem _shadowFileSystem; - private string _shadowDir; + private ShadowFileSystem? _shadowFileSystem; + private string? _shadowDir; private readonly IIOHelper _ioHelper; private readonly IHostingEnvironment _hostingEnvironment; private readonly ILoggerFactory _loggerFactory; - public ShadowWrapper(IFileSystem innerFileSystem, IIOHelper ioHelper, IHostingEnvironment hostingEnvironment, ILoggerFactory loggerFactory, string shadowPath, Func isScoped = null) + public ShadowWrapper(IFileSystem innerFileSystem, IIOHelper ioHelper, IHostingEnvironment hostingEnvironment, ILoggerFactory loggerFactory, string shadowPath, Func? isScoped = null) { _innerFileSystem = innerFileSystem; _ioHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper)); @@ -80,17 +80,17 @@ namespace Umbraco.Cms.Core.IO try { // this may throw an AggregateException if some of the changes could not be applied - if (complete) shadowFileSystem.Complete(); + if (complete) shadowFileSystem?.Complete(); } finally { // in any case, cleanup try { - Directory.Delete(dir, true); + Directory.Delete(dir!, true); // shadowPath make be path/to/dir, remove each - dir = dir.Replace('/', Path.DirectorySeparatorChar); + dir = dir!.Replace('/', Path.DirectorySeparatorChar); var min = _hostingEnvironment.MapPathContentRoot(ShadowFsPath).Length; var pos = dir.LastIndexOf(Path.DirectorySeparatorChar); while (pos > min) @@ -116,16 +116,21 @@ namespace Umbraco.Cms.Core.IO { get { - var isScoped = _isScoped(); + if (_isScoped is not null && _shadowFileSystem is not null) + { + var isScoped = _isScoped!(); - // if the filesystem is created *after* shadowing starts, it won't be shadowing - // better not ignore that situation and raised a meaningful (?) exception - if (isScoped && _shadowFileSystem == null) - throw new Exception("The filesystems are shadowing, but this filesystem is not."); + // if the filesystem is created *after* shadowing starts, it won't be shadowing + // better not ignore that situation and raised a meaningful (?) exception + if ( isScoped.HasValue && isScoped.Value && _shadowFileSystem == null) + throw new Exception("The filesystems are shadowing, but this filesystem is not."); - return isScoped - ? _shadowFileSystem - : _innerFileSystem; + return isScoped.HasValue && isScoped.Value + ? _shadowFileSystem + : _innerFileSystem; + } + + return _innerFileSystem; } } @@ -169,7 +174,7 @@ namespace Umbraco.Cms.Core.IO return FileSystem.GetFiles(path, filter); } - public Stream OpenFile(string path) + public Stream? OpenFile(string path) { return FileSystem.OpenFile(path); } diff --git a/src/Umbraco.Core/IO/ViewHelper.cs b/src/Umbraco.Core/IO/ViewHelper.cs index 56a2760802..85401e6f12 100644 --- a/src/Umbraco.Core/IO/ViewHelper.cs +++ b/src/Umbraco.Core/IO/ViewHelper.cs @@ -28,7 +28,7 @@ namespace Umbraco.Cms.Core.IO } public bool ViewExists(ITemplate t) => _viewFileSystem.FileExists(ViewPath(t.Alias)); - + public string GetFileContents(ITemplate t) { @@ -37,7 +37,7 @@ namespace Umbraco.Cms.Core.IO if (_viewFileSystem.FileExists(path)) { - using (var tr = new StreamReader(_viewFileSystem.OpenFile(path))) + using (var tr = new StreamReader(_viewFileSystem.OpenFile(path)!)) { viewContent = tr.ReadToEnd(); tr.Close(); @@ -58,7 +58,7 @@ namespace Umbraco.Cms.Core.IO } else { - using (var tr = new StreamReader(_viewFileSystem.OpenFile(path))) + using (var tr = new StreamReader(_viewFileSystem.OpenFile(path)!)) { viewContent = tr.ReadToEnd(); tr.Close(); @@ -69,8 +69,8 @@ namespace Umbraco.Cms.Core.IO } [Obsolete("Inject IDefaultViewContentProvider instead")] - public static string GetDefaultFileContent(string layoutPageAlias = null, string modelClassName = null, - string modelNamespace = null, string modelNamespaceAlias = null) + public static string GetDefaultFileContent(string? layoutPageAlias = null, string? modelClassName = null, + string? modelNamespace = null, string? modelNamespaceAlias = null) { var viewContentProvider = StaticServiceProvider.Instance.GetRequiredService(); return viewContentProvider.GetDefaultFileContent(layoutPageAlias, modelClassName, modelNamespace, @@ -93,7 +93,7 @@ namespace Umbraco.Cms.Core.IO return design; } - public string UpdateViewFile(ITemplate t, string currentAlias = null) + public string UpdateViewFile(ITemplate t, string? currentAlias = null) { var path = ViewPath(t.Alias); diff --git a/src/Umbraco.Core/Install/InstallException.cs b/src/Umbraco.Core/Install/InstallException.cs index c21359e953..2ec741d200 100644 --- a/src/Umbraco.Core/Install/InstallException.cs +++ b/src/Umbraco.Core/Install/InstallException.cs @@ -16,7 +16,7 @@ namespace Umbraco.Cms.Core.Install /// /// The view. /// - public string View { get; private set; } + public string? View { get; private set; } /// /// Gets the view model. @@ -27,7 +27,7 @@ namespace Umbraco.Cms.Core.Install /// /// This object is not included when serializing. /// - public object ViewModel { get; private set; } + public object? ViewModel { get; private set; } /// /// Initializes a new instance of the class. @@ -58,7 +58,7 @@ namespace Umbraco.Cms.Core.Install /// The message. /// The view. /// The view model. - public InstallException(string message, string view, object viewModel) + public InstallException(string message, string view, object? viewModel) : base(message) { View = view; diff --git a/src/Umbraco.Core/Install/InstallStatusTracker.cs b/src/Umbraco.Core/Install/InstallStatusTracker.cs index 9f069c3081..43e2f477a4 100644 --- a/src/Umbraco.Core/Install/InstallStatusTracker.cs +++ b/src/Umbraco.Core/Install/InstallStatusTracker.cs @@ -105,7 +105,7 @@ namespace Umbraco.Cms.Core.Install } //save the file var serialized = _jsonSerializer.Serialize(new List(_steps)); - Directory.CreateDirectory(Path.GetDirectoryName(file)); + Directory.CreateDirectory(Path.GetDirectoryName(file)!); File.WriteAllText(file, serialized); } } @@ -119,7 +119,7 @@ namespace Umbraco.Cms.Core.Install //save the correct file var serialized = _jsonSerializer.Serialize(new List(_steps)); - Directory.CreateDirectory(Path.GetDirectoryName(file)); + Directory.CreateDirectory(Path.GetDirectoryName(file)!); File.WriteAllText(file, serialized); } } diff --git a/src/Umbraco.Core/Install/InstallSteps/FilePermissionsStep.cs b/src/Umbraco.Core/Install/InstallSteps/FilePermissionsStep.cs index 5b7d91468f..14d77ecb77 100644 --- a/src/Umbraco.Core/Install/InstallSteps/FilePermissionsStep.cs +++ b/src/Umbraco.Core/Install/InstallSteps/FilePermissionsStep.cs @@ -36,7 +36,7 @@ namespace Umbraco.Cms.Core.Install.InstallSteps } /// - public override Task ExecuteAsync(object model) + public override Task ExecuteAsync(object model) { // validate file permissions var permissionsOk = _filePermissionHelper.RunFilePermissionTestSuite(out Dictionary> report); @@ -47,7 +47,7 @@ namespace Umbraco.Cms.Core.Install.InstallSteps throw new InstallException("Permission check failed", "permissionsreport", new { errors = translatedErrors }); } - return Task.FromResult(null); + return Task.FromResult(null); } /// diff --git a/src/Umbraco.Core/Install/InstallSteps/TelemetryIdentifierStep.cs b/src/Umbraco.Core/Install/InstallSteps/TelemetryIdentifierStep.cs index 37769afc53..6f4cd87bd9 100644 --- a/src/Umbraco.Core/Install/InstallSteps/TelemetryIdentifierStep.cs +++ b/src/Umbraco.Core/Install/InstallSteps/TelemetryIdentifierStep.cs @@ -24,7 +24,7 @@ namespace Umbraco.Cms.Core.Install.InstallSteps _configManipulator = configManipulator; } - public override Task ExecuteAsync(object model) + public override Task ExecuteAsync(object model) { // Generate GUID var telemetrySiteIdentifier = Guid.NewGuid(); @@ -38,7 +38,7 @@ namespace Umbraco.Cms.Core.Install.InstallSteps _logger.LogError(ex, "Couldn't update config files with a telemetry site identifier"); } - return Task.FromResult(null); + return Task.FromResult(null); } public override bool RequiresExecution(object model) diff --git a/src/Umbraco.Core/Install/InstallSteps/UpgradeStep.cs b/src/Umbraco.Core/Install/InstallSteps/UpgradeStep.cs index e0e5c1ab6a..93290cc249 100644 --- a/src/Umbraco.Core/Install/InstallSteps/UpgradeStep.cs +++ b/src/Umbraco.Core/Install/InstallSteps/UpgradeStep.cs @@ -23,7 +23,7 @@ namespace Umbraco.Cms.Core.Install.InstallSteps _runtimeState = runtimeState; } - public override Task ExecuteAsync(object model) => Task.FromResult(null); + public override Task ExecuteAsync(object model) => Task.FromResult(null); public override object ViewModel { @@ -39,8 +39,8 @@ namespace Umbraco.Cms.Core.Install.InstallSteps var currentState = FormatGuidState(_runtimeState.CurrentMigrationState); var newState = FormatGuidState(_runtimeState.FinalMigrationState); - var newVersion = _umbracoVersion.SemanticVersion.ToSemanticStringWithoutBuild(); - var oldVersion = new SemVersion(_umbracoVersion.SemanticVersion.Major, 0, 0).ToString(); //TODO can we find the old version somehow? e.g. from current state + var newVersion = _umbracoVersion.SemanticVersion?.ToSemanticStringWithoutBuild(); + var oldVersion = new SemVersion(_umbracoVersion.SemanticVersion?.Major ?? 0, 0, 0).ToString(); //TODO can we find the old version somehow? e.g. from current state var reportUrl = $"https://our.umbraco.com/contribute/releases/compare?from={oldVersion}&to={newVersion}¬es=1"; diff --git a/src/Umbraco.Core/Install/Models/InstallSetupResult.cs b/src/Umbraco.Core/Install/Models/InstallSetupResult.cs index 071857193f..15a4c12b47 100644 --- a/src/Umbraco.Core/Install/Models/InstallSetupResult.cs +++ b/src/Umbraco.Core/Install/Models/InstallSetupResult.cs @@ -11,7 +11,7 @@ namespace Umbraco.Cms.Core.Install.Models { } - public InstallSetupResult(IDictionary savedStepData, string view, object viewModel = null) + public InstallSetupResult(IDictionary savedStepData, string view, object? viewModel = null) { ViewModel = viewModel; SavedStepData = savedStepData; @@ -23,7 +23,7 @@ namespace Umbraco.Cms.Core.Install.Models SavedStepData = savedStepData; } - public InstallSetupResult(string view, object viewModel = null) + public InstallSetupResult(string view, object? viewModel = null) { ViewModel = viewModel; View = view; @@ -32,16 +32,16 @@ namespace Umbraco.Cms.Core.Install.Models /// /// Data that is persisted to the installation file which can be used from other installation steps /// - public IDictionary SavedStepData { get; private set; } + public IDictionary? SavedStepData { get; private set; } /// /// The UI view to show when this step executes, by default no views are shown for the completion of a step unless explicitly specified. /// - public string View { get; private set; } + public string? View { get; private set; } /// /// The view model to return to the UI if this step is returning a view (optional) /// - public object ViewModel { get; private set; } + public object? ViewModel { get; private set; } } } diff --git a/src/Umbraco.Core/Install/Models/InstallSetupStep.cs b/src/Umbraco.Core/Install/Models/InstallSetupStep.cs index 8bfe1d75ec..766458f99f 100644 --- a/src/Umbraco.Core/Install/Models/InstallSetupStep.cs +++ b/src/Umbraco.Core/Install/Models/InstallSetupStep.cs @@ -22,7 +22,7 @@ namespace Umbraco.Cms.Core.Install.Models /// /// /// - public abstract Task ExecuteAsync(T model); + public abstract Task ExecuteAsync(T model); /// /// Determines if this step needs to execute based on the current state of the application and/or install process @@ -59,7 +59,7 @@ namespace Umbraco.Cms.Core.Install.Models /// The view model used to render the view, by default is null but can be populated /// [DataMember(Name = "model")] - public virtual object ViewModel { get; private set; } + public virtual object? ViewModel { get; private set; } [DataMember(Name = "description")] public string Description { get; private set; } diff --git a/src/Umbraco.Core/Install/Models/InstallTrackingItem.cs b/src/Umbraco.Core/Install/Models/InstallTrackingItem.cs index 48ad91abed..3a34264d77 100644 --- a/src/Umbraco.Core/Install/Models/InstallTrackingItem.cs +++ b/src/Umbraco.Core/Install/Models/InstallTrackingItem.cs @@ -21,7 +21,7 @@ namespace Umbraco.Cms.Core.Install.Models return string.Equals(Name, other.Name); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; diff --git a/src/Umbraco.Core/Logging/DisposableTimer.cs b/src/Umbraco.Core/Logging/DisposableTimer.cs index c87e7a9600..a22ac75127 100644 --- a/src/Umbraco.Core/Logging/DisposableTimer.cs +++ b/src/Umbraco.Core/Logging/DisposableTimer.cs @@ -13,12 +13,12 @@ namespace Umbraco.Cms.Core.Logging private readonly LogLevel _level; private readonly Type _loggerType; private readonly int _thresholdMilliseconds; - private readonly IDisposable _profilerStep; + private readonly IDisposable? _profilerStep; private readonly string _endMessage; - private string _failMessage; - private readonly object[] _endMessageArgs; - private readonly object[] _failMessageArgs; - private Exception _failException; + private string? _failMessage; + private readonly object[]? _endMessageArgs; + private readonly object[]? _failMessageArgs; + private Exception? _failException; private bool _failed; private readonly string _timingId; @@ -30,10 +30,10 @@ namespace Umbraco.Cms.Core.Logging Type loggerType, string startMessage, string endMessage, - string failMessage = null, - object[] startMessageArgs = null, - object[] endMessageArgs = null, - object[] failMessageArgs = null, + string? failMessage = null, + object[]? startMessageArgs = null, + object[]? endMessageArgs = null, + object[]? failMessageArgs = null, int thresholdMilliseconds = 0) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); @@ -93,7 +93,7 @@ namespace Umbraco.Cms.Core.Logging /// The fail message. /// The exception. /// Completion of the timer will be reported as an error, with the specified message and exception. - public void Fail(string failMessage = null, Exception exception = null) + public void Fail(string? failMessage = null, Exception? exception = null) { _failed = true; _failMessage = failMessage ?? _failMessage ?? "Failed."; diff --git a/src/Umbraco.Core/Logging/IProfilingLogger.cs b/src/Umbraco.Core/Logging/IProfilingLogger.cs index 4a0714fd0c..5873619988 100644 --- a/src/Umbraco.Core/Logging/IProfilingLogger.cs +++ b/src/Umbraco.Core/Logging/IProfilingLogger.cs @@ -10,31 +10,31 @@ namespace Umbraco.Cms.Core.Logging /// /// Profiles an action and log as information messages. /// - DisposableTimer TraceDuration(string startMessage, object[] startMessageArgs = null); + DisposableTimer TraceDuration(string startMessage, object[]? startMessageArgs = null); /// /// Profiles an action and log as information messages. /// - DisposableTimer TraceDuration(string startMessage, string completeMessage, string failMessage = null, object[] startMessageArgs = null, object[] endMessageArgs = null, object[] failMessageArgs = null); + DisposableTimer TraceDuration(string startMessage, string completeMessage, string? failMessage = null, object[]? startMessageArgs = null, object[]? endMessageArgs = null, object[]? failMessageArgs = null); /// /// Profiles an action and log as information messages. /// - DisposableTimer TraceDuration(Type loggerType, string startMessage, string completeMessage, string failMessage = null, object[] startMessageArgs = null, object[] endMessageArgs = null, object[] failMessageArgs = null); + DisposableTimer TraceDuration(Type loggerType, string startMessage, string completeMessage, string? failMessage = null, object[]? startMessageArgs = null, object[]? endMessageArgs = null, object[]? failMessageArgs = null); /// /// Profiles an action and log as debug messages. /// - DisposableTimer DebugDuration(string startMessage, object[] startMessageArgs = null); + DisposableTimer? DebugDuration(string startMessage, object[]? startMessageArgs = null); /// /// Profiles an action and log as debug messages. /// - DisposableTimer DebugDuration(string startMessage, string completeMessage, string failMessage = null, int thresholdMilliseconds = 0, object[] startMessageArgs = null, object[] endMessageArgs = null, object[] failMessageArgs = null); + DisposableTimer? DebugDuration(string startMessage, string completeMessage, string? failMessage = null, int thresholdMilliseconds = 0, object[]? startMessageArgs = null, object[]? endMessageArgs = null, object[]? failMessageArgs = null); /// /// Profiles an action and log as debug messages. /// - DisposableTimer DebugDuration(Type loggerType, string startMessage, string completeMessage, string failMessage = null, int thresholdMilliseconds = 0, object[] startMessageArgs = null, object[] endMessageArgs = null, object[] failMessageArgs = null); + DisposableTimer? DebugDuration(Type loggerType, string startMessage, string completeMessage, string? failMessage = null, int thresholdMilliseconds = 0, object[]? startMessageArgs = null, object[]? endMessageArgs = null, object[]? failMessageArgs = null); } } diff --git a/src/Umbraco.Core/Logging/LogHttpRequestExtension.cs b/src/Umbraco.Core/Logging/LogHttpRequestExtension.cs index d6d5af9802..c9e1b09e08 100644 --- a/src/Umbraco.Core/Logging/LogHttpRequestExtension.cs +++ b/src/Umbraco.Core/Logging/LogHttpRequestExtension.cs @@ -13,10 +13,10 @@ namespace Umbraco.Extensions /// The request id. /// /// true if there is a request in progress; false otherwise. - public static bool TryGetCurrentHttpRequestId(out Guid requestId, IRequestCache requestCache) + public static bool TryGetCurrentHttpRequestId(out Guid? requestId, IRequestCache requestCache) { var requestIdItem = requestCache.Get(RequestIdItemName, () => Guid.NewGuid()); - requestId = (Guid)requestIdItem; + requestId = (Guid?)requestIdItem; return true; } diff --git a/src/Umbraco.Core/Logging/ProfilingLogger.cs b/src/Umbraco.Core/Logging/ProfilingLogger.cs index 809600fbb0..d3388bda01 100644 --- a/src/Umbraco.Core/Logging/ProfilingLogger.cs +++ b/src/Umbraco.Core/Logging/ProfilingLogger.cs @@ -36,26 +36,26 @@ namespace Umbraco.Cms.Core.Logging Profiler = profiler ?? throw new ArgumentNullException(nameof(profiler)); } - public DisposableTimer TraceDuration(string startMessage, object[] startMessageArgs = null) + public DisposableTimer TraceDuration(string startMessage, object[]? startMessageArgs = null) => TraceDuration(startMessage, "Completed.", startMessageArgs: startMessageArgs); - public DisposableTimer TraceDuration(string startMessage, string completeMessage, string failMessage = null, object[] startMessageArgs = null, object[] endMessageArgs = null, object[] failMessageArgs = null) + public DisposableTimer TraceDuration(string startMessage, string completeMessage, string? failMessage = null, object[]? startMessageArgs = null, object[]? endMessageArgs = null, object[]? failMessageArgs = null) => new DisposableTimer(Logger, LogLevel.Information, Profiler, typeof(T), startMessage, completeMessage, failMessage, startMessageArgs, endMessageArgs, failMessageArgs); - public DisposableTimer TraceDuration(Type loggerType, string startMessage, string completeMessage, string failMessage = null, object[] startMessageArgs = null, object[] endMessageArgs = null, object[] failMessageArgs = null) + public DisposableTimer TraceDuration(Type loggerType, string startMessage, string completeMessage, string? failMessage = null, object[]? startMessageArgs = null, object[]? endMessageArgs = null, object[]? failMessageArgs = null) => new DisposableTimer(Logger, LogLevel.Information, Profiler, loggerType, startMessage, completeMessage, failMessage, startMessageArgs, endMessageArgs, failMessageArgs); - public DisposableTimer DebugDuration(string startMessage, object[] startMessageArgs = null) + public DisposableTimer? DebugDuration(string startMessage, object[]? startMessageArgs = null) => Logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug) ? DebugDuration(startMessage, "Completed.", startMessageArgs: startMessageArgs) : null; - public DisposableTimer DebugDuration(string startMessage, string completeMessage, string failMessage = null, int thresholdMilliseconds = 0, object[] startMessageArgs = null, object[] endMessageArgs = null, object[] failMessageArgs = null) + public DisposableTimer? DebugDuration(string startMessage, string completeMessage, string? failMessage = null, int thresholdMilliseconds = 0, object[]? startMessageArgs = null, object[]? endMessageArgs = null, object[]? failMessageArgs = null) => Logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug) ? new DisposableTimer(Logger, LogLevel.Debug, Profiler, typeof(T), startMessage, completeMessage, failMessage, startMessageArgs, endMessageArgs, failMessageArgs, thresholdMilliseconds) : null; - public DisposableTimer DebugDuration(Type loggerType, string startMessage, string completeMessage, string failMessage = null, int thresholdMilliseconds = 0, object[] startMessageArgs = null, object[] endMessageArgs = null, object[] failMessageArgs = null) + public DisposableTimer? DebugDuration(Type loggerType, string startMessage, string completeMessage, string? failMessage = null, int thresholdMilliseconds = 0, object[]? startMessageArgs = null, object[]? endMessageArgs = null, object[]? failMessageArgs = null) => Logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug) ? new DisposableTimer(Logger, LogLevel.Debug, Profiler, loggerType, startMessage, completeMessage, failMessage, startMessageArgs, endMessageArgs, failMessageArgs, thresholdMilliseconds) : null; diff --git a/src/Umbraco.Core/Macros/MacroModel.cs b/src/Umbraco.Core/Macros/MacroModel.cs index 08f52c0f53..5242b14d86 100644 --- a/src/Umbraco.Core/Macros/MacroModel.cs +++ b/src/Umbraco.Core/Macros/MacroModel.cs @@ -13,14 +13,14 @@ namespace Umbraco.Cms.Core.Macros /// /// The Macro Name /// - public string Name { get; set; } + public string? Name { get; set; } /// /// The Macro Alias /// - public string Alias { get; set; } + public string? Alias { get; set; } - public string MacroSource { get; set; } + public string? MacroSource { get; set; } public int CacheDuration { get; set; } @@ -30,7 +30,7 @@ namespace Umbraco.Cms.Core.Macros public bool RenderInEditor { get; set; } - public string CacheIdentifier { get; set; } + public string? CacheIdentifier { get; set; } public List Properties { get; } = new List(); diff --git a/src/Umbraco.Core/Macros/MacroPropertyModel.cs b/src/Umbraco.Core/Macros/MacroPropertyModel.cs index 78683a323d..1b59992f32 100644 --- a/src/Umbraco.Core/Macros/MacroPropertyModel.cs +++ b/src/Umbraco.Core/Macros/MacroPropertyModel.cs @@ -2,11 +2,11 @@ { public class MacroPropertyModel { - public string Key { get; set; } + public string? Key { get; set; } - public string Value { get; set; } + public string? Value { get; set; } - public string Type { get; set; } + public string? Type { get; set; } public MacroPropertyModel() { } diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentApp.cs b/src/Umbraco.Core/Models/ContentEditing/ContentApp.cs index e40e126c96..3dc88df3dd 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentApp.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentApp.cs @@ -15,7 +15,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// Gets the name of the content app. /// [DataMember(Name = "name")] - public string Name { get; set; } + public string? Name { get; set; } /// /// Gets the unique alias of the content app. @@ -24,7 +24,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// Must be a valid javascript identifier, ie no spaces etc. /// [DataMember(Name = "alias")] - public string Alias { get; set; } + public string? Alias { get; set; } /// /// Gets or sets the weight of the content app. @@ -45,19 +45,19 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// Must be a valid helveticons class name (see http://hlvticons.ch/). /// [DataMember(Name = "icon")] - public string Icon { get; set; } + public string? Icon { get; set; } /// /// Gets the view for rendering the content app. /// [DataMember(Name = "view")] - public string View { get; set; } + public string? View { get; set; } /// /// The view model specific to this app /// [DataMember(Name = "viewModel")] - public object ViewModel { get; set; } + public object? ViewModel { get; set; } /// /// Gets a value indicating whether the app is active. @@ -72,7 +72,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// Gets or sets the content app badge. /// [DataMember(Name = "badge")] - public ContentAppBadge Badge { get; set; } + public ContentAppBadge? Badge { get; set; } } } diff --git a/src/Umbraco.Core/Models/Email/EmailMessage.cs b/src/Umbraco.Core/Models/Email/EmailMessage.cs index 55e30f2150..b012bbfeb3 100644 --- a/src/Umbraco.Core/Models/Email/EmailMessage.cs +++ b/src/Umbraco.Core/Models/Email/EmailMessage.cs @@ -6,32 +6,32 @@ namespace Umbraco.Cms.Core.Models.Email { public class EmailMessage { - public string From { get; } + public string? From { get; } - public string[] To { get; } + public string?[] To { get; } - public string[] Cc { get; } + public string[]? Cc { get; } - public string[] Bcc { get; } + public string[]? Bcc { get; } - public string[] ReplyTo { get; } + public string[]? ReplyTo { get; } - public string Subject { get; } + public string? Subject { get; } - public string Body { get; } + public string? Body { get; } public bool IsBodyHtml { get; } - public IList Attachments { get; } + public IList? Attachments { get; } public bool HasAttachments => Attachments != null && Attachments.Count > 0; - public EmailMessage(string from, string to, string subject, string body, bool isBodyHtml) + public EmailMessage(string? from, string? to, string? subject, string? body, bool isBodyHtml) : this(from, new[] { to }, null, null, null, subject, body, isBodyHtml, null) { } - public EmailMessage(string from, string[] to, string[] cc, string[] bcc, string[] replyTo, string subject, string body, bool isBodyHtml, IEnumerable attachments) + public EmailMessage(string? from, string?[] to, string[]? cc, string[]? bcc, string[]? replyTo, string? subject, string? body, bool isBodyHtml, IEnumerable? attachments) { ArgumentIsNotNullOrEmpty(to, nameof(to)); ArgumentIsNotNullOrEmpty(subject, nameof(subject)); @@ -48,7 +48,7 @@ namespace Umbraco.Cms.Core.Models.Email Attachments = attachments?.ToList(); } - private static void ArgumentIsNotNullOrEmpty(string arg, string argName) + private static void ArgumentIsNotNullOrEmpty(string? arg, string argName) { if (arg == null) { @@ -61,7 +61,7 @@ namespace Umbraco.Cms.Core.Models.Email } } - private static void ArgumentIsNotNullOrEmpty(string[] arg, string argName) + private static void ArgumentIsNotNullOrEmpty(string?[]? arg, string argName) { if (arg == null) { diff --git a/src/Umbraco.Core/Models/IProperty.cs b/src/Umbraco.Core/Models/IProperty.cs index 8654c24d64..0fc8af9a22 100644 --- a/src/Umbraco.Core/Models/IProperty.cs +++ b/src/Umbraco.Core/Models/IProperty.cs @@ -30,7 +30,7 @@ namespace Umbraco.Cms.Core.Models /// /// Sets a value. /// - void SetValue(object value, string? culture = null, string? segment = null); + void SetValue(object? value, string? culture = null, string? segment = null); int PropertyTypeId { get; } void PublishValues(string culture = "*", string segment = "*"); diff --git a/src/Umbraco.Core/Services/ILocalizedTextService.cs b/src/Umbraco.Core/Services/ILocalizedTextService.cs index 51c1c97c9b..d3cb837ff7 100644 --- a/src/Umbraco.Core/Services/ILocalizedTextService.cs +++ b/src/Umbraco.Core/Services/ILocalizedTextService.cs @@ -24,7 +24,7 @@ namespace Umbraco.Cms.Core.Services /// /// This can be null /// - string Localize(string area, string alias, CultureInfo culture, IDictionary tokens = null); + string Localize(string area, string? alias, CultureInfo culture, IDictionary? tokens = null); /// diff --git a/src/Umbraco.Core/Services/INotificationService.cs b/src/Umbraco.Core/Services/INotificationService.cs index 17ee45dcfa..42345d8ca3 100644 --- a/src/Umbraco.Core/Services/INotificationService.cs +++ b/src/Umbraco.Core/Services/INotificationService.cs @@ -18,7 +18,7 @@ namespace Umbraco.Cms.Core.Services /// /// /// - void SendNotifications(IUser operatingUser, IEnumerable entities, string action, string actionName, Uri siteUri, + void SendNotifications(IUser operatingUser, IEnumerable entities, string? action, string? actionName, Uri siteUri, Func<(IUser user, NotificationEmailSubjectParams subject), string> createSubject, Func<(IUser user, NotificationEmailBodyParams body, bool isHtml), string> createBody); diff --git a/src/Umbraco.Core/Services/LocalizedTextServiceExtensions.cs b/src/Umbraco.Core/Services/LocalizedTextServiceExtensions.cs index 39704b2bb2..b341757946 100644 --- a/src/Umbraco.Core/Services/LocalizedTextServiceExtensions.cs +++ b/src/Umbraco.Core/Services/LocalizedTextServiceExtensions.cs @@ -20,7 +20,7 @@ namespace Umbraco.Extensions where T: System.Enum => manager.Localize(area, key.ToString(), Thread.CurrentThread.CurrentUICulture); - public static string Localize(this ILocalizedTextService manager, string area, string alias) + public static string Localize(this ILocalizedTextService manager, string area, string? alias) => manager.Localize(area, alias, Thread.CurrentThread.CurrentUICulture); /// @@ -31,7 +31,7 @@ namespace Umbraco.Extensions /// /// /// - public static string Localize(this ILocalizedTextService manager, string area, string alias, string[] tokens) + public static string Localize(this ILocalizedTextService manager, string area, string alias, string?[] tokens) => manager.Localize(area, alias, Thread.CurrentThread.CurrentUICulture, ConvertToDictionaryVars(tokens)); /// @@ -43,7 +43,7 @@ namespace Umbraco.Extensions /// /// /// - public static string Localize(this ILocalizedTextService manager, string area, string alias, CultureInfo culture, string[] tokens) + public static string Localize(this ILocalizedTextService manager, string area, string alias, CultureInfo culture, string?[] tokens) => manager.Localize(area, alias, culture, ConvertToDictionaryVars(tokens)); /// @@ -51,7 +51,7 @@ namespace Umbraco.Extensions /// /// /// - internal static IDictionary ConvertToDictionaryVars(string[] variables) + internal static IDictionary? ConvertToDictionaryVars(string?[] variables) { if (variables == null) return null; if (variables.Any() == false) return null; @@ -60,7 +60,7 @@ namespace Umbraco.Extensions .ToDictionary(keyvals => keyvals.index, keyvals => keyvals.value); } - public static string UmbracoDictionaryTranslate(this ILocalizedTextService manager, ICultureDictionary cultureDictionary, string text) + public static string? UmbracoDictionaryTranslate(this ILocalizedTextService manager, ICultureDictionary cultureDictionary, string text) { if (text == null) return null; diff --git a/src/Umbraco.Core/Services/PublicAccessServiceExtensions.cs b/src/Umbraco.Core/Services/PublicAccessServiceExtensions.cs index 487a0ad50a..8a1d007be8 100644 --- a/src/Umbraco.Core/Services/PublicAccessServiceExtensions.cs +++ b/src/Umbraco.Core/Services/PublicAccessServiceExtensions.cs @@ -16,7 +16,7 @@ namespace Umbraco.Extensions /// public static class PublicAccessServiceExtensions { - public static bool RenameMemberGroupRoleRules(this IPublicAccessService publicAccessService, string oldRolename, string newRolename) + public static bool RenameMemberGroupRoleRules(this IPublicAccessService publicAccessService, string? oldRolename, string newRolename) { var hasChange = false; if (oldRolename == newRolename) return false;