diff --git a/src/Umbraco.Core/Cache/ContentCacheRefresher.cs b/src/Umbraco.Core/Cache/ContentCacheRefresher.cs index 7fa77feb94..bd3e50377d 100644 --- a/src/Umbraco.Core/Cache/ContentCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/ContentCacheRefresher.cs @@ -67,7 +67,7 @@ namespace Umbraco.Cms.Core.Cache if (payload.ChangeTypes.HasTypesAny(TreeChangeTypes.RefreshBranch | TreeChangeTypes.Remove)) { var pathid = "," + payload.Id + ","; - isolatedCache.ClearOfType((k, v) => v.Path.Contains(pathid)); + isolatedCache.ClearOfType((k, v) => v.Path?.Contains(pathid) ?? false); } //if the item is being completely removed, we need to refresh the domains cache if any domain was assigned to the content diff --git a/src/Umbraco.Core/Cache/DictionaryAppCache.cs b/src/Umbraco.Core/Cache/DictionaryAppCache.cs index f6c733d1cc..296050a361 100644 --- a/src/Umbraco.Core/Cache/DictionaryAppCache.cs +++ b/src/Umbraco.Core/Cache/DictionaryAppCache.cs @@ -34,7 +34,7 @@ namespace Umbraco.Cms.Core.Cache return _items.GetOrAdd(key, _ => factory()); } - public bool Set(string key, object value) => _items.TryAdd(key, value); + public bool Set(string key, object? value) => _items.TryAdd(key, value); public bool Remove(string key) => _items.TryRemove(key, out _); diff --git a/src/Umbraco.Core/Cache/IRequestCache.cs b/src/Umbraco.Core/Cache/IRequestCache.cs index fa69725dcd..02f37e6ea9 100644 --- a/src/Umbraco.Core/Cache/IRequestCache.cs +++ b/src/Umbraco.Core/Cache/IRequestCache.cs @@ -4,7 +4,7 @@ namespace Umbraco.Cms.Core.Cache { public interface IRequestCache : IAppCache, IEnumerable> { - bool Set(string key, object value); + bool Set(string key, object? value); bool Remove(string key); /// diff --git a/src/Umbraco.Core/Cache/MediaCacheRefresher.cs b/src/Umbraco.Core/Cache/MediaCacheRefresher.cs index d4c4558dd4..dd4b05aa12 100644 --- a/src/Umbraco.Core/Cache/MediaCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/MediaCacheRefresher.cs @@ -65,7 +65,7 @@ namespace Umbraco.Cms.Core.Cache 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) ?? false); } } } diff --git a/src/Umbraco.Core/Cache/NoAppCache.cs b/src/Umbraco.Core/Cache/NoAppCache.cs index 759d8af9e1..ef22a51ab0 100644 --- a/src/Umbraco.Core/Cache/NoAppCache.cs +++ b/src/Umbraco.Core/Cache/NoAppCache.cs @@ -32,7 +32,7 @@ namespace Umbraco.Cms.Core.Cache return factory(); } - public bool Set(string key, object value) => false; + public bool Set(string key, object? value) => false; public bool Remove(string key) => false; diff --git a/src/Umbraco.Core/Collections/CompositeNStringNStringKey.cs b/src/Umbraco.Core/Collections/CompositeNStringNStringKey.cs index 450037e652..2886de92f1 100644 --- a/src/Umbraco.Core/Collections/CompositeNStringNStringKey.cs +++ b/src/Umbraco.Core/Collections/CompositeNStringNStringKey.cs @@ -17,7 +17,7 @@ namespace Umbraco.Cms.Core.Collections /// /// Initializes a new instance of the struct. /// - public CompositeNStringNStringKey(string key1, string key2) + public CompositeNStringNStringKey(string? key1, string? key2) { _key1 = key1?.ToLowerInvariant() ?? "NULL"; _key2 = key2?.ToLowerInvariant() ?? "NULL"; diff --git a/src/Umbraco.Core/Collections/ObservableDictionary.cs b/src/Umbraco.Core/Collections/ObservableDictionary.cs index 9e6b005407..1ea6a827c4 100644 --- a/src/Umbraco.Core/Collections/ObservableDictionary.cs +++ b/src/Umbraco.Core/Collections/ObservableDictionary.cs @@ -20,14 +20,14 @@ namespace Umbraco.Cms.Core.Collections where TKey : notnull { protected Dictionary Indecies { get; } - protected Func KeySelector { get; } + protected Func KeySelector { get; } /// /// Create new ObservableDictionary /// /// Selector function to create key from value /// The equality comparer to use when comparing keys, or null to use the default comparer. - public ObservableDictionary(Func keySelector, IEqualityComparer? equalityComparer = null) + public ObservableDictionary(Func keySelector, IEqualityComparer? equalityComparer = null) { KeySelector = keySelector ?? throw new ArgumentException(nameof(keySelector)); Indecies = new Dictionary(equalityComparer); diff --git a/src/Umbraco.Core/Dictionary/ICultureDictionary.cs b/src/Umbraco.Core/Dictionary/ICultureDictionary.cs index 9a6898c18d..e8e3c62050 100644 --- a/src/Umbraco.Core/Dictionary/ICultureDictionary.cs +++ b/src/Umbraco.Core/Dictionary/ICultureDictionary.cs @@ -13,7 +13,7 @@ namespace Umbraco.Cms.Core.Dictionary /// /// /// - string this[string key] { get; } + string? this[string key] { get; } /// /// Returns the current culture diff --git a/src/Umbraco.Core/Dictionary/UmbracoCultureDictionary.cs b/src/Umbraco.Core/Dictionary/UmbracoCultureDictionary.cs index d4d81c76c7..44cc15033f 100644 --- a/src/Umbraco.Core/Dictionary/UmbracoCultureDictionary.cs +++ b/src/Umbraco.Core/Dictionary/UmbracoCultureDictionary.cs @@ -52,7 +52,7 @@ namespace Umbraco.Cms.Core.Dictionary /// /// /// - public string this[string key] + public string? this[string key] { get { @@ -62,7 +62,7 @@ namespace Umbraco.Cms.Core.Dictionary return string.Empty; } - var byLang = found.Translations.FirstOrDefault(x => x.Language.Equals(Language)); + var byLang = found.Translations?.FirstOrDefault(x => x.Language?.Equals(Language) ?? false); if (byLang == null) { return string.Empty; @@ -105,8 +105,8 @@ namespace Umbraco.Cms.Core.Dictionary foreach (var dictionaryItem in children) { - var byLang = dictionaryItem.Translations.FirstOrDefault((x => x.Language.Equals(Language))); - if (byLang != null) + var byLang = dictionaryItem.Translations?.FirstOrDefault((x => x.Language?.Equals(Language) ?? false)); + if (byLang != null && dictionaryItem.ItemKey is not null && byLang.Value is not null) { result.Add(dictionaryItem.ItemKey, byLang.Value); } diff --git a/src/Umbraco.Core/Editors/UserEditorAuthorizationHelper.cs b/src/Umbraco.Core/Editors/UserEditorAuthorizationHelper.cs index 1ecb90b119..c74623c5fe 100644 --- a/src/Umbraco.Core/Editors/UserEditorAuthorizationHelper.cs +++ b/src/Umbraco.Core/Editors/UserEditorAuthorizationHelper.cs @@ -59,12 +59,12 @@ namespace Umbraco.Cms.Core.Editors var changedStartContentIds = savingUser == null ? startContentIds - : startContentIds == null + : startContentIds == null || savingUser.StartContentIds is null ? null : startContentIds.Except(savingUser.StartContentIds).ToArray(); var changedStartMediaIds = savingUser == null ? startMediaIds - : startMediaIds == null + : startMediaIds == null || savingUser.StartMediaIds is null ? null : startMediaIds.Except(savingUser.StartMediaIds).ToArray(); var pathResult = AuthorizePath(currentUser, changedStartContentIds, changedStartMediaIds); diff --git a/src/Umbraco.Core/Events/RelateOnCopyNotificationHandler.cs b/src/Umbraco.Core/Events/RelateOnCopyNotificationHandler.cs index 0a6518a1ca..44d2eb6ee7 100644 --- a/src/Umbraco.Core/Events/RelateOnCopyNotificationHandler.cs +++ b/src/Umbraco.Core/Events/RelateOnCopyNotificationHandler.cs @@ -44,7 +44,7 @@ namespace Umbraco.Cms.Core.Events _auditService.Add( AuditType.Copy, notification.Copy.WriterId, - notification.Copy.Id, ObjectTypes.GetName(UmbracoObjectTypes.Document), + notification.Copy.Id, ObjectTypes.GetName(UmbracoObjectTypes.Document) ?? string.Empty, $"Copied content with Id: '{notification.Copy.Id}' related to original content with Id: '{notification.Original.Id}'"); } } diff --git a/src/Umbraco.Core/Extensions/ContentExtensions.cs b/src/Umbraco.Core/Extensions/ContentExtensions.cs index 7f34446f61..904ca9941a 100644 --- a/src/Umbraco.Core/Extensions/ContentExtensions.cs +++ b/src/Umbraco.Core/Extensions/ContentExtensions.cs @@ -90,7 +90,7 @@ namespace Umbraco.Extensions /// public static void SanitizeEntityPropertiesForXmlStorage(this IContentBase entity) { - entity.Name = entity.Name.ToValidXmlString(); + entity.Name = entity.Name?.ToValidXmlString(); foreach (var property in entity.Properties) { foreach (var propertyValue in property.Values) @@ -170,8 +170,8 @@ namespace Umbraco.Extensions /// /// to retrieve ancestors for /// An Enumerable list of integer ids - public static IEnumerable GetAncestorIds(this IContent content) => - content.Path.Split(Constants.CharArrays.Comma) + public static IEnumerable? GetAncestorIds(this IContent content) => + content.Path?.Split(Constants.CharArrays.Comma) .Where(x => x != Constants.System.RootString && x != content.Id.ToString(CultureInfo.InvariantCulture)).Select(s => int.Parse(s, CultureInfo.InvariantCulture)); @@ -311,7 +311,7 @@ namespace Umbraco.Extensions var contentType = contentTypeBaseServiceProvider.GetContentTypeOf(content); var propertyType = contentType.CompositionPropertyTypes - .FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias)); + .FirstOrDefault(x => x.Alias?.InvariantEquals(propertyTypeAlias) ?? false); if (propertyType == null) throw new Exception("No property type exists with alias " + propertyTypeAlias + "."); @@ -340,7 +340,7 @@ namespace Umbraco.Extensions { var contentType = contentTypeBaseServiceProvider.GetContentTypeOf(content); var propertyType = contentType - .CompositionPropertyTypes.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias)); + .CompositionPropertyTypes.FirstOrDefault(x => x.Alias?.InvariantEquals(propertyTypeAlias) ?? false); if (propertyType == null) throw new ArgumentException("Invalid property type alias " + propertyTypeAlias + "."); return mediaFileManager.StoreFile(content, propertyType, filename, filestream, filepath); diff --git a/src/Umbraco.Core/Extensions/PublishedContentExtensions.cs b/src/Umbraco.Core/Extensions/PublishedContentExtensions.cs index 3f1b60fa13..aaae931727 100644 --- a/src/Umbraco.Core/Extensions/PublishedContentExtensions.cs +++ b/src/Umbraco.Core/Extensions/PublishedContentExtensions.cs @@ -166,7 +166,7 @@ namespace Umbraco.Extensions } var template = fileService.GetTemplate(content.TemplateId.Value); - return template == null ? string.Empty : template.Alias; + return template.Alias ?? string.Empty; } public static bool IsAllowedTemplate(this IPublishedContent content, IContentTypeService contentTypeService, @@ -1358,7 +1358,7 @@ namespace Umbraco.Extensions return fields; } - private static Dictionary GetAliasesAndNames(IContentTypeBase contentType) => contentType.PropertyTypes.ToDictionary(x => x.Alias, x => x.Name); + private static Dictionary GetAliasesAndNames(IContentTypeBase contentType) => contentType.PropertyTypes.Where(x => x.Alias is not null && x.Name is not null).ToDictionary(x => x.Alias!, x => x.Name!); #endregion } diff --git a/src/Umbraco.Core/Extensions/PublishedPropertyExtension.cs b/src/Umbraco.Core/Extensions/PublishedPropertyExtension.cs index 903633e9e4..dcfd6900ef 100644 --- a/src/Umbraco.Core/Extensions/PublishedPropertyExtension.cs +++ b/src/Umbraco.Core/Extensions/PublishedPropertyExtension.cs @@ -11,7 +11,7 @@ namespace Umbraco.Extensions { #region Value - public static object Value(this IPublishedProperty property, IPublishedValueFallback publishedValueFallback, string? culture = null, string? segment = null, Fallback fallback = default, object? defaultValue = default) + public static object? Value(this IPublishedProperty property, IPublishedValueFallback publishedValueFallback, string? culture = null, string? segment = null, Fallback fallback = default, object? defaultValue = default) { if (property.HasValue(culture, segment)) return property.GetValue(culture, segment); diff --git a/src/Umbraco.Core/Extensions/StringExtensions.cs b/src/Umbraco.Core/Extensions/StringExtensions.cs index 3202b3a253..7661fc44d3 100644 --- a/src/Umbraco.Core/Extensions/StringExtensions.cs +++ b/src/Umbraco.Core/Extensions/StringExtensions.cs @@ -1307,7 +1307,7 @@ namespace Umbraco.Extensions /// The short string helper. /// The culture. /// The safe url segment. - public static string ToUrlSegment(this string text, IShortStringHelper shortStringHelper, string culture) + public static string ToUrlSegment(this string text, IShortStringHelper shortStringHelper, string? culture) { if (text == null) throw new ArgumentNullException(nameof(text)); if (string.IsNullOrWhiteSpace(text)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(text)); diff --git a/src/Umbraco.Core/Handlers/AuditNotificationsHandler.cs b/src/Umbraco.Core/Handlers/AuditNotificationsHandler.cs index fbc91d812d..594f8aa620 100644 --- a/src/Umbraco.Core/Handlers/AuditNotificationsHandler.cs +++ b/src/Umbraco.Core/Handlers/AuditNotificationsHandler.cs @@ -179,7 +179,7 @@ namespace Umbraco.Cms.Core.Handlers var sections = ((UserGroup)group).WasPropertyDirty("AllowedSections") ? string.Join(", ", group.AllowedSections) : null; - var perms = ((UserGroup)group).WasPropertyDirty("Permissions") + var perms = ((UserGroup)group).WasPropertyDirty("Permissions") && group.Permissions is not null ? string.Join(", ", group.Permissions) : null; diff --git a/src/Umbraco.Core/Handlers/PublicAccessHandler.cs b/src/Umbraco.Core/Handlers/PublicAccessHandler.cs index b50375adfe..466e09e3f1 100644 --- a/src/Umbraco.Core/Handlers/PublicAccessHandler.cs +++ b/src/Umbraco.Core/Handlers/PublicAccessHandler.cs @@ -26,12 +26,12 @@ namespace Umbraco.Cms.Core.Handlers foreach (var grp in affectedEntities) { //check if the name has changed - if (grp.AdditionalData.ContainsKey("previousName") + if ((grp.AdditionalData?.ContainsKey("previousName") ?? false) && grp.AdditionalData["previousName"] != null - && grp.AdditionalData["previousName"].ToString().IsNullOrWhiteSpace() == false - && grp.AdditionalData["previousName"].ToString() != grp.Name) + && grp.AdditionalData["previousName"]?.ToString().IsNullOrWhiteSpace() == false + && grp.AdditionalData["previousName"]?.ToString() != grp.Name) { - _publicAccessService.RenameMemberGroupRoleRules(grp.AdditionalData["previousName"].ToString(), grp.Name); + _publicAccessService.RenameMemberGroupRoleRules(grp.AdditionalData["previousName"]?.ToString(), grp.Name); } } } diff --git a/src/Umbraco.Core/IO/IFileSystem.cs b/src/Umbraco.Core/IO/IFileSystem.cs index 53c37dbe05..232827300c 100644 --- a/src/Umbraco.Core/IO/IFileSystem.cs +++ b/src/Umbraco.Core/IO/IFileSystem.cs @@ -124,7 +124,7 @@ namespace Umbraco.Cms.Core.IO /// /// representing the relative URL. /// - string GetUrl(string path); + string GetUrl(string? path); /// /// Gets the last modified date/time of the file, expressed as a UTC value. diff --git a/src/Umbraco.Core/IO/IViewHelper.cs b/src/Umbraco.Core/IO/IViewHelper.cs index 19805a0fad..ae6f8698a4 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/PhysicalFileSystem.cs b/src/Umbraco.Core/IO/PhysicalFileSystem.cs index db10cae416..5bdf347ef9 100644 --- a/src/Umbraco.Core/IO/PhysicalFileSystem.cs +++ b/src/Umbraco.Core/IO/PhysicalFileSystem.cs @@ -327,9 +327,9 @@ namespace Umbraco.Cms.Core.IO /// The filesystem-relative path. /// The URL. /// All separators are forward-slashes. - public string GetUrl(string path) + public string GetUrl(string? path) { - path = EnsureUrlSeparatorChar(path).Trim(Constants.CharArrays.ForwardSlash); + path = EnsureUrlSeparatorChar(path ?? string.Empty).Trim(Constants.CharArrays.ForwardSlash); return _rootUrl + "/" + path; } diff --git a/src/Umbraco.Core/IO/ShadowFileSystem.cs b/src/Umbraco.Core/IO/ShadowFileSystem.cs index b921445663..66ed1947a7 100644 --- a/src/Umbraco.Core/IO/ShadowFileSystem.cs +++ b/src/Umbraco.Core/IO/ShadowFileSystem.cs @@ -262,7 +262,7 @@ namespace Umbraco.Cms.Core.IO return _fs.GetFullPath(path); } - public string GetUrl(string path) + public string GetUrl(string? path) { return _fs.GetUrl(path); } diff --git a/src/Umbraco.Core/IO/ShadowWrapper.cs b/src/Umbraco.Core/IO/ShadowWrapper.cs index 408b64959c..c331c04a82 100644 --- a/src/Umbraco.Core/IO/ShadowWrapper.cs +++ b/src/Umbraco.Core/IO/ShadowWrapper.cs @@ -199,7 +199,7 @@ namespace Umbraco.Cms.Core.IO return FileSystem.GetFullPath(path); } - public string GetUrl(string path) + public string GetUrl(string? path) { return FileSystem.GetUrl(path); } diff --git a/src/Umbraco.Core/IO/ViewHelper.cs b/src/Umbraco.Core/IO/ViewHelper.cs index 85401e6f12..e78b3757f5 100644 --- a/src/Umbraco.Core/IO/ViewHelper.cs +++ b/src/Umbraco.Core/IO/ViewHelper.cs @@ -27,13 +27,13 @@ namespace Umbraco.Cms.Core.IO _defaultViewContentProvider = defaultViewContentProvider ?? throw new ArgumentNullException(nameof(defaultViewContentProvider)); } - public bool ViewExists(ITemplate t) => _viewFileSystem.FileExists(ViewPath(t.Alias)); + public bool ViewExists(ITemplate t) => t.Alias is not null && _viewFileSystem.FileExists(ViewPath(t.Alias)); public string GetFileContents(ITemplate t) { var viewContent = ""; - var path = ViewPath(t.Alias); + var path = ViewPath(t.Alias ?? string.Empty); if (_viewFileSystem.FileExists(path)) { @@ -79,7 +79,7 @@ namespace Umbraco.Cms.Core.IO private string SaveTemplateToFile(ITemplate template) { - var design = template.Content.IsNullOrWhiteSpace() ? EnsureInheritedLayout(template) : template.Content; + var design = template.Content.IsNullOrWhiteSpace() ? EnsureInheritedLayout(template) : template.Content!; var path = ViewPath(template.Alias); var data = Encoding.UTF8.GetBytes(design); @@ -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); @@ -105,7 +105,7 @@ namespace Umbraco.Cms.Core.IO _viewFileSystem.DeleteFile(oldFile); } - var data = Encoding.UTF8.GetBytes(t.Content); + var data = Encoding.UTF8.GetBytes(t.Content ?? string.Empty); var withBom = Encoding.UTF8.GetPreamble().Concat(data).ToArray(); using (var ms = new MemoryStream(withBom)) diff --git a/src/Umbraco.Core/Manifest/ManifestContentAppFactory.cs b/src/Umbraco.Core/Manifest/ManifestContentAppFactory.cs index d865bb01aa..c52bd81e21 100644 --- a/src/Umbraco.Core/Manifest/ManifestContentAppFactory.cs +++ b/src/Umbraco.Core/Manifest/ManifestContentAppFactory.cs @@ -43,13 +43,13 @@ namespace Umbraco.Cms.Core.Manifest _ioHelper = ioHelper; } - private ContentApp _app; - private ShowRule[] _showRules; + private ContentApp? _app; + private ShowRule[]? _showRules; /// - public ContentApp GetContentAppFor(object o,IEnumerable userGroups) + public ContentApp? GetContentAppFor(object o,IEnumerable userGroups) { - string partA, partB; + string? partA, partB; switch (o) { @@ -68,7 +68,7 @@ namespace Umbraco.Cms.Core.Manifest break; case IContentType contentType: partA = "contentType"; - partB = contentType.Alias; + partB = contentType?.Alias; break; default: @@ -85,7 +85,7 @@ namespace Umbraco.Cms.Core.Manifest foreach (var rule in rules) { - if (rule.PartA.InvariantEquals("role")) + if (rule.PartA?.InvariantEquals("role") ?? false) { // if roles have been ok-ed already, skip the rule if (okRole) @@ -156,12 +156,12 @@ namespace Umbraco.Cms.Core.Manifest private static readonly Regex ShowRegex = new Regex("^([+-])?([a-z]+)/([a-z0-9_]+|\\*)$", RegexOptions.Compiled | RegexOptions.IgnoreCase); public bool Show { get; private set; } - public string PartA { get; private set; } - public string PartB { get; private set; } + public string? PartA { get; private set; } + public string? PartB { get; private set; } - public bool Matches(string partA, string partB) + public bool Matches(string? partA, string? partB) { - return (PartA == "*" || PartA.InvariantEquals(partA)) && (PartB == "*" || PartB.InvariantEquals(partB)); + return (PartA == "*" || (PartA?.InvariantEquals(partA) ?? false)) && (PartB == "*" || (PartB?.InvariantEquals(partB) ?? false)); } public static IEnumerable Parse(string[] rules) diff --git a/src/Umbraco.Core/Manifest/PackageManifest.cs b/src/Umbraco.Core/Manifest/PackageManifest.cs index ae6ffdc8ba..dfe6ad46e7 100644 --- a/src/Umbraco.Core/Manifest/PackageManifest.cs +++ b/src/Umbraco.Core/Manifest/PackageManifest.cs @@ -13,13 +13,13 @@ namespace Umbraco.Cms.Core.Manifest [DataContract] public class PackageManifest { - private string _packageName; + private string? _packageName; /// /// An optional package name. If not specified then the directory name is used. /// [DataMember(Name = "name")] - public string PackageName + public string? PackageName { get { @@ -37,7 +37,7 @@ namespace Umbraco.Cms.Core.Manifest } [DataMember(Name = "packageView")] - public string PackageView { get; set; } + public string? PackageView { get; set; } /// /// Gets the source path of the manifest. @@ -47,7 +47,7 @@ namespace Umbraco.Cms.Core.Manifest /// using system directory separators. /// [IgnoreDataMember] - public string Source { get; set; } + public string? Source { get; set; } /// /// Gets or sets the version of the package diff --git a/src/Umbraco.Core/Mapping/MapperContext.cs b/src/Umbraco.Core/Mapping/MapperContext.cs index 0e529b23a1..8c0413ada2 100644 --- a/src/Umbraco.Core/Mapping/MapperContext.cs +++ b/src/Umbraco.Core/Mapping/MapperContext.cs @@ -9,7 +9,7 @@ namespace Umbraco.Cms.Core.Mapping public class MapperContext { private readonly IUmbracoMapper _mapper; - private IDictionary _items; + private IDictionary? _items; /// /// Initializes a new instance of the class. diff --git a/src/Umbraco.Core/Models/AuditEntry.cs b/src/Umbraco.Core/Models/AuditEntry.cs index b89979e08f..e0bb52375b 100644 --- a/src/Umbraco.Core/Models/AuditEntry.cs +++ b/src/Umbraco.Core/Models/AuditEntry.cs @@ -12,12 +12,12 @@ namespace Umbraco.Cms.Core.Models public class AuditEntry : EntityBase, IAuditEntry { private int _performingUserId; - private string _performingDetails; - private string _performingIp; + private string? _performingDetails; + private string? _performingIp; private int _affectedUserId; - private string _affectedDetails; - private string _eventType; - private string _eventDetails; + private string? _affectedDetails; + private string? _eventType; + private string? _eventDetails; /// public int PerformingUserId @@ -27,14 +27,14 @@ namespace Umbraco.Cms.Core.Models } /// - public string PerformingDetails + public string? PerformingDetails { get => _performingDetails; set => SetPropertyValueAndDetectChanges(value, ref _performingDetails, nameof(PerformingDetails)); } /// - public string PerformingIp + public string? PerformingIp { get => _performingIp; set => SetPropertyValueAndDetectChanges(value, ref _performingIp, nameof(PerformingIp)); @@ -55,21 +55,21 @@ namespace Umbraco.Cms.Core.Models } /// - public string AffectedDetails + public string? AffectedDetails { get => _affectedDetails; set => SetPropertyValueAndDetectChanges(value, ref _affectedDetails, nameof(AffectedDetails)); } /// - public string EventType + public string? EventType { get => _eventType; set => SetPropertyValueAndDetectChanges(value, ref _eventType, nameof(EventType)); } /// - public string EventDetails + public string? EventDetails { get => _eventDetails; set => SetPropertyValueAndDetectChanges(value, ref _eventDetails, nameof(EventDetails)); diff --git a/src/Umbraco.Core/Models/AuditItem.cs b/src/Umbraco.Core/Models/AuditItem.cs index 13b6ff1264..6eca2ae185 100644 --- a/src/Umbraco.Core/Models/AuditItem.cs +++ b/src/Umbraco.Core/Models/AuditItem.cs @@ -7,7 +7,7 @@ namespace Umbraco.Cms.Core.Models /// /// Initializes a new instance of the class. /// - public AuditItem(int objectId, AuditType type, int userId, string entityType, string comment = null, string parameters = null) + public AuditItem(int objectId, AuditType type, int userId, string entityType, string? comment = null, string? parameters = null) { DisableChangeTracking(); @@ -31,9 +31,9 @@ namespace Umbraco.Cms.Core.Models public int UserId { get; } /// - public string Comment { get; } + public string? Comment { get; } /// - public string Parameters { get; } + public string? Parameters { get; } } } diff --git a/src/Umbraco.Core/Models/BackOfficeTour.cs b/src/Umbraco.Core/Models/BackOfficeTour.cs index 4889fb5dde..a8e6c535e1 100644 --- a/src/Umbraco.Core/Models/BackOfficeTour.cs +++ b/src/Umbraco.Core/Models/BackOfficeTour.cs @@ -15,13 +15,13 @@ namespace Umbraco.Cms.Core.Models } [DataMember(Name = "name")] - public string Name { get; set; } + public string? Name { get; set; } [DataMember(Name = "alias")] - public string Alias { get; set; } + public string? Alias { get; set; } [DataMember(Name = "group")] - public string Group { get; set; } + public string? Group { get; set; } [DataMember(Name = "groupOrder")] public int GroupOrder { get; set; } @@ -36,12 +36,12 @@ namespace Umbraco.Cms.Core.Models public List RequiredSections { get; set; } [DataMember(Name = "steps")] - public BackOfficeTourStep[] Steps { get; set; } + public BackOfficeTourStep[]? Steps { get; set; } [DataMember(Name = "culture")] - public string Culture { get; set; } + public string? Culture { get; set; } [DataMember(Name = "contentType")] - public string ContentType { get; set; } + public string? ContentType { get; set; } } } diff --git a/src/Umbraco.Core/Models/BackOfficeTourFile.cs b/src/Umbraco.Core/Models/BackOfficeTourFile.cs index 3229a736d8..21b769f94e 100644 --- a/src/Umbraco.Core/Models/BackOfficeTourFile.cs +++ b/src/Umbraco.Core/Models/BackOfficeTourFile.cs @@ -18,7 +18,7 @@ namespace Umbraco.Cms.Core.Models /// The file name for the tour /// [DataMember(Name = "fileName")] - public string FileName { get; set; } + public string? FileName { get; set; } /// /// The plugin folder that the tour comes from @@ -27,7 +27,7 @@ namespace Umbraco.Cms.Core.Models /// If this is null it means it's a Core tour /// [DataMember(Name = "pluginName")] - public string PluginName { get; set; } + public string? PluginName { get; set; } [DataMember(Name = "tours")] public IEnumerable Tours { get; set; } diff --git a/src/Umbraco.Core/Models/Blocks/BlockListModel.cs b/src/Umbraco.Core/Models/Blocks/BlockListModel.cs index f2e556e004..33a711520b 100644 --- a/src/Umbraco.Core/Models/Blocks/BlockListModel.cs +++ b/src/Umbraco.Core/Models/Blocks/BlockListModel.cs @@ -46,7 +46,7 @@ namespace Umbraco.Cms.Core.Models.Blocks /// /// The with the specified content key. /// - public BlockListItem this[Guid contentKey] => this.FirstOrDefault(x => x.Content.Key == contentKey); + public BlockListItem? this[Guid contentKey] => this.FirstOrDefault(x => x.Content.Key == contentKey); /// /// Gets the with the specified content UDI. @@ -58,6 +58,6 @@ namespace Umbraco.Cms.Core.Models.Blocks /// /// The with the specified content UDI. /// - public BlockListItem this[Udi contentUdi] => contentUdi is GuidUdi guidUdi ? this.FirstOrDefault(x => x.Content.Key == guidUdi.Guid) : null; + public BlockListItem? this[Udi contentUdi] => contentUdi is GuidUdi guidUdi ? this.FirstOrDefault(x => x.Content.Key == guidUdi.Guid) : null; } } diff --git a/src/Umbraco.Core/Models/Blocks/ContentAndSettingsReference.cs b/src/Umbraco.Core/Models/Blocks/ContentAndSettingsReference.cs index 48d93ec985..3cfcbf9122 100644 --- a/src/Umbraco.Core/Models/Blocks/ContentAndSettingsReference.cs +++ b/src/Umbraco.Core/Models/Blocks/ContentAndSettingsReference.cs @@ -15,7 +15,7 @@ namespace Umbraco.Cms.Core.Models.Blocks public Udi SettingsUdi { get; } - public override bool Equals(object obj) => obj is ContentAndSettingsReference reference && Equals(reference); + public override bool Equals(object? obj) => obj is ContentAndSettingsReference reference && Equals(reference); public bool Equals(ContentAndSettingsReference other) => other != null && EqualityComparer.Default.Equals(ContentUdi, other.ContentUdi) diff --git a/src/Umbraco.Core/Models/Consent.cs b/src/Umbraco.Core/Models/Consent.cs index 5bbb5e4607..2354c67b1e 100644 --- a/src/Umbraco.Core/Models/Consent.cs +++ b/src/Umbraco.Core/Models/Consent.cs @@ -13,11 +13,11 @@ namespace Umbraco.Cms.Core.Models public class Consent : EntityBase, IConsent { private bool _current; - private string _source; - private string _context; - private string _action; + private string? _source; + private string? _context; + private string? _action; private ConsentState _state; - private string _comment; + private string? _comment; /// public bool Current @@ -27,7 +27,7 @@ namespace Umbraco.Cms.Core.Models } /// - public string Source + public string? Source { get => _source; set @@ -38,7 +38,7 @@ namespace Umbraco.Cms.Core.Models } /// - public string Context + public string? Context { get => _context; set @@ -49,7 +49,7 @@ namespace Umbraco.Cms.Core.Models } /// - public string Action + public string? Action { get => _action; set @@ -69,18 +69,18 @@ namespace Umbraco.Cms.Core.Models } /// - public string Comment + public string? Comment { get => _comment; set => SetPropertyValueAndDetectChanges(value, ref _comment, nameof(Comment)); } /// - public IEnumerable History => HistoryInternal; + public IEnumerable? History => HistoryInternal; /// /// Gets the previous states of this consent. /// - public List HistoryInternal { get; set; } + public List? HistoryInternal { get; set; } } } diff --git a/src/Umbraco.Core/Models/Content.cs b/src/Umbraco.Core/Models/Content.cs index cc475a566a..e854e6bf6d 100644 --- a/src/Umbraco.Core/Models/Content.cs +++ b/src/Umbraco.Core/Models/Content.cs @@ -17,13 +17,13 @@ namespace Umbraco.Cms.Core.Models private int? _templateId; private bool _published; private PublishedState _publishedState; - private HashSet _editedCultures; - private ContentCultureInfosCollection _publishInfos; + private HashSet? _editedCultures; + private ContentCultureInfosCollection? _publishInfos; #region Used for change tracking - private (HashSet addedCultures, HashSet removedCultures, HashSet updatedCultures) _currentPublishCultureChanges; - private (HashSet addedCultures, HashSet removedCultures, HashSet updatedCultures) _previousPublishCultureChanges; + private (HashSet? addedCultures, HashSet? removedCultures, HashSet? updatedCultures) _currentPublishCultureChanges; + private (HashSet? addedCultures, HashSet? removedCultures, HashSet? updatedCultures) _previousPublishCultureChanges; #endregion @@ -180,13 +180,13 @@ namespace Umbraco.Cms.Core.Models /// [IgnoreDataMember] - public string PublishName { get; set; } // set by persistence + public string? PublishName { get; set; } // set by persistence /// [IgnoreDataMember] - public IEnumerable EditedCultures + public IEnumerable? EditedCultures { - get => CultureInfos.Keys.Where(IsCultureEdited); + get => CultureInfos?.Keys.Where(IsCultureEdited); set => _editedCultures = value == null ? null : new HashSet(value, StringComparer.OrdinalIgnoreCase); } @@ -208,7 +208,7 @@ namespace Umbraco.Cms.Core.Models /// [IgnoreDataMember] - public ContentCultureInfosCollection PublishCultureInfos + public ContentCultureInfosCollection? PublishCultureInfos { get { @@ -233,7 +233,7 @@ namespace Umbraco.Cms.Core.Models } /// - public string GetPublishName(string culture) + public string? GetPublishName(string culture) { if (culture.IsNullOrWhiteSpace()) return PublishName; if (!ContentType.VariesByCulture()) return null; @@ -253,7 +253,7 @@ namespace Umbraco.Cms.Core.Models /// /// Handles culture infos collection changes. /// - private void PublishNamesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + private void PublishNamesCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { OnPropertyChanged(nameof(PublishCultureInfos)); @@ -263,30 +263,39 @@ namespace Umbraco.Cms.Core.Models { case NotifyCollectionChangedAction.Add: { - var cultureInfo = e.NewItems.Cast().First(); + var cultureInfo = e.NewItems?.Cast().First(); if (_currentPublishCultureChanges.addedCultures == null) _currentPublishCultureChanges.addedCultures = new HashSet(StringComparer.InvariantCultureIgnoreCase); if (_currentPublishCultureChanges.updatedCultures == null) _currentPublishCultureChanges.updatedCultures = new HashSet(StringComparer.InvariantCultureIgnoreCase); - _currentPublishCultureChanges.addedCultures.Add(cultureInfo.Culture); - _currentPublishCultureChanges.updatedCultures.Add(cultureInfo.Culture); - _currentPublishCultureChanges.removedCultures?.Remove(cultureInfo.Culture); + if (cultureInfo is not null) + { + _currentPublishCultureChanges.addedCultures.Add(cultureInfo.Culture); + _currentPublishCultureChanges.updatedCultures.Add(cultureInfo.Culture); + _currentPublishCultureChanges.removedCultures?.Remove(cultureInfo.Culture); + } break; } case NotifyCollectionChangedAction.Remove: { //remove listening for changes - var cultureInfo = e.OldItems.Cast().First(); + var cultureInfo = e.OldItems?.Cast().First(); if (_currentPublishCultureChanges.removedCultures == null) _currentPublishCultureChanges.removedCultures = new HashSet(StringComparer.InvariantCultureIgnoreCase); - _currentPublishCultureChanges.removedCultures.Add(cultureInfo.Culture); - _currentPublishCultureChanges.updatedCultures?.Remove(cultureInfo.Culture); - _currentPublishCultureChanges.addedCultures?.Remove(cultureInfo.Culture); + if (cultureInfo is not null) + { + _currentPublishCultureChanges.removedCultures.Add(cultureInfo.Culture); + _currentPublishCultureChanges.updatedCultures?.Remove(cultureInfo.Culture); + _currentPublishCultureChanges.addedCultures?.Remove(cultureInfo.Culture); + } break; } case NotifyCollectionChangedAction.Replace: { //replace occurs when an Update occurs - var cultureInfo = e.NewItems.Cast().First(); + var cultureInfo = e.NewItems?.Cast().First(); if (_currentPublishCultureChanges.updatedCultures == null) _currentPublishCultureChanges.updatedCultures = new HashSet(StringComparer.InvariantCultureIgnoreCase); - _currentPublishCultureChanges.updatedCultures.Add(cultureInfo.Culture); + if (cultureInfo is not null) + { + _currentPublishCultureChanges.updatedCultures.Add(cultureInfo.Culture); + } break; } } @@ -441,8 +450,12 @@ namespace Umbraco.Cms.Core.Models if (clonedContent._publishInfos != null) { clonedContent._publishInfos.ClearCollectionChangedEvents(); //clear this event handler if any - clonedContent._publishInfos = (ContentCultureInfosCollection)_publishInfos.DeepClone(); //manually deep clone - clonedContent._publishInfos.CollectionChanged += clonedContent.PublishNamesCollectionChanged; //re-assign correct event handler + clonedContent._publishInfos = (ContentCultureInfosCollection?)_publishInfos?.DeepClone(); //manually deep clone + if (clonedContent._publishInfos is not null) + { + clonedContent._publishInfos.CollectionChanged += + clonedContent.PublishNamesCollectionChanged; //re-assign correct event handler + } } clonedContent._currentPublishCultureChanges.updatedCultures = null; diff --git a/src/Umbraco.Core/Models/ContentBase.cs b/src/Umbraco.Core/Models/ContentBase.cs index a53f2ccf51..ee5a89c734 100644 --- a/src/Umbraco.Core/Models/ContentBase.cs +++ b/src/Umbraco.Core/Models/ContentBase.cs @@ -20,13 +20,13 @@ namespace Umbraco.Cms.Core.Models private int _contentTypeId; private int _writerId; private IPropertyCollection _properties; - private ContentCultureInfosCollection _cultureInfos; + private ContentCultureInfosCollection? _cultureInfos; internal IReadOnlyList AllPropertyTypes { get; } #region Used for change tracking - private (HashSet addedCultures, HashSet removedCultures, HashSet updatedCultures) _currentCultureChanges; - private (HashSet addedCultures, HashSet removedCultures, HashSet updatedCultures) _previousCultureChanges; + private (HashSet? addedCultures, HashSet? removedCultures, HashSet? updatedCultures) _currentCultureChanges; + private (HashSet? addedCultures, HashSet? removedCultures, HashSet? updatedCultures) _previousCultureChanges; public static class ChangeTrackingPrefix { @@ -89,7 +89,7 @@ namespace Umbraco.Cms.Core.Models ContentTypeId = contentType.Id; } - protected void PropertiesChanged(object sender, NotifyCollectionChangedEventArgs e) + protected void PropertiesChanged(object? sender, NotifyCollectionChangedEventArgs e) { OnPropertyChanged(nameof(Properties)); } @@ -167,7 +167,7 @@ namespace Umbraco.Cms.Core.Models /// [DataMember] - public ContentCultureInfosCollection CultureInfos + public ContentCultureInfosCollection? CultureInfos { get { @@ -191,12 +191,12 @@ namespace Umbraco.Cms.Core.Models } /// - public string GetCultureName(string culture) + public string? GetCultureName(string? culture) { if (culture.IsNullOrWhiteSpace()) return Name; if (!ContentType.VariesByCulture()) return null; if (_cultureInfos == null) return null; - return _cultureInfos.TryGetValue(culture, out var infos) ? infos.Name : null; + return _cultureInfos.TryGetValue(culture!, out var infos) ? infos.Name : null; } /// @@ -209,7 +209,7 @@ namespace Umbraco.Cms.Core.Models } /// - public void SetCultureName(string name, string culture) + public void SetCultureName(string? name, string? culture) { if (ContentType.VariesByCulture()) // set on variant content type { @@ -219,11 +219,11 @@ namespace Umbraco.Cms.Core.Models } else if (name.IsNullOrWhiteSpace()) // clear { - ClearCultureInfo(culture); + ClearCultureInfo(culture!); } else // set { - this.SetCultureInfo(culture, name, DateTime.Now); + this.SetCultureInfo(culture!, name, DateTime.Now); } } else // set on invariant content type @@ -249,7 +249,7 @@ namespace Umbraco.Cms.Core.Models /// /// Handles culture infos collection changes. /// - private void CultureInfosCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + private void CultureInfosCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { OnPropertyChanged(nameof(CultureInfos)); @@ -257,30 +257,42 @@ namespace Umbraco.Cms.Core.Models { case NotifyCollectionChangedAction.Add: { - var cultureInfo = e.NewItems.Cast().First(); + var cultureInfo = e.NewItems?.Cast().First(); if (_currentCultureChanges.addedCultures == null) _currentCultureChanges.addedCultures = new HashSet(StringComparer.InvariantCultureIgnoreCase); if (_currentCultureChanges.updatedCultures == null) _currentCultureChanges.updatedCultures = new HashSet(StringComparer.InvariantCultureIgnoreCase); - _currentCultureChanges.addedCultures.Add(cultureInfo.Culture); - _currentCultureChanges.updatedCultures.Add(cultureInfo.Culture); - _currentCultureChanges.removedCultures?.Remove(cultureInfo.Culture); + if (cultureInfo is not null) + { + _currentCultureChanges.addedCultures.Add(cultureInfo.Culture); + _currentCultureChanges.updatedCultures.Add(cultureInfo.Culture); + _currentCultureChanges.removedCultures?.Remove(cultureInfo.Culture); + } + break; } case NotifyCollectionChangedAction.Remove: { //remove listening for changes - var cultureInfo = e.OldItems.Cast().First(); + var cultureInfo = e.OldItems?.Cast().First(); if (_currentCultureChanges.removedCultures == null) _currentCultureChanges.removedCultures = new HashSet(StringComparer.InvariantCultureIgnoreCase); - _currentCultureChanges.removedCultures.Add(cultureInfo.Culture); - _currentCultureChanges.updatedCultures?.Remove(cultureInfo.Culture); - _currentCultureChanges.addedCultures?.Remove(cultureInfo.Culture); + if (cultureInfo is not null) + { + _currentCultureChanges.removedCultures.Add(cultureInfo.Culture); + _currentCultureChanges.updatedCultures?.Remove(cultureInfo.Culture); + _currentCultureChanges.addedCultures?.Remove(cultureInfo.Culture); + } + break; } case NotifyCollectionChangedAction.Replace: { //replace occurs when an Update occurs - var cultureInfo = e.NewItems.Cast().First(); + var cultureInfo = e.NewItems?.Cast().First(); if (_currentCultureChanges.updatedCultures == null) _currentCultureChanges.updatedCultures = new HashSet(StringComparer.InvariantCultureIgnoreCase); - _currentCultureChanges.updatedCultures.Add(cultureInfo.Culture); + if (cultureInfo is not null) + { + _currentCultureChanges.updatedCultures.Add(cultureInfo.Culture); + } + break; } } @@ -295,7 +307,7 @@ namespace Umbraco.Cms.Core.Models => Properties.Contains(propertyTypeAlias); /// - public object GetValue(string propertyTypeAlias, string? culture = null, string? segment = null, bool published = false) + public object? GetValue(string propertyTypeAlias, string? culture = null, string? segment = null, bool published = false) { return Properties.TryGetValue(propertyTypeAlias, out var property) ? property.GetValue(culture, segment, published) @@ -303,13 +315,13 @@ namespace Umbraco.Cms.Core.Models } /// - public TValue GetValue(string propertyTypeAlias, string? culture = null, string? segment = null, bool published = false) + public TValue? GetValue(string propertyTypeAlias, string? culture = null, string? segment = null, bool published = false) { if (!Properties.TryGetValue(propertyTypeAlias, out var property)) return default; var convertAttempt = property.GetValue(culture, segment, published).TryConvertTo(); - return convertAttempt.Success ? convertAttempt.Result : default; + return convertAttempt.Success is not null && convertAttempt.Success.Value ? convertAttempt.Result : default; } /// @@ -490,8 +502,12 @@ namespace Umbraco.Cms.Core.Models if (clonedContent._cultureInfos != null) { clonedContent._cultureInfos.ClearCollectionChangedEvents(); //clear this event handler if any - clonedContent._cultureInfos = (ContentCultureInfosCollection)_cultureInfos.DeepClone(); //manually deep clone - clonedContent._cultureInfos.CollectionChanged += clonedContent.CultureInfosCollectionChanged; //re-assign correct event handler + clonedContent._cultureInfos = (ContentCultureInfosCollection?)_cultureInfos?.DeepClone(); //manually deep clone + if (clonedContent._cultureInfos is not null) + { + clonedContent._cultureInfos.CollectionChanged += + clonedContent.CultureInfosCollectionChanged; //re-assign correct event handler + } } //if properties exist then deal with event bindings diff --git a/src/Umbraco.Core/Models/ContentCultureInfos.cs b/src/Umbraco.Core/Models/ContentCultureInfos.cs index ab7a0a8e37..47f0765d63 100644 --- a/src/Umbraco.Core/Models/ContentCultureInfos.cs +++ b/src/Umbraco.Core/Models/ContentCultureInfos.cs @@ -10,7 +10,7 @@ namespace Umbraco.Cms.Core.Models public class ContentCultureInfos : BeingDirtyBase, IDeepCloneable, IEquatable { private DateTime _date; - private string _name; + private string? _name; /// /// Initializes a new instance of the class. @@ -42,7 +42,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets the name. /// - public string Name + public string? Name { get => _name; set => SetPropertyValueAndDetectChanges(value, ref _name, nameof(Name)); @@ -64,13 +64,13 @@ namespace Umbraco.Cms.Core.Models } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is ContentCultureInfos other && Equals(other); } /// - public bool Equals(ContentCultureInfos other) + public bool Equals(ContentCultureInfos? other) { return other != null && Culture == other.Culture && Name == other.Name; } @@ -80,14 +80,18 @@ namespace Umbraco.Cms.Core.Models { var hashCode = 479558943; hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(Culture); - hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(Name); + if (Name is not null) + { + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(Name); + } + return hashCode; } /// /// Deconstructs into culture and name. /// - public void Deconstruct(out string culture, out string name) + public void Deconstruct(out string culture, out string? name) { culture = Culture; name = Name; @@ -96,7 +100,7 @@ namespace Umbraco.Cms.Core.Models /// /// Deconstructs into culture, name and date. /// - public void Deconstruct(out string culture, out string name, out DateTime date) + public void Deconstruct(out string culture, out string? name, out DateTime date) { Deconstruct(out culture, out name); date = Date; diff --git a/src/Umbraco.Core/Models/ContentCultureInfosCollection.cs b/src/Umbraco.Core/Models/ContentCultureInfosCollection.cs index 03dde33a1a..0d480ede6d 100644 --- a/src/Umbraco.Core/Models/ContentCultureInfosCollection.cs +++ b/src/Umbraco.Core/Models/ContentCultureInfosCollection.cs @@ -19,7 +19,7 @@ namespace Umbraco.Cms.Core.Models /// /// Adds or updates a instance. /// - public void AddOrUpdate(string culture, string name, DateTime date) + public void AddOrUpdate(string culture, string? name, DateTime date) { if (culture == null) throw new ArgumentNullException(nameof(culture)); if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(culture)); diff --git a/src/Umbraco.Core/Models/ContentEditing/AuditLog.cs b/src/Umbraco.Core/Models/ContentEditing/AuditLog.cs index 3ade6e864d..5f40ace6ca 100644 --- a/src/Umbraco.Core/Models/ContentEditing/AuditLog.cs +++ b/src/Umbraco.Core/Models/ContentEditing/AuditLog.cs @@ -10,10 +10,10 @@ namespace Umbraco.Cms.Core.Models.ContentEditing public int UserId { get; set; } [DataMember(Name = "userName")] - public string UserName { get; set; } + public string? UserName { get; set; } [DataMember(Name = "userAvatars")] - public string[] UserAvatars { get; set; } + public string[]? UserAvatars { get; set; } [DataMember(Name = "nodeId")] public int NodeId { get; set; } @@ -22,15 +22,15 @@ namespace Umbraco.Cms.Core.Models.ContentEditing public DateTime Timestamp { get; set; } [DataMember(Name = "logType")] - public string LogType { get; set; } + public string? LogType { get; set; } [DataMember(Name = "entityType")] - public string EntityType { get; set; } + public string? EntityType { get; set; } [DataMember(Name = "comment")] - public string Comment { get; set; } + public string? Comment { get; set; } [DataMember(Name = "parameters")] - public string Parameters { get; set; } + public string? Parameters { get; set; } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/BackOfficeNotification.cs b/src/Umbraco.Core/Models/ContentEditing/BackOfficeNotification.cs index 22d97b8a22..982f46d912 100644 --- a/src/Umbraco.Core/Models/ContentEditing/BackOfficeNotification.cs +++ b/src/Umbraco.Core/Models/ContentEditing/BackOfficeNotification.cs @@ -18,10 +18,10 @@ namespace Umbraco.Cms.Core.Models.ContentEditing } [DataMember(Name = "header")] - public string Header { get; set; } + public string? Header { get; set; } [DataMember(Name = "message")] - public string Message { get; set; } + public string? Message { get; set; } [DataMember(Name = "type")] public NotificationStyle NotificationType { get; set; } diff --git a/src/Umbraco.Core/Models/ContentEditing/CodeFileDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/CodeFileDisplay.cs index 49dfa9dd22..37243c702c 100644 --- a/src/Umbraco.Core/Models/ContentEditing/CodeFileDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/CodeFileDisplay.cs @@ -19,7 +19,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// /views/partials/file.cshtml /// [DataMember(Name = "virtualPath", IsRequired = true)] - public string VirtualPath { get; set; } + public string? VirtualPath { get; set; } /// /// Path represents the path used by the backoffice tree @@ -30,24 +30,24 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// [DataMember(Name = "path")] [ReadOnly(true)] - public string Path { get; set; } + public string? Path { get; set; } [DataMember(Name = "name", IsRequired = true)] - public string Name { get; set; } + public string? Name { get; set; } [DataMember(Name = "content", IsRequired = true)] - public string Content { get; set; } + public string? Content { get; set; } [DataMember(Name = "fileType", IsRequired = true)] - public string FileType { get; set; } + public string? FileType { get; set; } [DataMember(Name = "snippet")] [ReadOnly(true)] - public string Snippet { get; set; } + public string? Snippet { get; set; } [DataMember(Name = "id")] [ReadOnly(true)] - public string Id { get; set; } + public string? Id { get; set; } public List Notifications { get; private set; } @@ -59,7 +59,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing public IEnumerable Validate(ValidationContext validationContext) { var illegalChars = System.IO.Path.GetInvalidFileNameChars(); - if (Name.ContainsAny(illegalChars)) + if (Name?.ContainsAny(illegalChars) ?? false) { yield return new ValidationResult( "The file name cannot contain illegal characters", diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentBaseSave.cs b/src/Umbraco.Core/Models/ContentEditing/ContentBaseSave.cs index b1bebf1731..294dc3386e 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentBaseSave.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentBaseSave.cs @@ -36,11 +36,11 @@ namespace Umbraco.Cms.Core.Models.ContentEditing //These need explicit implementation because we are using internal models /// [IgnoreDataMember] - TPersisted IContentSave.PersistedContent { get; set; } + TPersisted? IContentSave.PersistedContent { get; set; } //Non explicit internal getter so we don't need to explicitly cast in our own code [IgnoreDataMember] - public TPersisted PersistedContent + public TPersisted? PersistedContent { get => ((IContentSave)this).PersistedContent; set => ((IContentSave) this).PersistedContent = value; @@ -55,7 +55,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// This is not used for outgoing model information. /// [IgnoreDataMember] - public ContentPropertyCollectionDto PropertyCollectionDto { get; set; } + public ContentPropertyCollectionDto? PropertyCollectionDto { get; set; } #endregion } diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentItemBasic.cs b/src/Umbraco.Core/Models/ContentEditing/ContentItemBasic.cs index 12dab25a9e..2c9e498a85 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentItemBasic.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentItemBasic.cs @@ -31,16 +31,16 @@ namespace Umbraco.Cms.Core.Models.ContentEditing public bool Edited { get; set; } [DataMember(Name = "owner")] - public UserProfile Owner { get; set; } + public UserProfile? Owner { get; set; } [DataMember(Name = "updater")] - public UserProfile Updater { get; set; } + public UserProfile? Updater { get; set; } public int ContentTypeId { get; set; } [DataMember(Name = "contentTypeAlias", IsRequired = true)] [Required(AllowEmptyStrings = false)] - public string ContentTypeAlias { get; set; } + public string? ContentTypeAlias { get; set; } [DataMember(Name = "sortOrder")] public int SortOrder { get; set; } @@ -62,7 +62,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing return 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; @@ -72,7 +72,12 @@ namespace Umbraco.Cms.Core.Models.ContentEditing public override int GetHashCode() { - return Id.GetHashCode(); + if (Id is not null) + { + return Id.GetHashCode(); + } + + return base.GetHashCode(); } } diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentItemDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/ContentItemDisplay.cs index 23d5fbc2fd..f2088715a9 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentItemDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentItemDisplay.cs @@ -33,10 +33,10 @@ namespace Umbraco.Cms.Core.Models.ContentEditing [DataMember(Name = "udi")] [ReadOnly(true)] - public Udi Udi { get; set; } + public Udi? Udi { get; set; } [DataMember(Name = "icon")] - public string Icon { get; set; } + public string? Icon { get; set; } [DataMember(Name = "trashed")] [ReadOnly(true)] @@ -46,17 +46,17 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// This is the unique Id stored in the database - but could also be the unique id for a custom membership provider /// [DataMember(Name = "key")] - public Guid Key { get; set; } + public Guid? Key { get; set; } [DataMember(Name = "parentId", IsRequired = true)] [Required] - public int ParentId { get; set; } + public int? ParentId { get; set; } /// /// The path of the entity /// [DataMember(Name = "path")] - public string Path { get; set; } + public string? Path { get; set; } /// /// A collection of content variants @@ -65,19 +65,19 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// If a content item is invariant, this collection will only contain one item, else it will contain all culture variants /// [DataMember(Name = "variants")] - public IEnumerable Variants { get; set; } + public IEnumerable? Variants { get; set; } [DataMember(Name = "owner")] - public UserProfile Owner { get; set; } + public UserProfile? Owner { get; set; } [DataMember(Name = "updater")] - public UserProfile Updater { get; set; } + public UserProfile? Updater { get; set; } /// /// The name of the content type /// [DataMember(Name = "contentTypeName")] - public string ContentTypeName { get; set; } + public string? ContentTypeName { get; set; } /// /// Indicates if the content is configured as a list view container @@ -105,17 +105,17 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// so the app will need to go fetch the individual tree node in order to be able to load it's action list (menu) /// [DataMember(Name = "treeNodeUrl")] - public string TreeNodeUrl { get; set; } + public string? TreeNodeUrl { get; set; } [DataMember(Name = "contentTypeId")] - public int ContentTypeId { get; set; } + public int? ContentTypeId { get; set; } [DataMember(Name = "contentTypeKey")] public Guid ContentTypeKey { get; set; } [DataMember(Name = "contentTypeAlias", IsRequired = true)] [Required(AllowEmptyStrings = false)] - public string ContentTypeAlias { get; set; } + public string? ContentTypeAlias { get; set; } [DataMember(Name = "sortOrder")] public int SortOrder { get; set; } @@ -130,19 +130,19 @@ namespace Umbraco.Cms.Core.Models.ContentEditing public DateTime UpdateDate { get; set; } [DataMember(Name = "template")] - public string TemplateAlias { get; set; } + public string? TemplateAlias { get; set; } [DataMember(Name = "templateId")] public int TemplateId { get; set; } [DataMember(Name = "allowedTemplates")] - public IDictionary AllowedTemplates { get; set; } + public IDictionary? AllowedTemplates { get; set; } [DataMember(Name = "documentType")] - public ContentTypeBasic DocumentType { get; set; } + public ContentTypeBasic? DocumentType { get; set; } [DataMember(Name = "urls")] - public UrlInfo[] Urls { get; set; } + public UrlInfo[]? Urls { get; set; } /// /// Determines whether previewing is allowed for this node @@ -160,7 +160,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// Each char represents a button which we can then map on the front-end to the correct actions /// [DataMember(Name = "allowedActions")] - public IEnumerable AllowedActions { get; set; } + public IEnumerable? AllowedActions { get; set; } [DataMember(Name = "isBlueprint")] public bool IsBlueprint { get; set; } @@ -175,7 +175,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// This is not used for outgoing model information. /// [IgnoreDataMember] - public IContent PersistedContent { get; set; } + public IContent? PersistedContent { get; set; } /// /// The DTO object used to gather all required content data including data type information etc... for use with validation - used during inbound model binding @@ -186,7 +186,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// This is not used for outgoing model information. /// [IgnoreDataMember] - public ContentPropertyCollectionDto ContentDto { get; set; } + public ContentPropertyCollectionDto? ContentDto { get; set; } /// /// This is used to add custom localized messages/strings to the response for the app to use for localized UI purposes. @@ -214,6 +214,6 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// [DataMember(Name = "metaData")] [ReadOnly(true)] - public IDictionary AdditionalData { get; private set; } + public IDictionary? AdditionalData { get; private set; } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentItemDisplayBase.cs b/src/Umbraco.Core/Models/ContentEditing/ContentItemDisplayBase.cs index d992e3da9a..a06fa62b1a 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentItemDisplayBase.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentItemDisplayBase.cs @@ -17,7 +17,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// The name of the content type /// [DataMember(Name = "contentTypeName")] - public string ContentTypeName { get; set; } + public string? ContentTypeName { get; set; } /// /// Indicates if the content is configured as a list view container diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentItemSave.cs b/src/Umbraco.Core/Models/ContentEditing/ContentItemSave.cs index 9207a70a0a..622276cecf 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentItemSave.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentItemSave.cs @@ -30,13 +30,13 @@ namespace Umbraco.Cms.Core.Models.ContentEditing [DataMember(Name = "contentTypeAlias", IsRequired = true)] [Required(AllowEmptyStrings = false)] - public string ContentTypeAlias { get; set; } + public string? ContentTypeAlias { get; set; } /// /// The template alias to save /// [DataMember(Name = "templateAlias")] - public string TemplateAlias { get; set; } + public string? TemplateAlias { get; set; } #region IContentSave @@ -50,11 +50,11 @@ namespace Umbraco.Cms.Core.Models.ContentEditing //These need explicit implementation because we are using internal models /// [IgnoreDataMember] - IContent IContentSave.PersistedContent { get; set; } + IContent? IContentSave.PersistedContent { get; set; } //Non explicit internal getter so we don't need to explicitly cast in our own code [IgnoreDataMember] - public IContent PersistedContent + public IContent? PersistedContent { get => ((IContentSave)this).PersistedContent; set => ((IContentSave)this).PersistedContent = value; diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentPropertyDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/ContentPropertyDisplay.cs index fe953850b0..a174de7a13 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentPropertyDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentPropertyDisplay.cs @@ -18,14 +18,14 @@ namespace Umbraco.Cms.Core.Models.ContentEditing [DataMember(Name = "label", IsRequired = true)] [Required] - public string Label { get; set; } + public string? Label { get; set; } [DataMember(Name = "description")] - public string Description { get; set; } + public string? Description { get; set; } [DataMember(Name = "view", IsRequired = true)] [Required(AllowEmptyStrings = false)] - public string View { get; set; } + public string? View { get; set; } [DataMember(Name = "config")] public IDictionary Config { get; set; } diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentPropertyDto.cs b/src/Umbraco.Core/Models/ContentEditing/ContentPropertyDto.cs index fd24964f27..e12a7bbdba 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentPropertyDto.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentPropertyDto.cs @@ -5,20 +5,20 @@ /// public class ContentPropertyDto : ContentPropertyBasic { - public IDataType DataType { get; set; } + public IDataType? DataType { get; set; } - public string Label { get; set; } + public string? Label { get; set; } - public string Description { get; set; } + public string? Description { get; set; } - public bool IsRequired { get; set; } + public bool? IsRequired { get; set; } public bool LabelOnTop { get; set; } - public string IsRequiredMessage { get; set; } + public string? IsRequiredMessage { get; set; } - public string ValidationRegExp { get; set; } + public string? ValidationRegExp { get; set; } - public string ValidationRegExpMessage { get; set; } + public string? ValidationRegExpMessage { get; set; } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentRedirectUrl.cs b/src/Umbraco.Core/Models/ContentEditing/ContentRedirectUrl.cs index e509ff5db1..99ea69b364 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentRedirectUrl.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentRedirectUrl.cs @@ -10,10 +10,10 @@ namespace Umbraco.Cms.Core.Models.ContentEditing public Guid RedirectId { get; set; } [DataMember(Name = "originalUrl")] - public string OriginalUrl { get; set; } + public string? OriginalUrl { get; set; } [DataMember(Name = "destinationUrl")] - public string DestinationUrl { get; set; } + public string? DestinationUrl { get; set; } [DataMember(Name = "createDateUtc")] public DateTime CreateDateUtc { get; set; } @@ -22,6 +22,6 @@ namespace Umbraco.Cms.Core.Models.ContentEditing public int ContentId { get; set; } [DataMember(Name = "culture")] - public string Culture { get; set; } + public string? Culture { get; set; } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentTypeBasic.cs b/src/Umbraco.Core/Models/ContentEditing/ContentTypeBasic.cs index dc3e455fb0..f46d8dc8f8 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentTypeBasic.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentTypeBasic.cs @@ -19,6 +19,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing public ContentTypeBasic() { Blueprints = new Dictionary(); + Alias = string.Empty; } /// @@ -38,10 +39,10 @@ namespace Umbraco.Cms.Core.Models.ContentEditing public DateTime CreateDate { get; set; } [DataMember(Name = "description")] - public string Description { get; set; } + public string? Description { get; set; } [DataMember(Name = "thumbnail")] - public string Thumbnail { get; set; } + public string? Thumbnail { get; set; } /// /// Returns true if the icon represents a CSS class instead of a file path @@ -57,7 +58,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing return true; } //if it starts with a '.' or doesn't contain a '.' at all then it is a class - return Icon.StartsWith(".") || Icon.Contains(".") == false; + return (Icon?.StartsWith(".") ?? false) || Icon?.Contains(".") == false; } } @@ -66,7 +67,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// [DataMember(Name = "iconFilePath")] [ReadOnly(true)] - public string IconFilePath { get; set; } + public string? IconFilePath { get; set; } /// /// Returns true if the icon represents a CSS class instead of a file path @@ -82,7 +83,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing return true; } //if it starts with a '.' or doesn't contain a '.' at all then it is a class - return Thumbnail.StartsWith(".") || Thumbnail.Contains(".") == false; + return (Thumbnail?.StartsWith(".") ?? false) || Thumbnail?.Contains(".") == false; } } @@ -91,7 +92,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// [DataMember(Name = "thumbnailFilePath")] [ReadOnly(true)] - public string ThumbnailFilePath { get; set; } + public string? ThumbnailFilePath { get; set; } [DataMember(Name = "blueprints")] [ReadOnly(true)] diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentTypeCompositionDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/ContentTypeCompositionDisplay.cs index 0ff43178c9..4eb8563a6e 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentTypeCompositionDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentTypeCompositionDisplay.cs @@ -18,19 +18,19 @@ namespace Umbraco.Cms.Core.Models.ContentEditing [DataMember(Name = "listViewEditorName")] [ReadOnly(true)] - public string ListViewEditorName { get; set; } + public string? ListViewEditorName { get; set; } //Allowed child types [DataMember(Name = "allowedContentTypes")] - public IEnumerable AllowedContentTypes { get; set; } + public IEnumerable? AllowedContentTypes { get; set; } //Compositions [DataMember(Name = "compositeContentTypes")] - public IEnumerable CompositeContentTypes { get; set; } + public IEnumerable CompositeContentTypes { get; set; } //Locked compositions [DataMember(Name = "lockedCompositeContentTypes")] - public IEnumerable LockedCompositeContentTypes { get; set; } + public IEnumerable? LockedCompositeContentTypes { get; set; } [DataMember(Name = "allowAsRoot")] public bool AllowAsRoot { get; set; } @@ -54,7 +54,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// [DataMember(Name = "ModelState")] [ReadOnly(true)] - public IDictionary Errors { get; set; } + public IDictionary? Errors { get; set; } } [DataContract(Name = "contentType", Namespace = "")] diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentTypeSave.cs b/src/Umbraco.Core/Models/ContentEditing/ContentTypeSave.cs index 6198f0c664..55c4a07cfd 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentTypeSave.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentTypeSave.cs @@ -30,7 +30,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing public IEnumerable AllowedContentTypes { get; set; } [DataMember(Name = "historyCleanup")] - public HistoryCleanupViewModel HistoryCleanup { get; set; } + public HistoryCleanupViewModel? HistoryCleanup { get; set; } /// /// Custom validation diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentVariantSave.cs b/src/Umbraco.Core/Models/ContentEditing/ContentVariantSave.cs index cc8e8b9493..f7ea69f7ce 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentVariantSave.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentVariantSave.cs @@ -17,7 +17,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing [DataMember(Name = "name", IsRequired = true)] [RequiredForPersistence(AllowEmptyStrings = false, ErrorMessage = "Required")] [MaxLength(255, ErrorMessage ="Name must be less than 255 characters")] - public string Name { get; set; } + public string? Name { get; set; } [DataMember(Name = "properties")] public IEnumerable Properties { get; set; } @@ -26,13 +26,13 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// The culture of this variant, if this is invariant than this is null or empty /// [DataMember(Name = "culture")] - public string Culture { get; set; } + public string? Culture { get; set; } /// /// The segment of this variant, if this is invariant than this is null or empty /// [DataMember(Name = "segment")] - public string Segment { get; set; } + public string? Segment { get; set; } /// /// Indicates if the variant should be updated @@ -68,6 +68,6 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// This is not used for outgoing model information. /// [IgnoreDataMember] - public ContentPropertyCollectionDto PropertyCollectionDto { get; set; } + public ContentPropertyCollectionDto? PropertyCollectionDto { get; set; } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentVariationDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/ContentVariationDisplay.cs index 70e025a865..44f0b31c25 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentVariationDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentVariationDisplay.cs @@ -19,10 +19,10 @@ namespace Umbraco.Cms.Core.Models.ContentEditing } [DataMember(Name = "name", IsRequired = true)] - public string Name { get; set; } + public string? Name { get; set; } [DataMember(Name = "displayName")] - public string DisplayName { get; set; } + public string? DisplayName { get; set; } /// /// Defines the tabs containing display properties @@ -34,7 +34,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// Internal property used for tests to get all properties from all tabs /// [IgnoreDataMember] - IEnumerable IContentProperties.Properties => Tabs.SelectMany(x => x.Properties); + IEnumerable IContentProperties.Properties => Tabs.Where(x => x.Properties is not null).SelectMany(x => x.Properties!); /// /// The language/culture assigned to this content variation @@ -43,10 +43,10 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// If this is null it means this content variant is an invariant culture /// [DataMember(Name = "language")] - public Language Language { get; set; } + public Language? Language { get; set; } [DataMember(Name = "segment")] - public string Segment { get; set; } + public string? Segment { get; set; } [DataMember(Name = "state")] public ContentSavedState State { get; set; } diff --git a/src/Umbraco.Core/Models/ContentEditing/DataTypeDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/DataTypeDisplay.cs index a30490582f..cbe5552b1e 100644 --- a/src/Umbraco.Core/Models/ContentEditing/DataTypeDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/DataTypeDisplay.cs @@ -20,13 +20,13 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// [DataMember(Name = "selectedEditor", IsRequired = true)] [Required] - public string SelectedEditor { get; set; } + public string? SelectedEditor { get; set; } [DataMember(Name = "availableEditors")] - public IEnumerable AvailableEditors { get; set; } + public IEnumerable? AvailableEditors { get; set; } [DataMember(Name = "preValues")] - public IEnumerable PreValues { get; set; } + public IEnumerable? PreValues { get; set; } /// /// This is used to add custom localized messages/strings to the response for the app to use for localized UI purposes. diff --git a/src/Umbraco.Core/Models/ContentEditing/DictionaryOverviewDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/DictionaryOverviewDisplay.cs index f67163d7a1..adf279c412 100644 --- a/src/Umbraco.Core/Models/ContentEditing/DictionaryOverviewDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/DictionaryOverviewDisplay.cs @@ -21,7 +21,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// Gets or sets the key. /// [DataMember(Name = "name")] - public string Name { get; set; } + public string? Name { get; set; } /// /// Gets or sets the id. diff --git a/src/Umbraco.Core/Models/ContentEditing/DictionaryOverviewTranslationDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/DictionaryOverviewTranslationDisplay.cs index e5948ecf4a..00d8b339f9 100644 --- a/src/Umbraco.Core/Models/ContentEditing/DictionaryOverviewTranslationDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/DictionaryOverviewTranslationDisplay.cs @@ -12,7 +12,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// Gets or sets the display name. /// [DataMember(Name = "displayName")] - public string DisplayName { get; set; } + public string? DisplayName { get; set; } /// /// Gets or sets a value indicating whether has translation. diff --git a/src/Umbraco.Core/Models/ContentEditing/DictionaryTranslationDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/DictionaryTranslationDisplay.cs index 901afaa3bc..4ad4002b77 100644 --- a/src/Umbraco.Core/Models/ContentEditing/DictionaryTranslationDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/DictionaryTranslationDisplay.cs @@ -13,6 +13,6 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// Gets or sets the display name. /// [DataMember(Name = "displayName")] - public string DisplayName { get; set; } + public string? DisplayName { get; set; } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/DictionaryTranslationSave.cs b/src/Umbraco.Core/Models/ContentEditing/DictionaryTranslationSave.cs index 00332248e6..b86d6cf6e2 100644 --- a/src/Umbraco.Core/Models/ContentEditing/DictionaryTranslationSave.cs +++ b/src/Umbraco.Core/Models/ContentEditing/DictionaryTranslationSave.cs @@ -12,13 +12,13 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// Gets or sets the ISO code. /// [DataMember(Name = "isoCode")] - public string IsoCode { get; set; } + public string? IsoCode { get; set; } /// /// Gets or sets the translation. /// [DataMember(Name = "translation")] - public string Translation { get; set; } + public string? Translation { get; set; } /// /// Gets or sets the language id. diff --git a/src/Umbraco.Core/Models/ContentEditing/DocumentTypeDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/DocumentTypeDisplay.cs index 3bb52c39b7..6f56c92292 100644 --- a/src/Umbraco.Core/Models/ContentEditing/DocumentTypeDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/DocumentTypeDisplay.cs @@ -17,7 +17,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing public IEnumerable AllowedTemplates { get; set; } [DataMember(Name = "defaultTemplate")] - public EntityBasic DefaultTemplate { get; set; } + public EntityBasic? DefaultTemplate { get; set; } [DataMember(Name = "allowCultureVariant")] public bool AllowCultureVariant { get; set; } @@ -26,9 +26,9 @@ namespace Umbraco.Cms.Core.Models.ContentEditing public bool AllowSegmentVariant { get; set; } [DataMember(Name = "apps")] - public IEnumerable ContentApps { get; set; } + public IEnumerable? ContentApps { get; set; } [DataMember(Name = "historyCleanup")] - public HistoryCleanupViewModel HistoryCleanup { get; set; } + public HistoryCleanupViewModel? HistoryCleanup { get; set; } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/DomainDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/DomainDisplay.cs index 49ed898f3b..573909a610 100644 --- a/src/Umbraco.Core/Models/ContentEditing/DomainDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/DomainDisplay.cs @@ -21,6 +21,6 @@ namespace Umbraco.Cms.Core.Models.ContentEditing public bool Duplicate { get; set; } [DataMember(Name = "other")] - public string Other { get; set; } + public string? Other { get; set; } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/EntityBasic.cs b/src/Umbraco.Core/Models/ContentEditing/EntityBasic.cs index b923beabaf..32477f2443 100644 --- a/src/Umbraco.Core/Models/ContentEditing/EntityBasic.cs +++ b/src/Umbraco.Core/Models/ContentEditing/EntityBasic.cs @@ -13,22 +13,23 @@ namespace Umbraco.Cms.Core.Models.ContentEditing public EntityBasic() { AdditionalData = new Dictionary(); + Alias = string.Empty; } [DataMember(Name = "name", IsRequired = true)] [RequiredForPersistence(AllowEmptyStrings = false, ErrorMessage = "Required")] - public string Name { get; set; } + public string? Name { get; set; } [DataMember(Name = "id", IsRequired = true)] [Required] - public object Id { get; set; } + public object? Id { get; set; } [DataMember(Name = "udi")] [ReadOnly(true)] - public Udi Udi { get; set; } + public Udi? Udi { get; set; } [DataMember(Name = "icon")] - public string Icon { get; set; } + public string? Icon { get; set; } [DataMember(Name = "trashed")] [ReadOnly(true)] @@ -57,7 +58,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// The path of the entity /// [DataMember(Name = "path")] - public string Path { get; set; } + public string? Path { get; set; } /// /// A collection of extra data that is available for this specific entity/entity type /// diff --git a/src/Umbraco.Core/Models/ContentEditing/IContentSave.cs b/src/Umbraco.Core/Models/ContentEditing/IContentSave.cs index dfaf183479..a6c500e820 100644 --- a/src/Umbraco.Core/Models/ContentEditing/IContentSave.cs +++ b/src/Umbraco.Core/Models/ContentEditing/IContentSave.cs @@ -18,6 +18,6 @@ /// /// This is not used for outgoing model information. /// - TPersisted PersistedContent { get; set; } + TPersisted? PersistedContent { get; set; } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/INotificationModel.cs b/src/Umbraco.Core/Models/ContentEditing/INotificationModel.cs index 5bc9996f6b..ac104c0e1b 100644 --- a/src/Umbraco.Core/Models/ContentEditing/INotificationModel.cs +++ b/src/Umbraco.Core/Models/ContentEditing/INotificationModel.cs @@ -9,6 +9,6 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// This is used to add custom localized messages/strings to the response for the app to use for localized UI purposes. /// [DataMember(Name = "notifications")] - List Notifications { get; } + List? Notifications { get; } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/Language.cs b/src/Umbraco.Core/Models/ContentEditing/Language.cs index 617b18bb6e..bc9aa6f881 100644 --- a/src/Umbraco.Core/Models/ContentEditing/Language.cs +++ b/src/Umbraco.Core/Models/ContentEditing/Language.cs @@ -12,11 +12,11 @@ namespace Umbraco.Cms.Core.Models.ContentEditing [DataMember(Name = "culture", IsRequired = true)] [Required(AllowEmptyStrings = false)] - public string IsoCode { get; set; } + public string? IsoCode { get; set; } [DataMember(Name = "name")] [ReadOnly(true)] - public string Name { get; set; } + public string? Name { get; set; } [DataMember(Name = "isDefault")] public bool IsDefault { get; set; } diff --git a/src/Umbraco.Core/Models/ContentEditing/MacroDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/MacroDisplay.cs index d5d363057f..5cb65c00cc 100644 --- a/src/Umbraco.Core/Models/ContentEditing/MacroDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/MacroDisplay.cs @@ -56,7 +56,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// Gets or sets the view. /// [DataMember(Name = "view")] - public string View { get; set; } + public string? View { get; set; } /// /// Gets or sets the parameters. diff --git a/src/Umbraco.Core/Models/ContentEditing/MacroParameter.cs b/src/Umbraco.Core/Models/ContentEditing/MacroParameter.cs index 19949e9d68..a53dc2069a 100644 --- a/src/Umbraco.Core/Models/ContentEditing/MacroParameter.cs +++ b/src/Umbraco.Core/Models/ContentEditing/MacroParameter.cs @@ -15,7 +15,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing public string Alias { get; set; } [DataMember(Name = "name")] - public string Name { get; set; } + public string? Name { get; set; } [DataMember(Name = "sortOrder")] public int SortOrder { get; set; } diff --git a/src/Umbraco.Core/Models/ContentEditing/MediaItemDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/MediaItemDisplay.cs index c20337f68d..a56911f707 100644 --- a/src/Umbraco.Core/Models/ContentEditing/MediaItemDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/MediaItemDisplay.cs @@ -15,10 +15,10 @@ namespace Umbraco.Cms.Core.Models.ContentEditing } [DataMember(Name = "contentType")] - public ContentTypeBasic ContentType { get; set; } + public ContentTypeBasic? ContentType { get; set; } [DataMember(Name = "mediaLink")] - public string MediaLink { get; set; } + public string? MediaLink { get; set; } [DataMember(Name = "apps")] public IEnumerable ContentApps { get; set; } diff --git a/src/Umbraco.Core/Models/ContentEditing/MemberDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/MemberDisplay.cs index 809e47e073..1b2aadd69f 100644 --- a/src/Umbraco.Core/Models/ContentEditing/MemberDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/MemberDisplay.cs @@ -16,13 +16,13 @@ namespace Umbraco.Cms.Core.Models.ContentEditing } [DataMember(Name = "contentType")] - public ContentTypeBasic ContentType { get; set; } + public ContentTypeBasic? ContentType { get; set; } [DataMember(Name = "username")] - public string Username { get; set; } + public string? Username { get; set; } [DataMember(Name = "email")] - public string Email { get; set; } + public string? Email { get; set; } //[DataMember(Name = "membershipScenario")] //public MembershipScenario MembershipScenario { get; set; } @@ -40,6 +40,6 @@ namespace Umbraco.Cms.Core.Models.ContentEditing [DataMember(Name = "membershipProperties")] - public IEnumerable MembershipProperties { get; set; } + public IEnumerable? MembershipProperties { get; set; } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/MemberSave.cs b/src/Umbraco.Core/Models/ContentEditing/MemberSave.cs index 6b5c0096a0..e5c864781d 100644 --- a/src/Umbraco.Core/Models/ContentEditing/MemberSave.cs +++ b/src/Umbraco.Core/Models/ContentEditing/MemberSave.cs @@ -13,23 +13,23 @@ namespace Umbraco.Cms.Core.Models.ContentEditing [DataMember(Name = "username", IsRequired = true)] [RequiredForPersistence(AllowEmptyStrings = false, ErrorMessage = "Required")] - public string Username { get; set; } + public string? Username { get; set; } [DataMember(Name = "email", IsRequired = true)] [RequiredForPersistence(AllowEmptyStrings = false, ErrorMessage = "Required")] [EmailAddress] - public string Email { get; set; } + public string? Email { get; set; } [DataMember(Name = "password")] - public ChangingPasswordModel Password { get; set; } + public ChangingPasswordModel? Password { get; set; } [DataMember(Name = "memberGroups")] - public IEnumerable Groups { get; set; } + public IEnumerable? Groups { get; set; } /// /// Returns the value from the Comments property /// - public string Comments => GetPropertyValue(Constants.Conventions.Member.Comments); + public string? Comments => GetPropertyValue(Constants.Conventions.Member.Comments); /// /// Returns the value from the IsLockedOut property @@ -41,7 +41,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// public bool IsApproved => GetPropertyValue(Constants.Conventions.Member.IsApproved); - private T GetPropertyValue(string alias) + private T? GetPropertyValue(string alias) { var prop = Properties.FirstOrDefault(x => x.Alias == alias); if (prop == null) return default; diff --git a/src/Umbraco.Core/Models/ContentEditing/MessagesExtensions.cs b/src/Umbraco.Core/Models/ContentEditing/MessagesExtensions.cs index 0026dcc21e..293693b2f7 100644 --- a/src/Umbraco.Core/Models/ContentEditing/MessagesExtensions.cs +++ b/src/Umbraco.Core/Models/ContentEditing/MessagesExtensions.cs @@ -9,7 +9,7 @@ namespace Umbraco.Extensions { if (model.Exists(header, msg, type)) return; - model.Notifications.Add(new BackOfficeNotification() + model.Notifications?.Add(new BackOfficeNotification() { Header = header, Message = msg, @@ -21,7 +21,7 @@ namespace Umbraco.Extensions { if (model.Exists(header, msg, NotificationStyle.Success)) return; - model.Notifications.Add(new BackOfficeNotification() + model.Notifications?.Add(new BackOfficeNotification() { Header = header, Message = msg, @@ -33,7 +33,7 @@ namespace Umbraco.Extensions { if (model.Exists(header, msg, NotificationStyle.Error)) return; - model.Notifications.Add(new BackOfficeNotification() + model.Notifications?.Add(new BackOfficeNotification() { Header = header, Message = msg, @@ -45,7 +45,7 @@ namespace Umbraco.Extensions { if (model.Exists(header, msg, NotificationStyle.Warning)) return; - model.Notifications.Add(new BackOfficeNotification() + model.Notifications?.Add(new BackOfficeNotification() { Header = header, Message = msg, @@ -57,7 +57,7 @@ namespace Umbraco.Extensions { if (model.Exists(header, msg, NotificationStyle.Info)) return; - model.Notifications.Add(new BackOfficeNotification() + model.Notifications?.Add(new BackOfficeNotification() { Header = header, Message = msg, @@ -65,6 +65,6 @@ namespace Umbraco.Extensions }); } - private static bool Exists(this INotificationModel model, string header, string message, NotificationStyle notificationType) => model.Notifications.Any(x => x.Header.InvariantEquals(header) && x.Message.InvariantEquals(message) && x.NotificationType == notificationType); + private static bool Exists(this INotificationModel model, string header, string message, NotificationStyle notificationType) => model.Notifications?.Any(x => (x.Header?.InvariantEquals(header) ?? false) && (x.Message?.InvariantEquals(message) ?? false) && x.NotificationType == notificationType) ?? false; } } diff --git a/src/Umbraco.Core/Models/ContentEditing/PropertyGroupDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/PropertyGroupDisplay.cs index 6c4d234abe..a543d85347 100644 --- a/src/Umbraco.Core/Models/ContentEditing/PropertyGroupDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/PropertyGroupDisplay.cs @@ -34,6 +34,6 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// [DataMember(Name = "parentTabContentTypeNames")] [ReadOnly(true)] - public IEnumerable ParentTabContentTypeNames { get; set; } + public IEnumerable ParentTabContentTypeNames { get; set; } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/PropertyTypeBasic.cs b/src/Umbraco.Core/Models/ContentEditing/PropertyTypeBasic.cs index 3b2a3aa37b..6752507de4 100644 --- a/src/Umbraco.Core/Models/ContentEditing/PropertyTypeBasic.cs +++ b/src/Umbraco.Core/Models/ContentEditing/PropertyTypeBasic.cs @@ -28,14 +28,14 @@ namespace Umbraco.Cms.Core.Models.ContentEditing public string Alias { get; set; } [DataMember(Name = "description")] - public string Description { get; set; } + public string? Description { get; set; } [DataMember(Name = "validation")] - public PropertyTypeValidation Validation { get; set; } + public PropertyTypeValidation? Validation { get; set; } [DataMember(Name = "label")] [Required] - public string Label { get; set; } + public string? Label { get; set; } [DataMember(Name = "sortOrder")] public int SortOrder { get; set; } @@ -50,11 +50,11 @@ namespace Umbraco.Cms.Core.Models.ContentEditing [DataMember(Name = "dataTypeName")] [ReadOnly(true)] - public string DataTypeName { get; set; } + public string? DataTypeName { get; set; } [DataMember(Name = "dataTypeIcon")] [ReadOnly(true)] - public string DataTypeIcon { get; set; } + public string? DataTypeIcon { get; set; } //SD: Is this really needed ? [DataMember(Name = "groupId")] diff --git a/src/Umbraco.Core/Models/ContentEditing/PropertyTypeDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/PropertyTypeDisplay.cs index 20a8cbe2e8..5ca3e4de5c 100644 --- a/src/Umbraco.Core/Models/ContentEditing/PropertyTypeDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/PropertyTypeDisplay.cs @@ -9,15 +9,15 @@ namespace Umbraco.Cms.Core.Models.ContentEditing { [DataMember(Name = "editor")] [ReadOnly(true)] - public string Editor { get; set; } + public string? Editor { get; set; } [DataMember(Name = "view")] [ReadOnly(true)] - public string View { get; set; } + public string? View { get; set; } [DataMember(Name = "config")] [ReadOnly(true)] - public IDictionary Config { get; set; } + public IDictionary? Config { get; set; } /// /// Gets a value indicating whether this property should be locked when editing. @@ -42,7 +42,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// [DataMember(Name = "contentTypeName")] [ReadOnly(true)] - public string ContentTypeName { get; set; } + public string? ContentTypeName { get; set; } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/PropertyTypeValidation.cs b/src/Umbraco.Core/Models/ContentEditing/PropertyTypeValidation.cs index 17c71eb479..7c35fd156a 100644 --- a/src/Umbraco.Core/Models/ContentEditing/PropertyTypeValidation.cs +++ b/src/Umbraco.Core/Models/ContentEditing/PropertyTypeValidation.cs @@ -9,15 +9,15 @@ namespace Umbraco.Cms.Core.Models.ContentEditing public class PropertyTypeValidation { [DataMember(Name = "mandatory")] - public bool Mandatory { get; set; } + public bool? Mandatory { get; set; } [DataMember(Name = "mandatoryMessage")] - public string MandatoryMessage { get; set; } + public string? MandatoryMessage { get; set; } [DataMember(Name = "pattern")] - public string Pattern { get; set; } + public string? Pattern { get; set; } [DataMember(Name = "patternMessage")] - public string PatternMessage { get; set; } + public string? PatternMessage { get; set; } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/RelationDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/RelationDisplay.cs index 61b9b3f39b..0decb18414 100644 --- a/src/Umbraco.Core/Models/ContentEditing/RelationDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/RelationDisplay.cs @@ -19,7 +19,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// [DataMember(Name = "parentName")] [ReadOnly(true)] - public string ParentName { get; set; } + public string? ParentName { get; set; } /// /// Gets or sets the Child Id of the Relation (Destination). @@ -33,7 +33,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// [DataMember(Name = "childName")] [ReadOnly(true)] - public string ChildName { get; set; } + public string? ChildName { get; set; } /// /// Gets or sets the date when the Relation was created. @@ -47,6 +47,6 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// [DataMember(Name = "comment")] [ReadOnly(true)] - public string Comment { get; set; } + public string? Comment { get; set; } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/RelationTypeDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/RelationTypeDisplay.cs index 27f0f525df..0c649c092f 100644 --- a/src/Umbraco.Core/Models/ContentEditing/RelationTypeDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/RelationTypeDisplay.cs @@ -34,7 +34,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// [DataMember(Name = "parentObjectTypeName")] [ReadOnly(true)] - public string ParentObjectTypeName { get; set; } + public string? ParentObjectTypeName { get; set; } /// /// Gets or sets the Child's object type id @@ -48,7 +48,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// [DataMember(Name = "childObjectTypeName")] [ReadOnly(true)] - public string ChildObjectTypeName { get; set; } + public string? ChildObjectTypeName { get; set; } /// /// This is used to add custom localized messages/strings to the response for the app to use for localized UI purposes. diff --git a/src/Umbraco.Core/Models/ContentEditing/SimpleNotificationModel.cs b/src/Umbraco.Core/Models/ContentEditing/SimpleNotificationModel.cs index 1c01a3153c..e6db2b933a 100644 --- a/src/Umbraco.Core/Models/ContentEditing/SimpleNotificationModel.cs +++ b/src/Umbraco.Core/Models/ContentEditing/SimpleNotificationModel.cs @@ -26,6 +26,6 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// A default message /// [DataMember(Name = "message")] - public string Message { get; set; } + public string? Message { get; set; } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/Tab.cs b/src/Umbraco.Core/Models/ContentEditing/Tab.cs index eda5abb2c3..4bcd824670 100644 --- a/src/Umbraco.Core/Models/ContentEditing/Tab.cs +++ b/src/Umbraco.Core/Models/ContentEditing/Tab.cs @@ -17,16 +17,16 @@ namespace Umbraco.Cms.Core.Models.ContentEditing public Guid Key { get; set; } [DataMember(Name = "type")] - public string Type { get; set; } + public string? Type { get; set; } [DataMember(Name = "active")] public bool IsActive { get; set; } [DataMember(Name = "label")] - public string Label { get; set; } + public string? Label { get; set; } [DataMember(Name = "alias")] - public string Alias { get; set; } + public string? Alias { get; set; } /// /// The expanded state of the tab @@ -35,6 +35,6 @@ namespace Umbraco.Cms.Core.Models.ContentEditing public bool Expanded { get; set; } = true; [DataMember(Name = "properties")] - public IEnumerable Properties { get; set; } + public IEnumerable? Properties { get; set; } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/TabbedContentItem.cs b/src/Umbraco.Core/Models/ContentEditing/TabbedContentItem.cs index 2695d01c7a..afc64e7faf 100644 --- a/src/Umbraco.Core/Models/ContentEditing/TabbedContentItem.cs +++ b/src/Umbraco.Core/Models/ContentEditing/TabbedContentItem.cs @@ -28,7 +28,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing [IgnoreDataMember] public override IEnumerable Properties { - get => Tabs.SelectMany(x => x.Properties); + get => Tabs.Where(x => x.Properties is not null).SelectMany(x => x.Properties!); set => throw new NotImplementedException(); } } diff --git a/src/Umbraco.Core/Models/ContentEditing/TemplateDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/TemplateDisplay.cs index e73f36c189..fd67d55936 100644 --- a/src/Umbraco.Core/Models/ContentEditing/TemplateDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/TemplateDisplay.cs @@ -14,26 +14,26 @@ namespace Umbraco.Cms.Core.Models.ContentEditing [Required] [DataMember(Name = "name")] - public string Name { get; set; } + public string? Name { get; set; } [Required] [DataMember(Name = "alias")] - public string Alias { get; set; } + public string Alias { get; set; } = string.Empty; [DataMember(Name = "key")] public Guid Key { get; set; } [DataMember(Name = "content")] - public string Content { get; set; } + public string? Content { get; set; } [DataMember(Name = "path")] - public string Path { get; set; } + public string? Path { get; set; } [DataMember(Name = "virtualPath")] - public string VirtualPath { get; set; } + public string? VirtualPath { get; set; } [DataMember(Name = "masterTemplateAlias")] - public string MasterTemplateAlias { get; set; } + public string? MasterTemplateAlias { get; set; } [DataMember(Name = "isMasterTemplate")] public bool IsMasterTemplate { get; set; } @@ -42,6 +42,6 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// This is used to add custom localized messages/strings to the response for the app to use for localized UI purposes. /// [DataMember(Name = "notifications")] - public List Notifications { get; private set; } + public List? Notifications { get; private set; } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/UserBasic.cs b/src/Umbraco.Core/Models/ContentEditing/UserBasic.cs index e67d3bae6e..b2dc4ceb4a 100644 --- a/src/Umbraco.Core/Models/ContentEditing/UserBasic.cs +++ b/src/Umbraco.Core/Models/ContentEditing/UserBasic.cs @@ -20,13 +20,13 @@ namespace Umbraco.Cms.Core.Models.ContentEditing } [DataMember(Name = "username")] - public string Username { get; set; } + public string? Username { get; set; } /// /// The MD5 lowercase hash of the email which can be used by gravatar /// [DataMember(Name = "emailHash")] - public string EmailHash { get; set; } + public string? EmailHash { get; set; } [DataMember(Name = "lastLoginDate")] public DateTime? LastLoginDate { get; set; } @@ -35,16 +35,16 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// Returns a list of different size avatars /// [DataMember(Name = "avatars")] - public string[] Avatars { get; set; } + public string[]? Avatars { get; set; } [DataMember(Name = "userState")] public UserState UserState { get; set; } [DataMember(Name = "culture", IsRequired = true)] - public string Culture { get; set; } + public string? Culture { get; set; } [DataMember(Name = "email", IsRequired = true)] - public string Email { get; set; } + public string? Email { get; set; } /// /// The list of group aliases assigned to the user diff --git a/src/Umbraco.Core/Models/ContentEditing/UserDetail.cs b/src/Umbraco.Core/Models/ContentEditing/UserDetail.cs index c655ba1875..01c2bcb70c 100644 --- a/src/Umbraco.Core/Models/ContentEditing/UserDetail.cs +++ b/src/Umbraco.Core/Models/ContentEditing/UserDetail.cs @@ -13,21 +13,21 @@ namespace Umbraco.Cms.Core.Models.ContentEditing { [DataMember(Name = "email", IsRequired = true)] [Required] - public string Email { get; set; } + public string? Email { get; set; } [DataMember(Name = "locale", IsRequired = true)] [Required] - public string Culture { get; set; } + public string? Culture { get; set; } /// /// The MD5 lowercase hash of the email which can be used by gravatar /// [DataMember(Name = "emailHash")] - public string EmailHash { get; set; } + public string? EmailHash { get; set; } [ReadOnly(true)] [DataMember(Name = "userGroups")] - public string[] UserGroups { get; set; } + public string?[]? UserGroups { get; set; } /// /// Gets/sets the number of seconds for the user's auth ticket to expire @@ -39,24 +39,24 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// The user's calculated start nodes based on the start nodes they have assigned directly to them and via the groups they're assigned to /// [DataMember(Name = "startContentIds")] - public int[] StartContentIds { get; set; } + public int[]? StartContentIds { get; set; } /// /// The user's calculated start nodes based on the start nodes they have assigned directly to them and via the groups they're assigned to /// [DataMember(Name = "startMediaIds")] - public int[] StartMediaIds { get; set; } + public int[]? StartMediaIds { get; set; } /// /// Returns a list of different size avatars /// [DataMember(Name = "avatars")] - public string[] Avatars { get; set; } + public string[]? Avatars { get; set; } /// /// A list of sections the user is allowed to view. /// [DataMember(Name = "allowedSections")] - public IEnumerable AllowedSections { get; set; } + public IEnumerable? AllowedSections { get; set; } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/UserDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/UserDisplay.cs index f16ad854e6..9ae3d25cb0 100644 --- a/src/Umbraco.Core/Models/ContentEditing/UserDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/UserDisplay.cs @@ -42,21 +42,21 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// [DataMember(Name = "resetPasswordValue")] [ReadOnly(true)] - public string ResetPasswordValue { get; set; } + public string? ResetPasswordValue { get; set; } /// /// A readonly value showing the user's current calculated start content ids /// [DataMember(Name = "calculatedStartContentIds")] [ReadOnly(true)] - public IEnumerable CalculatedStartContentIds { get; set; } + public IEnumerable? CalculatedStartContentIds { get; set; } /// /// A readonly value showing the user's current calculated start media ids /// [DataMember(Name = "calculatedStartMediaIds")] [ReadOnly(true)] - public IEnumerable CalculatedStartMediaIds { get; set; } + public IEnumerable? CalculatedStartMediaIds { get; set; } [DataMember(Name = "failedPasswordAttempts")] [ReadOnly(true)] diff --git a/src/Umbraco.Core/Models/ContentEditing/UserGroupBasic.cs b/src/Umbraco.Core/Models/ContentEditing/UserGroupBasic.cs index e4c76b699e..ffcfde8368 100644 --- a/src/Umbraco.Core/Models/ContentEditing/UserGroupBasic.cs +++ b/src/Umbraco.Core/Models/ContentEditing/UserGroupBasic.cs @@ -23,10 +23,10 @@ namespace Umbraco.Cms.Core.Models.ContentEditing public IEnumerable
Sections { get; set; } [DataMember(Name = "contentStartNode")] - public EntityBasic ContentStartNode { get; set; } + public EntityBasic? ContentStartNode { get; set; } [DataMember(Name = "mediaStartNode")] - public EntityBasic MediaStartNode { get; set; } + public EntityBasic? MediaStartNode { get; set; } /// /// The number of users assigned to this group diff --git a/src/Umbraco.Core/Models/ContentEditing/UserGroupDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/UserGroupDisplay.cs index 2e570df9dd..697a0a2100 100644 --- a/src/Umbraco.Core/Models/ContentEditing/UserGroupDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/UserGroupDisplay.cs @@ -20,7 +20,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// The default permissions for the user group organized by permission group name /// [DataMember(Name = "defaultPermissions")] - public IDictionary> DefaultPermissions { get; set; } + public IDictionary>? DefaultPermissions { get; set; } /// /// The assigned permissions for the user group organized by permission group name diff --git a/src/Umbraco.Core/Models/ContentEditing/UserGroupSave.cs b/src/Umbraco.Core/Models/ContentEditing/UserGroupSave.cs index 7d24378494..1bf7923817 100644 --- a/src/Umbraco.Core/Models/ContentEditing/UserGroupSave.cs +++ b/src/Umbraco.Core/Models/ContentEditing/UserGroupSave.cs @@ -22,13 +22,13 @@ namespace Umbraco.Cms.Core.Models.ContentEditing [DataMember(Name = "alias", IsRequired = true)] [Required] - public override string Alias { get; set; } + public override string Alias { get; set; } = string.Empty; [DataMember(Name = "sections")] - public IEnumerable Sections { get; set; } + public IEnumerable? Sections { get; set; } [DataMember(Name = "users")] - public IEnumerable Users { get; set; } + public IEnumerable? Users { get; set; } [DataMember(Name = "startContentId")] public int? StartContentId { get; set; } @@ -40,7 +40,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// The list of letters (permission codes) to assign as the default for the user group /// [DataMember(Name = "defaultPermissions")] - public IEnumerable DefaultPermissions { get; set; } + public IEnumerable? DefaultPermissions { get; set; } /// /// The assigned permissions for content @@ -49,27 +49,30 @@ namespace Umbraco.Cms.Core.Models.ContentEditing /// The key is the content id and the list is the list of letters (permission codes) to assign /// [DataMember(Name = "assignedPermissions")] - public IDictionary> AssignedPermissions { get; set; } + public IDictionary>? AssignedPermissions { get; set; } /// /// The real persisted user group /// [IgnoreDataMember] - public IUserGroup PersistedUserGroup { get; set; } + public IUserGroup? PersistedUserGroup { get; set; } public IEnumerable Validate(ValidationContext validationContext) { - if (DefaultPermissions.Any(x => x.IsNullOrWhiteSpace())) + if (DefaultPermissions?.Any(x => x.IsNullOrWhiteSpace()) ?? false) { yield return new ValidationResult("A permission value cannot be null or empty", new[] { "Permissions" }); } - foreach (var assignedPermission in AssignedPermissions) + if (AssignedPermissions is not null) { - foreach (var permission in assignedPermission.Value) + foreach (var assignedPermission in AssignedPermissions) { - if (permission.IsNullOrWhiteSpace()) - yield return new ValidationResult("A permission value cannot be null or empty", new[] { "AssignedPermissions" }); + foreach (var permission in assignedPermission.Value) + { + if (permission.IsNullOrWhiteSpace()) + yield return new ValidationResult("A permission value cannot be null or empty", new[] { "AssignedPermissions" }); + } } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/UserProfile.cs b/src/Umbraco.Core/Models/ContentEditing/UserProfile.cs index 314e0cfc09..9ade7735e7 100644 --- a/src/Umbraco.Core/Models/ContentEditing/UserProfile.cs +++ b/src/Umbraco.Core/Models/ContentEditing/UserProfile.cs @@ -16,12 +16,12 @@ namespace Umbraco.Cms.Core.Models.ContentEditing [DataMember(Name = "name", IsRequired = true)] [Required] - public string Name { get; set; } + public string? Name { get; set; } - int IComparable.CompareTo(object obj) + int IComparable.CompareTo(object? obj) { - return String.Compare(Name, ((UserProfile)obj).Name, StringComparison.Ordinal); + return String.Compare(Name, ((UserProfile?)obj)?.Name, StringComparison.Ordinal); } } } diff --git a/src/Umbraco.Core/Models/ContentRepositoryExtensions.cs b/src/Umbraco.Core/Models/ContentRepositoryExtensions.cs index ece903d8e6..8d816ab220 100644 --- a/src/Umbraco.Core/Models/ContentRepositoryExtensions.cs +++ b/src/Umbraco.Core/Models/ContentRepositoryExtensions.cs @@ -10,7 +10,7 @@ namespace Umbraco.Extensions /// public static class ContentRepositoryExtensions { - public static void SetCultureInfo(this IContentBase content, string culture, string name, DateTime date) + public static void SetCultureInfo(this IContentBase content, string culture, string? name, DateTime date) { if (name == null) throw new ArgumentNullException(nameof(name)); if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name)); @@ -18,17 +18,17 @@ namespace Umbraco.Extensions if (culture == null) throw new ArgumentNullException(nameof(culture)); if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(culture)); - content.CultureInfos.AddOrUpdate(culture, name, date); + content.CultureInfos?.AddOrUpdate(culture, name, date); } /// /// Updates a culture date, if the culture exists. /// - public static void TouchCulture(this IContentBase content, string culture) + public static void TouchCulture(this IContentBase content, string? culture) { if (culture.IsNullOrWhiteSpace()) return; - if (!content.CultureInfos.TryGetValue(culture, out var infos)) return; - content.CultureInfos.AddOrUpdate(culture, infos.Name, DateTime.Now); + if (!content.CultureInfos?.TryGetValue(culture!, out var infos) ?? true) return; + content.CultureInfos?.AddOrUpdate(culture!, infos.Name, DateTime.Now); } /// @@ -42,22 +42,26 @@ namespace Umbraco.Extensions /// public static void AdjustDates(this IContent content, DateTime date, bool publishing) { - foreach(var culture in content.EditedCultures.ToList()) + if (content.EditedCultures is not null) { - if (!content.CultureInfos.TryGetValue(culture, out ContentCultureInfos editedInfos)) + foreach(var culture in content.EditedCultures.ToList()) { - continue; - } + if (!content.CultureInfos?.TryGetValue(culture, out var editedInfos) ?? true) + { + continue; + } - // if it's not dirty, it means it hasn't changed so there's nothing to adjust - if (!editedInfos.IsDirty()) - { - continue; - } + // if it's not dirty, it means it hasn't changed so there's nothing to adjust + if (!editedInfos.IsDirty()) + { + continue; + } - content.CultureInfos.AddOrUpdate(culture, editedInfos.Name, date); + content.CultureInfos?.AddOrUpdate(culture, editedInfos?.Name, date); + } } + if (!publishing) { return; @@ -65,7 +69,7 @@ namespace Umbraco.Extensions foreach (var culture in content.PublishedCultures.ToList()) { - if (!content.PublishCultureInfos.TryGetValue(culture, out ContentCultureInfos publishInfos)) + if (!content.PublishCultureInfos?.TryGetValue(culture, out ContentCultureInfos publishInfos) ?? true) { continue; } @@ -78,7 +82,7 @@ namespace Umbraco.Extensions content.PublishCultureInfos.AddOrUpdate(culture, publishInfos.Name, date); - if (content.CultureInfos.TryGetValue(culture, out ContentCultureInfos infos)) + if (content.CultureInfos?.TryGetValue(culture, out ContentCultureInfos infos) ?? false) { SetCultureInfo(content, culture, infos.Name, date); } @@ -89,22 +93,22 @@ namespace Umbraco.Extensions /// Gets the cultures that have been flagged for unpublishing. /// /// Gets cultures for which content.UnpublishCulture() has been invoked. - public static IReadOnlyList GetCulturesUnpublishing(this IContent content) + public static IReadOnlyList? GetCulturesUnpublishing(this IContent content) { if (!content.Published || !content.ContentType.VariesByCulture() || !content.IsPropertyDirty("PublishCultureInfos")) return Array.Empty(); - var culturesUnpublishing = content.CultureInfos.Values + var culturesUnpublishing = content.CultureInfos?.Values .Where(x => content.IsPropertyDirty(ContentBase.ChangeTrackingPrefix.UnpublishedCulture + x.Culture)) .Select(x => x.Culture); - return culturesUnpublishing.ToList(); + return culturesUnpublishing?.ToList(); } /// /// Copies values from another document. /// - public static void CopyFrom(this IContent content, IContent other, string culture = "*") + public static void CopyFrom(this IContent content, IContent other, string? culture = "*") { if (other.ContentTypeId != content.ContentTypeId) throw new InvalidOperationException("Cannot copy values from a different content type."); @@ -161,7 +165,7 @@ namespace Umbraco.Extensions if (culture == "*") { - content.CultureInfos.Clear(); + content.CultureInfos?.Clear(); content.CultureInfos = null; } @@ -169,14 +173,17 @@ namespace Umbraco.Extensions content.Name = other.Name; // ReSharper disable once UseDeconstruction - foreach (var cultureInfo in other.CultureInfos) + if (other.CultureInfos is not null) { - if (culture == "*" || culture == cultureInfo.Culture) - content.SetCultureName(cultureInfo.Name, cultureInfo.Culture); + foreach (var cultureInfo in other.CultureInfos) + { + if (culture == "*" || culture == cultureInfo.Culture) + content.SetCultureName(cultureInfo.Name, cultureInfo.Culture); + } } } - public static void SetPublishInfo(this IContent content, string culture, string name, DateTime date) + public static void SetPublishInfo(this IContent content, string? culture, string name, DateTime date) { if (name == null) throw new ArgumentNullException(nameof(name)); if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name)); @@ -184,7 +191,7 @@ namespace Umbraco.Extensions if (culture == null) throw new ArgumentNullException(nameof(culture)); if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(culture)); - content.PublishCultureInfos.AddOrUpdate(culture, name, date); + content.PublishCultureInfos?.AddOrUpdate(culture, name, date); } // sets the edited cultures on the content @@ -265,9 +272,9 @@ namespace Umbraco.Extensions /// /// /// - public static bool UnpublishCulture(this IContent content, string culture = "*") + public static bool UnpublishCulture(this IContent content, string? culture = "*") { - culture = culture.NullOrWhiteSpaceAsNull(); + culture = culture?.NullOrWhiteSpaceAsNull(); // the variation should be supported by the content type properties if (!content.ContentType.SupportsPropertyVariation(culture, "*", true)) @@ -309,18 +316,18 @@ namespace Umbraco.Extensions /// /// /// - public static bool ClearPublishInfo(this IContent content, string culture) + public static bool ClearPublishInfo(this IContent content, string? culture) { if (culture == null) throw new ArgumentNullException(nameof(culture)); if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(culture)); - var removed = content.PublishCultureInfos.Remove(culture); - if (removed) + var removed = content.PublishCultureInfos?.Remove(culture); + if (removed ?? false) { // set the culture to be dirty - it's been modified content.TouchCulture(culture); } - return removed; + return removed ?? false; } } } diff --git a/src/Umbraco.Core/Models/ContentSchedule.cs b/src/Umbraco.Core/Models/ContentSchedule.cs index ce4686a7b1..77526f254a 100644 --- a/src/Umbraco.Core/Models/ContentSchedule.cs +++ b/src/Umbraco.Core/Models/ContentSchedule.cs @@ -60,7 +60,7 @@ namespace Umbraco.Cms.Core.Models [DataMember] public ContentScheduleAction Action { get; } - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is ContentSchedule other && Equals(other); public bool Equals(ContentSchedule other) diff --git a/src/Umbraco.Core/Models/ContentScheduleCollection.cs b/src/Umbraco.Core/Models/ContentScheduleCollection.cs index f8f6c323f7..a2691a4c8e 100644 --- a/src/Umbraco.Core/Models/ContentScheduleCollection.cs +++ b/src/Umbraco.Core/Models/ContentScheduleCollection.cs @@ -12,7 +12,7 @@ namespace Umbraco.Cms.Core.Models private readonly Dictionary> _schedule = new Dictionary>(StringComparer.InvariantCultureIgnoreCase); - public event NotifyCollectionChangedEventHandler CollectionChanged; + public event NotifyCollectionChangedEventHandler? CollectionChanged; /// /// Clears all event handlers @@ -202,10 +202,10 @@ namespace Umbraco.Cms.Core.Models return clone; } - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is ContentScheduleCollection other && Equals(other); - public bool Equals(ContentScheduleCollection other) + public bool Equals(ContentScheduleCollection? other) { if (other == null) return false; diff --git a/src/Umbraco.Core/Models/ContentType.cs b/src/Umbraco.Core/Models/ContentType.cs index 6ff94f57f3..07cc46c79b 100644 --- a/src/Umbraco.Core/Models/ContentType.cs +++ b/src/Umbraco.Core/Models/ContentType.cs @@ -22,7 +22,7 @@ namespace Umbraco.Cms.Core.Models (templates, enumerable) => templates.UnsortedSequenceEqual(enumerable), templates => templates.GetHashCode()); - private IEnumerable _allowedTemplates; + private IEnumerable? _allowedTemplates; private int _defaultTemplate; @@ -64,8 +64,8 @@ namespace Umbraco.Cms.Core.Models /// we should not store direct entity /// [IgnoreDataMember] - public ITemplate DefaultTemplate => - AllowedTemplates.FirstOrDefault(x => x != null && x.Id == DefaultTemplateId); + public ITemplate? DefaultTemplate => + AllowedTemplates?.FirstOrDefault(x => x != null && x.Id == DefaultTemplateId); [DataMember] @@ -82,21 +82,21 @@ namespace Umbraco.Cms.Core.Models /// we should not store direct entity ///
[DataMember] - public IEnumerable AllowedTemplates + public IEnumerable? AllowedTemplates { get => _allowedTemplates; set { SetPropertyValueAndDetectChanges(value, ref _allowedTemplates, nameof(AllowedTemplates), TemplateComparer); - if (_allowedTemplates.Any(x => x.Id == _defaultTemplate) == false) + if (_allowedTemplates?.Any(x => x.Id == _defaultTemplate) == false) { DefaultTemplateId = 0; } } } - public HistoryCleanup HistoryCleanup { get; set; } + public HistoryCleanup? HistoryCleanup { get; set; } /// /// Determines if AllowedTemplates contains templateId @@ -122,7 +122,7 @@ namespace Umbraco.Cms.Core.Models /// Sets the default template for the ContentType /// /// Default - public void SetDefaultTemplate(ITemplate template) + public void SetDefaultTemplate(ITemplate? template) { if (template == null) { @@ -131,10 +131,10 @@ namespace Umbraco.Cms.Core.Models } DefaultTemplateId = template.Id; - if (_allowedTemplates.Any(x => x != null && x.Id == template.Id) == false) + if (_allowedTemplates?.Any(x => x != null && x.Id == template.Id) == false) { - var templates = AllowedTemplates.ToList(); - templates.Add(template); + var templates = AllowedTemplates?.ToList(); + templates?.Add(template); AllowedTemplates = templates; } } @@ -151,9 +151,9 @@ namespace Umbraco.Cms.Core.Models DefaultTemplateId = default; } - var templates = AllowedTemplates.ToList(); - ITemplate remove = templates.FirstOrDefault(x => x.Id == template.Id); - var result = templates.Remove(remove); + var templates = AllowedTemplates?.ToList(); + ITemplate? remove = templates?.FirstOrDefault(x => x.Id == template.Id); + var result = remove is not null && templates is not null && templates.Remove(remove); AllowedTemplates = templates; return result; diff --git a/src/Umbraco.Core/Models/ContentTypeBase.cs b/src/Umbraco.Core/Models/ContentTypeBase.cs index afc291c09d..d0d072df6a 100644 --- a/src/Umbraco.Core/Models/ContentTypeBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeBase.cs @@ -21,20 +21,21 @@ namespace Umbraco.Cms.Core.Models private readonly IShortStringHelper _shortStringHelper; private string _alias; - private string _description; - private string _icon = "icon-folder"; - private string _thumbnail = "folder.png"; + private string? _description; + private string? _icon = "icon-folder"; + private string? _thumbnail = "folder.png"; private bool _allowedAsRoot; // note: only one that's not 'pure element type' private bool _isContainer; private bool _isElement; private PropertyGroupCollection _propertyGroups; private PropertyTypeCollection _noGroupPropertyTypes; - private IEnumerable _allowedContentTypes; + private IEnumerable? _allowedContentTypes; private bool _hasPropertyTypeBeenRemoved; private ContentVariation _variations; protected ContentTypeBase(IShortStringHelper shortStringHelper, int parentId) { + _alias = string.Empty; _shortStringHelper = shortStringHelper; if (parentId == 0) throw new ArgumentOutOfRangeException(nameof(parentId)); ParentId = parentId; @@ -51,7 +52,7 @@ namespace Umbraco.Cms.Core.Models } protected ContentTypeBase(IShortStringHelper shortStringHelper, IContentTypeBase parent) - : this(shortStringHelper, parent, null) + : this(shortStringHelper, parent, string.Empty) { } protected ContentTypeBase(IShortStringHelper shortStringHelper, IContentTypeBase parent, string alias) @@ -93,12 +94,12 @@ namespace Umbraco.Cms.Core.Models (sorts, enumerable) => sorts.UnsortedSequenceEqual(enumerable), sorts => sorts.GetHashCode()); - protected void PropertyGroupsChanged(object sender, NotifyCollectionChangedEventArgs e) + protected void PropertyGroupsChanged(object? sender, NotifyCollectionChangedEventArgs e) { OnPropertyChanged(nameof(PropertyGroups)); } - protected void PropertyTypesChanged(object sender, NotifyCollectionChangedEventArgs e) + protected void PropertyTypesChanged(object? sender, NotifyCollectionChangedEventArgs e) { //enable this to detect duplicate property aliases. We do want this, however making this change in a //patch release might be a little dangerous @@ -127,7 +128,7 @@ namespace Umbraco.Cms.Core.Models get => _alias; set => SetPropertyValueAndDetectChanges( value.ToCleanString(_shortStringHelper, CleanStringType.Alias | CleanStringType.UmbracoCase), - ref _alias, + ref _alias!, nameof(Alias)); } @@ -135,7 +136,7 @@ namespace Umbraco.Cms.Core.Models /// Description for the ContentType ///
[DataMember] - public string Description + public string? Description { get => _description; set => SetPropertyValueAndDetectChanges(value, ref _description, nameof(Description)); @@ -145,7 +146,7 @@ namespace Umbraco.Cms.Core.Models /// Name of the icon (sprite class) used to identify the ContentType ///
[DataMember] - public string Icon + public string? Icon { get => _icon; set => SetPropertyValueAndDetectChanges(value, ref _icon, nameof(Icon)); @@ -155,7 +156,7 @@ namespace Umbraco.Cms.Core.Models /// Name of the thumbnail used to identify the ContentType /// [DataMember] - public string Thumbnail + public string? Thumbnail { get => _thumbnail; set => SetPropertyValueAndDetectChanges(value, ref _thumbnail, nameof(Thumbnail)); @@ -196,7 +197,7 @@ namespace Umbraco.Cms.Core.Models /// Gets or sets a list of integer Ids for allowed ContentTypes /// [DataMember] - public IEnumerable AllowedContentTypes + public IEnumerable? AllowedContentTypes { get => _allowedContentTypes; set => SetPropertyValueAndDetectChanges(value, ref _allowedContentTypes, nameof(AllowedContentTypes), @@ -306,7 +307,7 @@ namespace Umbraco.Cms.Core.Models public abstract bool AddPropertyGroup(string alias, string name); /// - public abstract bool AddPropertyType(IPropertyType propertyType, string propertyGroupAlias, string propertyGroupName = null); + public abstract bool AddPropertyType(IPropertyType propertyType, string propertyGroupAlias, string? propertyGroupName = null); /// /// Adds a PropertyType, which does not belong to a PropertyGroup. @@ -339,7 +340,7 @@ namespace Umbraco.Cms.Core.Models if (propertyType == null) return false; // get new group, if required, and ensure it exists - PropertyGroup newPropertyGroup = null; + PropertyGroup? newPropertyGroup = null; if (propertyGroupAlias != null) { var index = PropertyGroups.IndexOfKey(propertyGroupAlias); @@ -347,7 +348,7 @@ namespace Umbraco.Cms.Core.Models newPropertyGroup = PropertyGroups[index]; } - + // get old group var oldPropertyGroup = PropertyGroups.FirstOrDefault(x => x.PropertyTypes.Any(y => y.Alias == propertyTypeAlias)); diff --git a/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs b/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs index 596dbe7a63..531a04181c 100644 --- a/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs @@ -22,7 +22,7 @@ namespace Umbraco.Cms.Core.Models { } protected ContentTypeCompositionBase(IShortStringHelper shortStringHelper,IContentTypeComposition parent) - : this(shortStringHelper, parent, null) + : this(shortStringHelper, parent, string.Empty) { } protected ContentTypeCompositionBase(IShortStringHelper shortStringHelper, IContentTypeComposition parent, string alias) @@ -207,7 +207,7 @@ namespace Umbraco.Cms.Core.Models /// public override bool AddPropertyGroup(string alias, string name) => AddAndReturnPropertyGroup(alias, name) != null; - private PropertyGroup AddAndReturnPropertyGroup(string alias, string name) + private PropertyGroup? AddAndReturnPropertyGroup(string alias, string name) { // Ensure we don't have it already if (PropertyGroups.Contains(alias)) @@ -244,14 +244,14 @@ namespace Umbraco.Cms.Core.Models } /// - public override bool AddPropertyType(IPropertyType propertyType, string propertyGroupAlias, string propertyGroupName = null) + public override bool AddPropertyType(IPropertyType propertyType, string propertyGroupAlias, string? propertyGroupName = null) { // ensure no duplicate alias - over all composition properties if (PropertyTypeExists(propertyType.Alias)) return false; // get and ensure a group local to this content type - PropertyGroup group; + PropertyGroup? group; var index = PropertyGroups.IndexOfKey(propertyGroupAlias); if (index != -1) { @@ -261,7 +261,9 @@ namespace Umbraco.Cms.Core.Models { group = AddAndReturnPropertyGroup(propertyGroupAlias, propertyGroupName); if (group == null) + { return false; + } } else { diff --git a/src/Umbraco.Core/Models/ContentTypeSort.cs b/src/Umbraco.Core/Models/ContentTypeSort.cs index fb595ef43f..925164b17c 100644 --- a/src/Umbraco.Core/Models/ContentTypeSort.cs +++ b/src/Umbraco.Core/Models/ContentTypeSort.cs @@ -16,7 +16,7 @@ namespace Umbraco.Cms.Core.Models /// public ContentTypeSort(int id, int sortOrder) { - Id = new Lazy(() => id); + Id = new Lazy(() => default); SortOrder = sortOrder; } @@ -30,7 +30,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets or sets the Id of the ContentType /// - public Lazy Id { get; set; } + public Lazy Id { get; set; } = new Lazy(() => 0); /// /// Gets or sets the Sort Order of the ContentType @@ -40,7 +40,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets or sets the Alias of the ContentType /// - public string Alias { get; set; } + public string Alias { get; set; } = string.Empty; public object DeepClone() @@ -56,7 +56,7 @@ namespace Umbraco.Cms.Core.Models return Id.Value.Equals(other.Id.Value) && string.Equals(Alias, other.Alias); } - 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/Models/ContentVersionMeta.cs b/src/Umbraco.Core/Models/ContentVersionMeta.cs index d2e53e0985..dbcd8540a0 100644 --- a/src/Umbraco.Core/Models/ContentVersionMeta.cs +++ b/src/Umbraco.Core/Models/ContentVersionMeta.cs @@ -13,7 +13,7 @@ namespace Umbraco.Cms.Core.Models public bool CurrentPublishedVersion { get; } public bool CurrentDraftVersion { get; } public bool PreventCleanup { get; } - public string Username { get; } + public string? Username { get; } public ContentVersionMeta() { } diff --git a/src/Umbraco.Core/Models/CultureImpact.cs b/src/Umbraco.Core/Models/CultureImpact.cs index 1f8e938c63..8c6be0f7ae 100644 --- a/src/Umbraco.Core/Models/CultureImpact.cs +++ b/src/Umbraco.Core/Models/CultureImpact.cs @@ -21,7 +21,7 @@ namespace Umbraco.Cms.Core.Models /// /// /// - public static string GetCultureForInvariantErrors(IContent content, string[] savingCultures, string defaultCulture) + public static string? GetCultureForInvariantErrors(IContent content, string[] savingCultures, string defaultCulture) { if (content == null) throw new ArgumentNullException(nameof(content)); if (savingCultures == null) throw new ArgumentNullException(nameof(savingCultures)); @@ -42,7 +42,7 @@ namespace Umbraco.Cms.Core.Models /// /// The culture code. /// A value indicating whether the culture is the default culture. - private CultureImpact(string culture, bool isDefault = false) + private CultureImpact(string? culture, bool isDefault = false) { if (culture != null && culture.IsNullOrWhiteSpace()) throw new ArgumentException("Culture \"\" is not valid here."); @@ -92,7 +92,7 @@ namespace Umbraco.Cms.Core.Models /// /// Validates that the culture is compatible with the variation. /// - public static CultureImpact Create(string culture, bool isDefault, IContent content) + public static CultureImpact? Create(string culture, bool isDefault, IContent content) { // throws if not successful TryCreate(culture, isDefault, content.ContentType.Variations, true, out var impact); @@ -112,7 +112,7 @@ namespace Umbraco.Cms.Core.Models /// /// Validates that the culture is compatible with the variation. /// - internal static bool TryCreate(string culture, bool isDefault, ContentVariation variation, bool throwOnFail, out CultureImpact impact) + internal static bool TryCreate(string culture, bool isDefault, ContentVariation variation, bool throwOnFail, out CultureImpact? impact) { impact = null; @@ -182,7 +182,7 @@ namespace Umbraco.Cms.Core.Models /// /// Can be null (invariant) or * (all cultures) or a specific culture code. /// - public string Culture { get; } + public string? Culture { get; } /// /// Gets a value indicating whether this impact impacts all cultures, including, diff --git a/src/Umbraco.Core/Models/DataType.cs b/src/Umbraco.Core/Models/DataType.cs index b60c3b85fb..8678f4947b 100644 --- a/src/Umbraco.Core/Models/DataType.cs +++ b/src/Umbraco.Core/Models/DataType.cs @@ -17,9 +17,9 @@ namespace Umbraco.Cms.Core.Models private IDataEditor _editor; private ValueStorageType _databaseType; private readonly IConfigurationEditorJsonSerializer _serializer; - private object _configuration; + private object? _configuration; private bool _hasConfiguration; - private string _configurationJson; + private string? _configurationJson; /// /// Initializes a new instance of the class. @@ -77,7 +77,7 @@ namespace Umbraco.Cms.Core.Models /// [DataMember] - public object Configuration + public object? Configuration { get { @@ -162,7 +162,7 @@ namespace Umbraco.Cms.Core.Models /// This method is meant to be used when creating published datatypes, exclusively. /// Think before using! /// - internal Lazy GetLazyConfiguration() + internal Lazy GetLazyConfiguration() { // note: in both cases, make sure we capture what we need - we don't want // to capture a reference to this full, potentially heavy, DataType instance. @@ -171,14 +171,14 @@ namespace Umbraco.Cms.Core.Models { // if configuration has already been de-serialized, return var capturedConfiguration = _configuration; - return new Lazy(() => capturedConfiguration); + return new Lazy(() => capturedConfiguration); } else { // else, create a Lazy de-serializer var capturedConfiguration = _configurationJson; var capturedEditor = _editor; - return new Lazy(() => + return new Lazy(() => { try { diff --git a/src/Umbraco.Core/Models/DataTypeExtensions.cs b/src/Umbraco.Core/Models/DataTypeExtensions.cs index 4601330cac..10419dca88 100644 --- a/src/Umbraco.Core/Models/DataTypeExtensions.cs +++ b/src/Umbraco.Core/Models/DataTypeExtensions.cs @@ -16,7 +16,7 @@ namespace Umbraco.Extensions /// The expected type of the configuration object. /// This datatype. /// When the datatype configuration is not of the expected type. - public static T ConfigurationAs(this IDataType dataType) + public static T? ConfigurationAs(this IDataType dataType) where T : class { if (dataType == null) diff --git a/src/Umbraco.Core/Models/DeepCloneHelper.cs b/src/Umbraco.Core/Models/DeepCloneHelper.cs index ab8f323e7d..4dc293641c 100644 --- a/src/Umbraco.Core/Models/DeepCloneHelper.cs +++ b/src/Umbraco.Core/Models/DeepCloneHelper.cs @@ -23,7 +23,7 @@ namespace Umbraco.Cms.Core.Models public PropertyInfo PropertyInfo { get; private set; } public bool IsDeepCloneable { get; set; } - public Type GenericListType { get; set; } + public Type? GenericListType { get; set; } public bool IsList { get { return GenericListType != null; } @@ -122,7 +122,7 @@ namespace Umbraco.Cms.Core.Models return new ClonePropertyInfo(propertyInfo); }) .Where(x => x.HasValue) - .Select(x => x.Value) + .Select(x => x!.Value) .ToArray()); foreach (var clonePropertyInfo in refProperties) @@ -130,7 +130,7 @@ namespace Umbraco.Cms.Core.Models if (clonePropertyInfo.IsDeepCloneable) { //this ref property is also deep cloneable so clone it - var result = (IDeepCloneable)clonePropertyInfo.PropertyInfo.GetValue(input, null); + var result = (IDeepCloneable?)clonePropertyInfo.PropertyInfo.GetValue(input, null); if (result != null) { @@ -140,10 +140,10 @@ namespace Umbraco.Cms.Core.Models } else if (clonePropertyInfo.IsList) { - var enumerable = (IEnumerable)clonePropertyInfo.PropertyInfo.GetValue(input, null); + var enumerable = (IEnumerable?)clonePropertyInfo.PropertyInfo.GetValue(input, null); if (enumerable == null) continue; - var newList = (IList)Activator.CreateInstance(clonePropertyInfo.GenericListType); + var newList = clonePropertyInfo.GenericListType is not null ? (IList?)Activator.CreateInstance(clonePropertyInfo.GenericListType) : null; var isUsableType = true; @@ -154,12 +154,12 @@ namespace Umbraco.Cms.Core.Models var dc = o as IDeepCloneable; if (dc != null) { - newList.Add(dc.DeepClone()); + newList?.Add(dc.DeepClone()); } else if (o is string || o.GetType().IsValueType) { //check if the item is a value type or a string, then we can just use it - newList.Add(o); + newList?.Add(o); } else { @@ -179,11 +179,15 @@ namespace Umbraco.Cms.Core.Models if (clonePropertyInfo.PropertyInfo.PropertyType.IsArray) { //need to convert to array - var arr = (object[])Activator.CreateInstance(clonePropertyInfo.PropertyInfo.PropertyType, newList.Count); - for (int i = 0; i < newList.Count; i++) + var arr = (object?[]?)Activator.CreateInstance(clonePropertyInfo.PropertyInfo.PropertyType, newList?.Count ?? 0); + for (int i = 0; i < newList?.Count; i++) { - arr[i] = newList[i]; + if (arr != null) + { + arr[i] = newList[i]; + } } + //set the cloned collection clonePropertyInfo.PropertyInfo.SetValue(output, arr, null); } diff --git a/src/Umbraco.Core/Models/DictionaryItem.cs b/src/Umbraco.Core/Models/DictionaryItem.cs index 2bd4d3db6f..759d5b5680 100644 --- a/src/Umbraco.Core/Models/DictionaryItem.cs +++ b/src/Umbraco.Core/Models/DictionaryItem.cs @@ -14,10 +14,10 @@ namespace Umbraco.Cms.Core.Models [DataContract(IsReference = true)] public class DictionaryItem : EntityBase, IDictionaryItem { - public Func GetLanguage { get; set; } + public Func? GetLanguage { get; set; } private Guid? _parentId; private string _itemKey; - private IEnumerable _translations; + private IEnumerable? _translations; public DictionaryItem(string itemKey) : this(null, itemKey) @@ -53,21 +53,21 @@ namespace Umbraco.Cms.Core.Models public string ItemKey { get { return _itemKey; } - set { SetPropertyValueAndDetectChanges(value, ref _itemKey, nameof(ItemKey)); } + set { SetPropertyValueAndDetectChanges(value, ref _itemKey!, nameof(ItemKey)); } } /// /// Gets or sets a list of translations for the Dictionary Item /// [DataMember] - public IEnumerable Translations + public IEnumerable? Translations { get { return _translations; } set { - var asArray = value.ToArray(); + var asArray = value?.ToArray(); //ensure the language callback is set on each translation - if (GetLanguage != null) + if (GetLanguage != null && asArray is not null) { foreach (var translation in asArray.OfType()) { diff --git a/src/Umbraco.Core/Models/DictionaryItemExtensions.cs b/src/Umbraco.Core/Models/DictionaryItemExtensions.cs index ba0a655c75..137680aa27 100644 --- a/src/Umbraco.Core/Models/DictionaryItemExtensions.cs +++ b/src/Umbraco.Core/Models/DictionaryItemExtensions.cs @@ -11,9 +11,9 @@ namespace Umbraco.Extensions /// /// /// - public static string GetTranslatedValue(this IDictionaryItem d, int languageId) + public static string? GetTranslatedValue(this IDictionaryItem d, int languageId) { - var trans = d.Translations.FirstOrDefault(x => x.LanguageId == languageId); + var trans = d.Translations?.FirstOrDefault(x => x.LanguageId == languageId); return trans == null ? string.Empty : trans.Value; } @@ -22,9 +22,9 @@ namespace Umbraco.Extensions /// /// /// - public static string GetDefaultValue(this IDictionaryItem d) + public static string? GetDefaultValue(this IDictionaryItem d) { - var defaultTranslation = d.Translations.FirstOrDefault(x => x.Language.Id == 1); + var defaultTranslation = d.Translations?.FirstOrDefault(x => x.Language?.Id == 1); return defaultTranslation == null ? string.Empty : defaultTranslation.Value; } } diff --git a/src/Umbraco.Core/Models/DictionaryTranslation.cs b/src/Umbraco.Core/Models/DictionaryTranslation.cs index 22833882f7..37350ef035 100644 --- a/src/Umbraco.Core/Models/DictionaryTranslation.cs +++ b/src/Umbraco.Core/Models/DictionaryTranslation.cs @@ -11,10 +11,10 @@ namespace Umbraco.Cms.Core.Models [DataContract(IsReference = true)] public class DictionaryTranslation : EntityBase, IDictionaryTranslation { - public Func GetLanguage { get; set; } + public Func? GetLanguage { get; set; } - private ILanguage _language; - private string _value; + private ILanguage? _language; + private string? _value; //note: this will be memberwise cloned private int _languageId; @@ -60,7 +60,7 @@ namespace Umbraco.Cms.Core.Models /// [DataMember] [DoNotClone] - public ILanguage Language + public ILanguage? Language { get { @@ -88,7 +88,7 @@ namespace Umbraco.Cms.Core.Models /// Gets or sets the translated text /// [DataMember] - public string Value + public string? Value { get { return _value; } set { SetPropertyValueAndDetectChanges(value, ref _value, nameof(Value)); } diff --git a/src/Umbraco.Core/Models/Editors/ContentPropertyData.cs b/src/Umbraco.Core/Models/Editors/ContentPropertyData.cs index 548691ab50..2b3e38ad13 100644 --- a/src/Umbraco.Core/Models/Editors/ContentPropertyData.cs +++ b/src/Umbraco.Core/Models/Editors/ContentPropertyData.cs @@ -40,6 +40,6 @@ namespace Umbraco.Cms.Core.Models.Editors /// /// Gets or sets the uploaded files. /// - public ContentPropertyFile[] Files { get; set; } + public ContentPropertyFile[]? Files { get; set; } } } diff --git a/src/Umbraco.Core/Models/Editors/UmbracoEntityReference.cs b/src/Umbraco.Core/Models/Editors/UmbracoEntityReference.cs index acd56f5642..4efc5017e1 100644 --- a/src/Umbraco.Core/Models/Editors/UmbracoEntityReference.cs +++ b/src/Umbraco.Core/Models/Editors/UmbracoEntityReference.cs @@ -38,7 +38,7 @@ namespace Umbraco.Cms.Core.Models.Editors public Udi Udi { get; } public string RelationTypeAlias { get; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is UmbracoEntityReference reference && Equals(reference); } diff --git a/src/Umbraco.Core/Models/Email/NotificationEmailModel.cs b/src/Umbraco.Core/Models/Email/NotificationEmailModel.cs index a606e8e680..8351232789 100644 --- a/src/Umbraco.Core/Models/Email/NotificationEmailModel.cs +++ b/src/Umbraco.Core/Models/Email/NotificationEmailModel.cs @@ -24,7 +24,7 @@ namespace Umbraco.Cms.Core.Models.Email public bool IsBodyHtml { get; } - public IList Attachments { get; } + public IList? Attachments { get; } public bool HasAttachments => Attachments != null && Attachments.Count > 0; @@ -47,7 +47,7 @@ namespace Umbraco.Cms.Core.Models.Email Subject = subject; Body = body; IsBodyHtml = isBodyHtml; - Attachments = attachments?.ToList(); + Attachments = attachments.ToList(); } } diff --git a/src/Umbraco.Core/Models/Entities/BeingDirty.cs b/src/Umbraco.Core/Models/Entities/BeingDirty.cs index 7128e0ca65..7b078b35b8 100644 --- a/src/Umbraco.Core/Models/Entities/BeingDirty.cs +++ b/src/Umbraco.Core/Models/Entities/BeingDirty.cs @@ -20,7 +20,7 @@ namespace Umbraco.Cms.Core.Models.Entities /// A reference to the value to set. /// The property name. /// A comparer to compare property values. - public new void SetPropertyValueAndDetectChanges(T value, ref T valueRef, string propertyName, IEqualityComparer comparer = null) + public new void SetPropertyValueAndDetectChanges(T value, ref T? valueRef, string propertyName, IEqualityComparer? comparer = null) { base.SetPropertyValueAndDetectChanges(value, ref valueRef, propertyName, comparer); } diff --git a/src/Umbraco.Core/Models/Entities/BeingDirtyBase.cs b/src/Umbraco.Core/Models/Entities/BeingDirtyBase.cs index 976627bf23..c63ee54a6d 100644 --- a/src/Umbraco.Core/Models/Entities/BeingDirtyBase.cs +++ b/src/Umbraco.Core/Models/Entities/BeingDirtyBase.cs @@ -15,8 +15,8 @@ namespace Umbraco.Cms.Core.Models.Entities public abstract class BeingDirtyBase : IRememberBeingDirty { private bool _withChanges = true; // should we track changes? - private Dictionary _currentChanges; // which properties have changed? - private Dictionary _savedChanges; // which properties had changed at last commit? + private Dictionary? _currentChanges; // which properties have changed? + private Dictionary? _savedChanges; // which properties had changed at last commit? #region ICanBeDirty @@ -102,7 +102,7 @@ namespace Umbraco.Cms.Core.Models.Entities /// /// Occurs when a property changes. /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// /// Registers that a property has changed. @@ -144,7 +144,7 @@ namespace Umbraco.Cms.Core.Models.Entities /// A reference to the value to set. /// The property name. /// A comparer to compare property values. - protected void SetPropertyValueAndDetectChanges(T value, ref T valueRef, string propertyName, IEqualityComparer comparer = null) + protected void SetPropertyValueAndDetectChanges(T? value, ref T? valueRef, string propertyName, IEqualityComparer? comparer = null) { if (comparer == null) { diff --git a/src/Umbraco.Core/Models/Entities/EntityBase.cs b/src/Umbraco.Core/Models/Entities/EntityBase.cs index 77c497c68a..476dd00bab 100644 --- a/src/Umbraco.Core/Models/Entities/EntityBase.cs +++ b/src/Umbraco.Core/Models/Entities/EntityBase.cs @@ -87,12 +87,12 @@ namespace Umbraco.Cms.Core.Models.Entities return other != null && (ReferenceEquals(this, other) || SameIdentityAs(other)); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj != null && (ReferenceEquals(this, obj) || SameIdentityAs(obj as EntityBase)); } - private bool SameIdentityAs(EntityBase other) + private bool SameIdentityAs(EntityBase? other) { if (other == null) return false; diff --git a/src/Umbraco.Core/Models/Entities/EntitySlim.cs b/src/Umbraco.Core/Models/Entities/EntitySlim.cs index 3bf91bc5be..cdbd8d4ade 100644 --- a/src/Umbraco.Core/Models/Entities/EntitySlim.cs +++ b/src/Umbraco.Core/Models/Entities/EntitySlim.cs @@ -15,7 +15,7 @@ namespace Umbraco.Cms.Core.Models.Entities /// public class EntitySlim : IEntitySlim { - private IDictionary _additionalData; + private IDictionary? _additionalData; /// /// Gets an entity representing "root". @@ -53,7 +53,7 @@ namespace Umbraco.Cms.Core.Models.Entities /// [DataMember] - public string Name { get; set; } + public string? Name { get; set; } /// [DataMember] @@ -72,7 +72,7 @@ namespace Umbraco.Cms.Core.Models.Entities /// [DataMember] - public string Path { get; set; } + public string? Path { get; set; } /// [DataMember] @@ -87,7 +87,7 @@ namespace Umbraco.Cms.Core.Models.Entities /// [DataMember] - public IDictionary AdditionalData => _additionalData ?? (_additionalData = new Dictionary()); + public IDictionary? AdditionalData => _additionalData ?? (_additionalData = new Dictionary()); /// [IgnoreDataMember] diff --git a/src/Umbraco.Core/Models/Entities/IHaveAdditionalData.cs b/src/Umbraco.Core/Models/Entities/IHaveAdditionalData.cs index d36d190706..651e6a5f7a 100644 --- a/src/Umbraco.Core/Models/Entities/IHaveAdditionalData.cs +++ b/src/Umbraco.Core/Models/Entities/IHaveAdditionalData.cs @@ -15,7 +15,7 @@ namespace Umbraco.Cms.Core.Models.Entities /// /// Can be empty, but never null. To avoid allocating, do not /// test for emptiness, but use instead. - IDictionary AdditionalData { get; } + IDictionary? AdditionalData { get; } /// /// Determines whether this entity has additional data. diff --git a/src/Umbraco.Core/Models/Entities/ITreeEntity.cs b/src/Umbraco.Core/Models/Entities/ITreeEntity.cs index b970f46726..f52b17512e 100644 --- a/src/Umbraco.Core/Models/Entities/ITreeEntity.cs +++ b/src/Umbraco.Core/Models/Entities/ITreeEntity.cs @@ -8,7 +8,7 @@ /// /// Gets or sets the name of the entity. /// - string Name { get; set; } + string? Name { get; set; } /// /// Gets or sets the identifier of the user who created this entity. @@ -37,7 +37,7 @@ /// /// Gets or sets the path to the entity. /// - string Path { get; set; } + string? Path { get; set; } /// /// Gets or sets the sort order of the entity. diff --git a/src/Umbraco.Core/Models/Entities/TreeEntityBase.cs b/src/Umbraco.Core/Models/Entities/TreeEntityBase.cs index 629e01a706..680dbdde0f 100644 --- a/src/Umbraco.Core/Models/Entities/TreeEntityBase.cs +++ b/src/Umbraco.Core/Models/Entities/TreeEntityBase.cs @@ -8,19 +8,19 @@ namespace Umbraco.Cms.Core.Models.Entities /// public abstract class TreeEntityBase : EntityBase, ITreeEntity { - private string _name; + private string? _name; private int _creatorId; private int _parentId; private bool _hasParentId; - private ITreeEntity _parent; + private ITreeEntity? _parent; private int _level; - private string _path; + private string? _path; private int _sortOrder; private bool _trashed; /// [DataMember] - public string Name + public string? Name { get => _name; set => SetPropertyValueAndDetectChanges(value, ref _name, nameof(Name)); @@ -81,7 +81,7 @@ namespace Umbraco.Cms.Core.Models.Entities /// [DataMember] - public string Path + public string? Path { get => _path; set => SetPropertyValueAndDetectChanges(value, ref _path, nameof(Path)); diff --git a/src/Umbraco.Core/Models/File.cs b/src/Umbraco.Core/Models/File.cs index 7c7031a027..ec493ad937 100644 --- a/src/Umbraco.Core/Models/File.cs +++ b/src/Umbraco.Core/Models/File.cs @@ -18,10 +18,10 @@ namespace Umbraco.Cms.Core.Models // should use the lazyContent ctor to set it to null when loading existing. // cannot simply use HasIdentity as some classes (eg Script) override it // in a weird way. - private string _content; - public Func GetFileContent { get; set; } + private string? _content; + public Func? GetFileContent { get; set; } - protected File(string path, Func getFileContent = null) + protected File(string path, Func? getFileContent = null) { _path = SanitizePath(path); _originalPath = _path; @@ -29,8 +29,8 @@ namespace Umbraco.Cms.Core.Models _content = getFileContent != null ? null : string.Empty; } - private string _alias; - private string _name; + private string? _alias; + private string? _name; private static string SanitizePath(string path) { @@ -84,7 +84,7 @@ namespace Umbraco.Cms.Core.Models _alias = null; _name = null; - SetPropertyValueAndDetectChanges(SanitizePath(value), ref _path, nameof(Path)); + SetPropertyValueAndDetectChanges(SanitizePath(value), ref _path!, nameof(Path)); } } @@ -110,7 +110,7 @@ namespace Umbraco.Cms.Core.Models /// Marked as DoNotClone, because it should be lazy-reloaded from disk. [DataMember] [DoNotClone] - public virtual string Content + public virtual string? Content { get { @@ -133,7 +133,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets or sets the file's virtual path (i.e. the file path relative to the root of the website) /// - public string VirtualPath { get; set; } + public string? VirtualPath { get; set; } // this exists so that class that manage name and alias differently, eg Template, // can implement their own cloning - (though really, not sure it's even needed) diff --git a/src/Umbraco.Core/Models/HaveAdditionalDataExtensions.cs b/src/Umbraco.Core/Models/HaveAdditionalDataExtensions.cs index 033bb26d26..1c1c377403 100644 --- a/src/Umbraco.Core/Models/HaveAdditionalDataExtensions.cs +++ b/src/Umbraco.Core/Models/HaveAdditionalDataExtensions.cs @@ -10,11 +10,11 @@ namespace Umbraco.Extensions /// /// Gets additional data. /// - public static object GetAdditionalDataValueIgnoreCase(this IHaveAdditionalData entity, string key, object defaultValue) + public static object? GetAdditionalDataValueIgnoreCase(this IHaveAdditionalData entity, string key, object? defaultValue) { if (!entity.HasAdditionalData) return defaultValue; - if (entity.AdditionalData.ContainsKeyIgnoreCase(key) == false) return defaultValue; - return entity.AdditionalData.GetValueIgnoreCase(key, defaultValue); + if (entity.AdditionalData?.ContainsKeyIgnoreCase(key) == false) return defaultValue; + return entity.AdditionalData?.GetValueIgnoreCase(key, defaultValue); } } } diff --git a/src/Umbraco.Core/Models/IAuditEntry.cs b/src/Umbraco.Core/Models/IAuditEntry.cs index c756a80004..e12237f06d 100644 --- a/src/Umbraco.Core/Models/IAuditEntry.cs +++ b/src/Umbraco.Core/Models/IAuditEntry.cs @@ -23,12 +23,12 @@ namespace Umbraco.Cms.Core.Models /// /// Gets or sets free-form details about the user triggering the audited event. /// - string PerformingDetails { get; set; } + string? PerformingDetails { get; set; } /// /// Gets or sets the IP address or the request triggering the audited event. /// - string PerformingIp { get; set; } + string? PerformingIp { get; set; } /// /// Gets or sets the date and time of the audited event. @@ -45,16 +45,16 @@ namespace Umbraco.Cms.Core.Models /// Gets or sets free-form details about the entity affected by the audited event. /// /// The entity affected by the event can be another user, a member... - string AffectedDetails { get; set; } + string? AffectedDetails { get; set; } /// /// Gets or sets the type of the audited event. /// - string EventType { get; set; } + string? EventType { get; set; } /// /// Gets or sets free-form details about the audited event. /// - string EventDetails { get; set; } + string? EventDetails { get; set; } } } diff --git a/src/Umbraco.Core/Models/IAuditItem.cs b/src/Umbraco.Core/Models/IAuditItem.cs index 4189b49410..9a70a11428 100644 --- a/src/Umbraco.Core/Models/IAuditItem.cs +++ b/src/Umbraco.Core/Models/IAuditItem.cs @@ -25,11 +25,11 @@ namespace Umbraco.Cms.Core.Models /// /// Gets the audit comments. /// - string Comment { get; } + string? Comment { get; } /// /// Gets optional additional data parameters. /// - string Parameters { get; } + string? Parameters { get; } } } diff --git a/src/Umbraco.Core/Models/IConsent.cs b/src/Umbraco.Core/Models/IConsent.cs index b02cd42282..747e7a145c 100644 --- a/src/Umbraco.Core/Models/IConsent.cs +++ b/src/Umbraco.Core/Models/IConsent.cs @@ -21,7 +21,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets the unique identifier of whoever is consenting. /// - string Source { get; } + string? Source { get; } /// /// Gets the unique identifier of the context of the consent. @@ -30,12 +30,12 @@ namespace Umbraco.Cms.Core.Models /// Represents the domain, application, scope... of the action. /// When the action is a Udi, this should be the Udi type. /// - string Context { get; } + string? Context { get; } /// /// Gets the unique identifier of the consented action. /// - string Action { get; } + string? Action { get; } /// /// Gets the state of the consent. @@ -45,11 +45,11 @@ namespace Umbraco.Cms.Core.Models /// /// Gets some additional free text. /// - string Comment { get; } + string? Comment { get; } /// /// Gets the previous states of this consent. /// - IEnumerable History { get; } + IEnumerable? History { get; } } } diff --git a/src/Umbraco.Core/Models/IContent.cs b/src/Umbraco.Core/Models/IContent.cs index 4951741122..e538b307e2 100644 --- a/src/Umbraco.Core/Models/IContent.cs +++ b/src/Umbraco.Core/Models/IContent.cs @@ -51,7 +51,7 @@ namespace Umbraco.Cms.Core.Models /// Gets the name of the published version of the content. /// /// When editing the content, the name can change, but this will not until the content is published. - string PublishName { get; set; } + string? PublishName { get; set; } /// /// Gets the identifier of the user who published the content. @@ -100,7 +100,7 @@ namespace Umbraco.Cms.Core.Models /// When is null, gets the invariant /// language, which is the value of the property. /// - string GetPublishName(string culture); + string? GetPublishName(string? culture); /// /// Gets the published culture infos of the content. @@ -109,7 +109,7 @@ namespace Umbraco.Cms.Core.Models /// Because a dictionary key cannot be null this cannot get the invariant /// name, which must be get via the property. /// - ContentCultureInfosCollection PublishCultureInfos { get; set; } + ContentCultureInfosCollection? PublishCultureInfos { get; set; } /// /// Gets the published cultures. @@ -119,7 +119,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets the edited cultures. /// - IEnumerable EditedCultures { get; set; } + IEnumerable? EditedCultures { get; set; } /// /// Creates a deep clone of the current entity with its identity/alias and it's property identities reset diff --git a/src/Umbraco.Core/Models/IContentBase.cs b/src/Umbraco.Core/Models/IContentBase.cs index 6053be2d38..674bc9aa68 100644 --- a/src/Umbraco.Core/Models/IContentBase.cs +++ b/src/Umbraco.Core/Models/IContentBase.cs @@ -43,7 +43,7 @@ namespace Umbraco.Cms.Core.Models /// When is not null, throws if the content /// type does not vary by culture. /// - void SetCultureName(string value, string culture); + void SetCultureName(string? value, string culture); /// /// Gets the name of the content item for a specified language. @@ -54,7 +54,7 @@ namespace Umbraco.Cms.Core.Models /// When is not null, and the content type /// does not vary by culture, returns null. /// - string GetCultureName(string culture); + string? GetCultureName(string? culture); /// /// Gets culture infos of the content item. @@ -63,7 +63,7 @@ namespace Umbraco.Cms.Core.Models /// Because a dictionary key cannot be null this cannot contain the invariant /// culture name, which must be get or set via the property. /// - ContentCultureInfosCollection CultureInfos { get; set; } + ContentCultureInfosCollection? CultureInfos { get; set; } /// /// Gets the available cultures. @@ -112,13 +112,13 @@ namespace Umbraco.Cms.Core.Models /// Gets the value of a Property /// /// Values 'null' and 'empty' are equivalent for culture and segment. - object GetValue(string propertyTypeAlias, string? culture = null, string? segment = null, bool published = false); + object? GetValue(string propertyTypeAlias, string? culture = null, string? segment = null, bool published = false); /// /// Gets the typed value of a Property /// /// Values 'null' and 'empty' are equivalent for culture and segment. - TValue GetValue(string propertyTypeAlias, string? culture = null, string? segment = null, bool published = false); + TValue? GetValue(string propertyTypeAlias, string? culture = null, string? segment = null, bool published = false); /// /// Sets the (edited) value of a Property diff --git a/src/Umbraco.Core/Models/IContentType.cs b/src/Umbraco.Core/Models/IContentType.cs index a689da4c05..e3fd83fcd3 100644 --- a/src/Umbraco.Core/Models/IContentType.cs +++ b/src/Umbraco.Core/Models/IContentType.cs @@ -14,7 +14,7 @@ namespace Umbraco.Cms.Core.Models /// Gets or sets the history cleanup configuration. /// /// The history cleanup configuration. - HistoryCleanup HistoryCleanup { get; set; } + HistoryCleanup? HistoryCleanup { get; set; } } /// @@ -30,12 +30,12 @@ namespace Umbraco.Cms.Core.Models /// /// Gets the default Template of the ContentType /// - ITemplate DefaultTemplate { get; } + ITemplate? DefaultTemplate { get; } /// /// Gets or Sets a list of Templates which are allowed for the ContentType /// - IEnumerable AllowedTemplates { get; set; } + IEnumerable? AllowedTemplates { get; set; } /// /// Determines if AllowedTemplates contains templateId @@ -55,7 +55,7 @@ namespace Umbraco.Cms.Core.Models /// Sets the default template for the ContentType /// /// Default - void SetDefaultTemplate(ITemplate template); + void SetDefaultTemplate(ITemplate? template); /// /// Removes a template from the list of allowed templates diff --git a/src/Umbraco.Core/Models/IContentTypeBase.cs b/src/Umbraco.Core/Models/IContentTypeBase.cs index bb5bd1182f..000660c54f 100644 --- a/src/Umbraco.Core/Models/IContentTypeBase.cs +++ b/src/Umbraco.Core/Models/IContentTypeBase.cs @@ -17,7 +17,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets or Sets the Description for the ContentType /// - string Description { get; set; } + string? Description { get; set; } /// /// Gets or sets the icon for the content type. The value is a CSS class name representing @@ -27,12 +27,12 @@ namespace Umbraco.Cms.Core.Models /// /// If a class name for the color isn't specified, the icon color will default to black. /// - string Icon { get; set; } + string? Icon { get; set; } /// /// Gets or Sets the Thumbnail for the ContentType /// - string Thumbnail { get; set; } + string? Thumbnail { get; set; } /// /// Gets or Sets a boolean indicating whether this ContentType is allowed at the root @@ -92,7 +92,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets or Sets a list of integer Ids of the ContentTypes allowed under the ContentType /// - IEnumerable AllowedContentTypes { get; set; } + IEnumerable? AllowedContentTypes { get; set; } /// /// Gets or sets the local property groups. @@ -137,7 +137,7 @@ namespace Umbraco.Cms.Core.Models /// /// Returns true if the property type was added; otherwise, false. /// - bool AddPropertyType(IPropertyType propertyType, string propertyGroupAlias, string propertyGroupName = null); + bool AddPropertyType(IPropertyType propertyType, string propertyGroupAlias, string? propertyGroupName = null); /// /// Adds a PropertyType, which does not belong to a PropertyGroup. diff --git a/src/Umbraco.Core/Models/IDataType.cs b/src/Umbraco.Core/Models/IDataType.cs index 4c6d0a3e31..d0819b9fae 100644 --- a/src/Umbraco.Core/Models/IDataType.cs +++ b/src/Umbraco.Core/Models/IDataType.cs @@ -33,6 +33,6 @@ namespace Umbraco.Cms.Core.Models /// The serialized Json is deserialized by the property editor, which by default should /// return a Dictionary{string, object} but could return a typed object e.g. MyEditor.Configuration. /// - object Configuration { get; set; } + object? Configuration { get; set; } } } diff --git a/src/Umbraco.Core/Models/IDictionaryItem.cs b/src/Umbraco.Core/Models/IDictionaryItem.cs index f299ce2ac5..5b0d868f83 100644 --- a/src/Umbraco.Core/Models/IDictionaryItem.cs +++ b/src/Umbraco.Core/Models/IDictionaryItem.cs @@ -23,6 +23,6 @@ namespace Umbraco.Cms.Core.Models /// Gets or sets a list of translations for the Dictionary Item /// [DataMember] - IEnumerable Translations { get; set; } + IEnumerable? Translations { get; set; } } } diff --git a/src/Umbraco.Core/Models/IDictionaryTranslation.cs b/src/Umbraco.Core/Models/IDictionaryTranslation.cs index c80318d073..372bb4488d 100644 --- a/src/Umbraco.Core/Models/IDictionaryTranslation.cs +++ b/src/Umbraco.Core/Models/IDictionaryTranslation.cs @@ -9,7 +9,7 @@ namespace Umbraco.Cms.Core.Models /// Gets or sets the for the translation /// [DataMember] - ILanguage Language { get; set; } + ILanguage? Language { get; set; } int LanguageId { get; } @@ -17,6 +17,6 @@ namespace Umbraco.Cms.Core.Models /// Gets or sets the translated text /// [DataMember] - string Value { get; set; } + string? Value { get; set; } } } diff --git a/src/Umbraco.Core/Models/IFile.cs b/src/Umbraco.Core/Models/IFile.cs index 48a2e234b6..216d45d277 100644 --- a/src/Umbraco.Core/Models/IFile.cs +++ b/src/Umbraco.Core/Models/IFile.cs @@ -11,7 +11,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets the Name of the File including extension /// - string Name { get; } + string? Name { get; } /// /// Gets the Alias of the File, which is the name without the extension @@ -36,12 +36,12 @@ namespace Umbraco.Cms.Core.Models /// /// Gets or sets the Content of a File /// - string Content { get; set; } + string? Content { get; set; } /// /// Gets or sets the file's virtual path (i.e. the file path relative to the root of the website) /// - string VirtualPath { get; set; } + string? VirtualPath { get; set; } } } diff --git a/src/Umbraco.Core/Models/IKeyValue.cs b/src/Umbraco.Core/Models/IKeyValue.cs index 52c1f5c568..767e22a8c3 100644 --- a/src/Umbraco.Core/Models/IKeyValue.cs +++ b/src/Umbraco.Core/Models/IKeyValue.cs @@ -4,8 +4,8 @@ namespace Umbraco.Cms.Core.Models { public interface IKeyValue : IEntity { - string Identifier { get; set; } + string? Identifier { get; set; } - string Value { get; set; } + string? Value { get; set; } } } diff --git a/src/Umbraco.Core/Models/ILanguage.cs b/src/Umbraco.Core/Models/ILanguage.cs index 363f8df138..d392e2bb37 100644 --- a/src/Umbraco.Core/Models/ILanguage.cs +++ b/src/Umbraco.Core/Models/ILanguage.cs @@ -25,7 +25,7 @@ namespace Umbraco.Cms.Core.Models /// Gets the object for the language. /// [IgnoreDataMember] - CultureInfo CultureInfo { get; } + CultureInfo? CultureInfo { get; } /// /// Gets or sets a value indicating whether the language is the default language. diff --git a/src/Umbraco.Core/Models/ILogViewerQuery.cs b/src/Umbraco.Core/Models/ILogViewerQuery.cs index 3b36f0a9e8..59a567a635 100644 --- a/src/Umbraco.Core/Models/ILogViewerQuery.cs +++ b/src/Umbraco.Core/Models/ILogViewerQuery.cs @@ -4,7 +4,7 @@ namespace Umbraco.Cms.Core.Models { public interface ILogViewerQuery : IEntity { - string Name { get; set; } - string Query { get; set; } + string? Name { get; set; } + string? Query { get; set; } } } diff --git a/src/Umbraco.Core/Models/IMacro.cs b/src/Umbraco.Core/Models/IMacro.cs index e91da77774..229c03348a 100644 --- a/src/Umbraco.Core/Models/IMacro.cs +++ b/src/Umbraco.Core/Models/IMacro.cs @@ -18,7 +18,7 @@ namespace Umbraco.Cms.Core.Models /// Gets or sets the name of the Macro /// [DataMember] - string Name { get; set; } + string? Name { get; set; } /// /// Gets or sets a boolean indicating whether the Macro can be used in an Editor @@ -54,7 +54,7 @@ namespace Umbraco.Cms.Core.Models /// Gets or set the path to the macro source to render /// [DataMember] - string MacroSource { get; set; } + string? MacroSource { get; set; } /// /// Gets or sets a list of Macro Properties diff --git a/src/Umbraco.Core/Models/IMacroProperty.cs b/src/Umbraco.Core/Models/IMacroProperty.cs index 609c1bf044..d3d589a31e 100644 --- a/src/Umbraco.Core/Models/IMacroProperty.cs +++ b/src/Umbraco.Core/Models/IMacroProperty.cs @@ -25,7 +25,7 @@ namespace Umbraco.Cms.Core.Models /// Gets or sets the Name of the Property /// [DataMember] - string Name { get; set; } + string? Name { get; set; } /// /// Gets or sets the Sort Order of the Property diff --git a/src/Umbraco.Core/Models/IMember.cs b/src/Umbraco.Core/Models/IMember.cs index c78d1012a9..0dba1d8049 100644 --- a/src/Umbraco.Core/Models/IMember.cs +++ b/src/Umbraco.Core/Models/IMember.cs @@ -19,7 +19,7 @@ namespace Umbraco.Cms.Core.Models /// Adding these to have first level properties instead of the Properties collection. /// [EditorBrowsable(EditorBrowsableState.Never)] - string LongStringPropertyValue { get; set; } + string? LongStringPropertyValue { get; set; } /// /// Internal/Experimental - only used for mapping queries. /// @@ -27,7 +27,7 @@ namespace Umbraco.Cms.Core.Models /// Adding these to have first level properties instead of the Properties collection. /// [EditorBrowsable(EditorBrowsableState.Never)] - string ShortStringPropertyValue { get; set; } + string? ShortStringPropertyValue { get; set; } /// /// Internal/Experimental - only used for mapping queries. /// @@ -59,6 +59,6 @@ namespace Umbraco.Cms.Core.Models /// Adding these to have first level properties instead of the Properties collection. /// [EditorBrowsable(EditorBrowsableState.Never)] - string PropertyTypeAlias { get; set; } + string? PropertyTypeAlias { get; set; } } } diff --git a/src/Umbraco.Core/Models/IMemberGroup.cs b/src/Umbraco.Core/Models/IMemberGroup.cs index ff6ba0c5b9..80d4a16ad6 100644 --- a/src/Umbraco.Core/Models/IMemberGroup.cs +++ b/src/Umbraco.Core/Models/IMemberGroup.cs @@ -10,7 +10,7 @@ namespace Umbraco.Cms.Core.Models /// /// The name of the member group /// - string Name { get; set; } + string? Name { get; set; } /// /// Profile of the user who created this Entity diff --git a/src/Umbraco.Core/Models/IMigrationEntry.cs b/src/Umbraco.Core/Models/IMigrationEntry.cs index b5dae1981a..a3d11e851a 100644 --- a/src/Umbraco.Core/Models/IMigrationEntry.cs +++ b/src/Umbraco.Core/Models/IMigrationEntry.cs @@ -5,7 +5,7 @@ namespace Umbraco.Cms.Core.Models { public interface IMigrationEntry : IEntity, IRememberBeingDirty { - string MigrationName { get; set; } - SemVersion Version { get; set; } + string? MigrationName { get; set; } + SemVersion? Version { get; set; } } } diff --git a/src/Umbraco.Core/Models/IProperty.cs b/src/Umbraco.Core/Models/IProperty.cs index 0fc8af9a22..0b9ecffe46 100644 --- a/src/Umbraco.Core/Models/IProperty.cs +++ b/src/Umbraco.Core/Models/IProperty.cs @@ -10,7 +10,7 @@ namespace Umbraco.Cms.Core.Models /// /// Returns the PropertyType, which this Property is based on /// - IPropertyType PropertyType { get; } + IPropertyType? PropertyType { get; } /// /// Gets the list of values. @@ -25,7 +25,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets the value. /// - object GetValue(string? culture = null, string? segment = null, bool published = false); + object? GetValue(string? culture = null, string? segment = null, bool published = false); /// /// Sets a value. @@ -33,8 +33,8 @@ namespace Umbraco.Cms.Core.Models void SetValue(object? value, string? culture = null, string? segment = null); int PropertyTypeId { get; } - void PublishValues(string culture = "*", string segment = "*"); - void UnpublishValues(string culture = "*", string segment = "*"); + void PublishValues(string? culture = "*", string segment = "*"); + void UnpublishValues(string? culture = "*", string segment = "*"); } } diff --git a/src/Umbraco.Core/Models/IPropertyType.cs b/src/Umbraco.Core/Models/IPropertyType.cs index adb8e283ee..2e70c64cd9 100644 --- a/src/Umbraco.Core/Models/IPropertyType.cs +++ b/src/Umbraco.Core/Models/IPropertyType.cs @@ -8,7 +8,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets of sets the name of the property type. /// - string Name { get; set; } + string? Name { get; set; } /// /// Gets of sets the alias of the property type. @@ -18,7 +18,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets of sets the description of the property type. /// - string Description { get; set; } + string? Description { get; set; } /// /// Gets or sets the identifier of the datatype for this property type. @@ -41,12 +41,12 @@ namespace Umbraco.Cms.Core.Models /// Gets or sets the identifier of the property group this property type belongs to. /// /// For generic properties, the value is null. - Lazy PropertyGroupId { get; set; } + Lazy? PropertyGroupId { get; set; } /// /// Gets of sets a value indicating whether a value for this property type is required. /// - bool Mandatory { get; set; } + bool? Mandatory { get; set; } /// /// Gets or sets a value indicating whether the label of this property type should be displayed on top. @@ -61,7 +61,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets or sets the regular expression validating the property values. /// - string ValidationRegExp { get; set; } + string? ValidationRegExp { get; set; } bool SupportsPublishing { get; set; } @@ -76,16 +76,16 @@ namespace Umbraco.Cms.Core.Models /// The culture. /// The segment. /// A value indicating whether wildcards are valid. - bool SupportsVariation(string culture, string segment, bool wildcards = false); + bool SupportsVariation(string? culture, string? segment, bool wildcards = false); /// /// Gets or sets the custom validation message used when a value for this PropertyType is required /// - string MandatoryMessage { get; set; } + string? MandatoryMessage { get; set; } /// /// Gets or sets the custom validation message used when a pattern for this PropertyType must be matched /// - string ValidationRegExpMessage { get; set; } + string? ValidationRegExpMessage { get; set; } } } diff --git a/src/Umbraco.Core/Models/IPropertyValue.cs b/src/Umbraco.Core/Models/IPropertyValue.cs index 1bd391625b..77e9e1dc25 100644 --- a/src/Umbraco.Core/Models/IPropertyValue.cs +++ b/src/Umbraco.Core/Models/IPropertyValue.cs @@ -7,24 +7,24 @@ namespace Umbraco.Cms.Core.Models /// /// The culture is either null (invariant) or a non-empty string. If the property is /// set with an empty or whitespace value, its value is converted to null. - string Culture { get; set; } + string? Culture { get; set; } /// /// Gets or sets the segment of the property. /// /// The segment is either null (neutral) or a non-empty string. If the property is /// set with an empty or whitespace value, its value is converted to null. - string Segment { get; set; } + string? Segment { get; set; } /// /// Gets or sets the edited value of the property. /// - object EditedValue { get; set; } + object? EditedValue { get; set; } /// /// Gets or sets the published value of the property. /// - object PublishedValue { get; set; } + object? PublishedValue { get; set; } /// /// Clones the property value. diff --git a/src/Umbraco.Core/Models/IReadOnlyContentBase.cs b/src/Umbraco.Core/Models/IReadOnlyContentBase.cs index e327a49f29..f7518140f5 100644 --- a/src/Umbraco.Core/Models/IReadOnlyContentBase.cs +++ b/src/Umbraco.Core/Models/IReadOnlyContentBase.cs @@ -27,7 +27,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets the name of the entity. /// - string Name { get; } + string? Name { get; } /// /// Gets the identifier of the user who created this entity. @@ -47,7 +47,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets the path to the entity. /// - string Path { get; } + string? Path { get; } /// /// Gets the sort order of the entity. diff --git a/src/Umbraco.Core/Models/IRedirectUrl.cs b/src/Umbraco.Core/Models/IRedirectUrl.cs index 7e007559a5..f2e4e131a7 100644 --- a/src/Umbraco.Core/Models/IRedirectUrl.cs +++ b/src/Umbraco.Core/Models/IRedirectUrl.cs @@ -31,14 +31,14 @@ namespace Umbraco.Cms.Core.Models /// Gets or sets the culture. /// [DataMember] - string Culture { get; set; } + string? Culture { get; set; } /// /// Gets or sets the redirect URL route. /// /// Is a proper Umbraco route eg /path/to/foo or 123/path/tofoo. [DataMember] - string Url { get; set; } + string? Url { get; set; } } } diff --git a/src/Umbraco.Core/Models/IRelation.cs b/src/Umbraco.Core/Models/IRelation.cs index 7a0fe756ed..0370bbe61f 100644 --- a/src/Umbraco.Core/Models/IRelation.cs +++ b/src/Umbraco.Core/Models/IRelation.cs @@ -34,7 +34,7 @@ namespace Umbraco.Cms.Core.Models /// Gets or sets a comment for the Relation /// [DataMember] - string Comment { get; set; } + string? Comment { get; set; } /// /// Gets the Id of the that this Relation is based on. diff --git a/src/Umbraco.Core/Models/IRelationType.cs b/src/Umbraco.Core/Models/IRelationType.cs index 9efde4b939..c48e13fdc3 100644 --- a/src/Umbraco.Core/Models/IRelationType.cs +++ b/src/Umbraco.Core/Models/IRelationType.cs @@ -10,7 +10,7 @@ namespace Umbraco.Cms.Core.Models /// Gets or sets the Name of the RelationType /// [DataMember] - string Name { get; set; } + string? Name { get; set; } /// /// Gets or sets the Alias of the RelationType diff --git a/src/Umbraco.Core/Models/IServerRegistration.cs b/src/Umbraco.Core/Models/IServerRegistration.cs index 12319da6c8..7d8c0f58c1 100644 --- a/src/Umbraco.Core/Models/IServerRegistration.cs +++ b/src/Umbraco.Core/Models/IServerRegistration.cs @@ -9,9 +9,9 @@ namespace Umbraco.Cms.Core.Models /// /// Gets or sets the server unique identity. /// - string ServerIdentity { get; set; } + string? ServerIdentity { get; set; } - new string ServerAddress { get; set; } + new string? ServerAddress { get; set; } /// /// Gets or sets a value indicating whether the server is active. diff --git a/src/Umbraco.Core/Models/ISimpleContentType.cs b/src/Umbraco.Core/Models/ISimpleContentType.cs index 9f1ab38aca..503946ba96 100644 --- a/src/Umbraco.Core/Models/ISimpleContentType.cs +++ b/src/Umbraco.Core/Models/ISimpleContentType.cs @@ -9,7 +9,7 @@ namespace Umbraco.Cms.Core.Models { int Id { get; } Guid Key { get; } - string Name { get; } + string? Name { get; } /// /// Gets the alias of the content type. @@ -19,7 +19,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets the default template of the content type. /// - ITemplate DefaultTemplate { get; } + ITemplate? DefaultTemplate { get; } /// /// Gets the content variation of the content type. @@ -29,7 +29,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets the icon of the content type. /// - string Icon { get; } + string? Icon { get; } /// /// Gets a value indicating whether the content type is a container. @@ -58,6 +58,6 @@ namespace Umbraco.Cms.Core.Models /// then an invariant culture is valid, because some properties may be invariant. On the other hand, if the content type is invariant, /// then a variant culture is invalid, because no property could possibly vary by culture. /// - bool SupportsPropertyVariation(string culture, string segment, bool wildcards = false); + bool SupportsPropertyVariation(string? culture, string segment, bool wildcards = false); } } diff --git a/src/Umbraco.Core/Models/IStylesheet.cs b/src/Umbraco.Core/Models/IStylesheet.cs index 6ef0867d16..e7710f26df 100644 --- a/src/Umbraco.Core/Models/IStylesheet.cs +++ b/src/Umbraco.Core/Models/IStylesheet.cs @@ -12,7 +12,7 @@ namespace Umbraco.Cms.Core.Models /// /// /** umb_name: MyPropertyName */ p { font-size: 1em; } /// - IEnumerable Properties { get; } + IEnumerable? Properties { get; } /// /// Adds an Umbraco stylesheet property for use in the back office diff --git a/src/Umbraco.Core/Models/ITag.cs b/src/Umbraco.Core/Models/ITag.cs index 79840481bb..fdef14fec0 100644 --- a/src/Umbraco.Core/Models/ITag.cs +++ b/src/Umbraco.Core/Models/ITag.cs @@ -12,13 +12,13 @@ namespace Umbraco.Cms.Core.Models /// Gets or sets the tag group. /// [DataMember] - string Group { get; set; } + string? Group { get; set; } /// /// Gets or sets the tag text. /// [DataMember] - string Text { get; set; } + string? Text { get; set; } /// /// Gets or sets the tag language. diff --git a/src/Umbraco.Core/Models/ITemplate.cs b/src/Umbraco.Core/Models/ITemplate.cs index 1c4f794c49..3f82957eb5 100644 --- a/src/Umbraco.Core/Models/ITemplate.cs +++ b/src/Umbraco.Core/Models/ITemplate.cs @@ -10,7 +10,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets the Name of the File including extension /// - new string Name { get; set; } + new string? Name { get; set; } /// /// Gets the Alias of the File, which is the name without the extension @@ -25,7 +25,7 @@ namespace Umbraco.Cms.Core.Models /// /// returns the master template alias /// - string MasterTemplateAlias { get; } + string? MasterTemplateAlias { get; } /// /// Set the mastertemplate diff --git a/src/Umbraco.Core/Models/ImageUrlGenerationOptions.cs b/src/Umbraco.Core/Models/ImageUrlGenerationOptions.cs index ba5c1d0e30..d414a25852 100644 --- a/src/Umbraco.Core/Models/ImageUrlGenerationOptions.cs +++ b/src/Umbraco.Core/Models/ImageUrlGenerationOptions.cs @@ -19,13 +19,13 @@ namespace Umbraco.Cms.Core.Models public ImageCropAnchor? ImageCropAnchor { get; set; } - public FocalPointPosition FocalPoint { get; set; } + public FocalPointPosition? FocalPoint { get; set; } - public CropCoordinates Crop { get; set; } + public CropCoordinates? Crop { get; set; } - public string CacheBusterValue { get; set; } + public string? CacheBusterValue { get; set; } - public string FurtherOptions { get; set; } + public string? FurtherOptions { get; set; } /// /// The focal point position, in whatever units the registered IImageUrlGenerator uses, typically a percentage of the total image from 0.0 to 1.0. diff --git a/src/Umbraco.Core/Models/KeyValue.cs b/src/Umbraco.Core/Models/KeyValue.cs index eabb94568a..76f03c2729 100644 --- a/src/Umbraco.Core/Models/KeyValue.cs +++ b/src/Umbraco.Core/Models/KeyValue.cs @@ -11,18 +11,18 @@ namespace Umbraco.Cms.Core.Models [DataContract(IsReference = true)] public class KeyValue : EntityBase, IKeyValue, IEntity { - private string _identifier; - private string _value; + private string? _identifier; + private string? _value; /// - public string Identifier + public string? Identifier { get => _identifier; set => SetPropertyValueAndDetectChanges(value, ref _identifier, nameof(Identifier)); } /// - public string Value + public string? Value { get => _value; set => SetPropertyValueAndDetectChanges(value, ref _value, nameof(Value)); diff --git a/src/Umbraco.Core/Models/Language.cs b/src/Umbraco.Core/Models/Language.cs index 6be774f7d2..aa16262b15 100644 --- a/src/Umbraco.Core/Models/Language.cs +++ b/src/Umbraco.Core/Models/Language.cs @@ -16,8 +16,8 @@ namespace Umbraco.Cms.Core.Models { private readonly GlobalSettings _globalSettings; - private string _isoCode; - private string _cultureName; + private string _isoCode = string.Empty; + private string? _cultureName; private bool _isDefaultVariantLanguage; private bool _mandatory; private int? _fallbackLanguageId; @@ -33,7 +33,7 @@ namespace Umbraco.Cms.Core.Models public string IsoCode { get => _isoCode; - set => SetPropertyValueAndDetectChanges(value, ref _isoCode, nameof(IsoCode)); + set => SetPropertyValueAndDetectChanges(value, ref _isoCode!, nameof(IsoCode)); } /// @@ -95,7 +95,7 @@ namespace Umbraco.Cms.Core.Models /// [IgnoreDataMember] - public CultureInfo CultureInfo => CultureInfo.GetCultureInfo(IsoCode); + public CultureInfo? CultureInfo => IsoCode is not null ? CultureInfo.GetCultureInfo(IsoCode) : null; /// public bool IsDefault diff --git a/src/Umbraco.Core/Models/LogViewerQuery.cs b/src/Umbraco.Core/Models/LogViewerQuery.cs index 5addfa705f..05009733ae 100644 --- a/src/Umbraco.Core/Models/LogViewerQuery.cs +++ b/src/Umbraco.Core/Models/LogViewerQuery.cs @@ -8,8 +8,8 @@ namespace Umbraco.Cms.Core.Models [DataContract(IsReference = true)] public class LogViewerQuery : EntityBase, ILogViewerQuery { - private string _name; - private string _query; + private string? _name; + private string? _query; public LogViewerQuery(string name, string query) { @@ -18,14 +18,14 @@ namespace Umbraco.Cms.Core.Models } [DataMember] - public string Name + public string? Name { get => _name; set => SetPropertyValueAndDetectChanges(value, ref _name, nameof(Name)); } [DataMember] - public string Query + public string? Query { get => _query; set => SetPropertyValueAndDetectChanges(value, ref _query, nameof(Query)); diff --git a/src/Umbraco.Core/Models/Macro.cs b/src/Umbraco.Core/Models/Macro.cs index 7fd60b98f0..cfea0df550 100644 --- a/src/Umbraco.Core/Models/Macro.cs +++ b/src/Umbraco.Core/Models/Macro.cs @@ -21,6 +21,7 @@ namespace Umbraco.Cms.Core.Models public Macro(IShortStringHelper shortStringHelper) { + _alias = string.Empty; _shortStringHelper = shortStringHelper; _properties = new MacroPropertyCollection(); _properties.CollectionChanged += PropertiesChanged; @@ -87,46 +88,52 @@ namespace Umbraco.Cms.Core.Models } private string _alias; - private string _name; + private string? _name; private bool _useInEditor; private int _cacheDuration; private bool _cacheByPage; private bool _cacheByMember; private bool _dontRender; - private string _macroSource; + private string? _macroSource; private MacroPropertyCollection _properties; private List _addedProperties; private List _removedProperties; - void PropertiesChanged(object sender, NotifyCollectionChangedEventArgs e) + void PropertiesChanged(object? sender, NotifyCollectionChangedEventArgs e) { OnPropertyChanged(nameof(Properties)); if (e.Action == NotifyCollectionChangedAction.Add) { //listen for changes - var prop = e.NewItems.Cast().First(); - prop.PropertyChanged += PropertyDataChanged; - - var alias = prop.Alias; - - if (_addedProperties.Contains(alias) == false) + MacroProperty? prop = e.NewItems?.Cast().First(); + if (prop is not null) { - //add to the added props - _addedProperties.Add(alias); + prop.PropertyChanged += PropertyDataChanged; + + var alias = prop.Alias; + + if (_addedProperties.Contains(alias) == false) + { + //add to the added props + _addedProperties.Add(alias); + } } } else if (e.Action == NotifyCollectionChangedAction.Remove) { //remove listening for changes - var prop = e.OldItems.Cast().First(); - prop.PropertyChanged -= PropertyDataChanged; - - var alias = prop.Alias; - - if (_removedProperties.Contains(alias) == false) + var prop = e.OldItems?.Cast().First(); + if (prop is not null) { - _removedProperties.Add(alias); + prop.PropertyChanged -= PropertyDataChanged; + + var alias = prop.Alias; + + if (_removedProperties.Contains(alias) == false) + { + _removedProperties.Add(alias); + } } } } @@ -136,7 +143,7 @@ namespace Umbraco.Cms.Core.Models /// /// /// - void PropertyDataChanged(object sender, PropertyChangedEventArgs e) + void PropertyDataChanged(object? sender, PropertyChangedEventArgs e) { OnPropertyChanged(nameof(Properties)); } @@ -171,14 +178,14 @@ namespace Umbraco.Cms.Core.Models public string Alias { get => _alias; - set => SetPropertyValueAndDetectChanges(value.ToCleanString(_shortStringHelper, CleanStringType.Alias), ref _alias, nameof(Alias)); + set => SetPropertyValueAndDetectChanges(value.ToCleanString(_shortStringHelper, CleanStringType.Alias), ref _alias!, nameof(Alias)); } /// /// Gets or sets the name of the Macro /// [DataMember] - public string Name + public string? Name { get => _name; set => SetPropertyValueAndDetectChanges(value, ref _name, nameof(Name)); @@ -238,7 +245,7 @@ namespace Umbraco.Cms.Core.Models /// Gets or set the path to the Partial View to render /// [DataMember] - public string MacroSource + public string? MacroSource { get => _macroSource; set => SetPropertyValueAndDetectChanges(value, ref _macroSource, nameof(MacroSource)); diff --git a/src/Umbraco.Core/Models/MacroProperty.cs b/src/Umbraco.Core/Models/MacroProperty.cs index a8f4ece17c..e0f5001244 100644 --- a/src/Umbraco.Core/Models/MacroProperty.cs +++ b/src/Umbraco.Core/Models/MacroProperty.cs @@ -13,6 +13,8 @@ namespace Umbraco.Cms.Core.Models { public MacroProperty() { + _editorAlias = string.Empty; + _alias = string.Empty; _key = Guid.NewGuid(); } @@ -53,7 +55,7 @@ namespace Umbraco.Cms.Core.Models private Guid _key; private string _alias; - private string _name; + private string? _name; private int _sortOrder; private int _id; private string _editorAlias; @@ -85,14 +87,14 @@ namespace Umbraco.Cms.Core.Models public string Alias { get => _alias; - set => SetPropertyValueAndDetectChanges(value, ref _alias, nameof(Alias)); + set => SetPropertyValueAndDetectChanges(value, ref _alias!, nameof(Alias)); } /// /// Gets or sets the Name of the Property /// [DataMember] - public string Name + public string? Name { get => _name; set => SetPropertyValueAndDetectChanges(value, ref _name, nameof(Name)); @@ -119,7 +121,7 @@ namespace Umbraco.Cms.Core.Models public string EditorAlias { get => _editorAlias; - set => SetPropertyValueAndDetectChanges(value, ref _editorAlias, nameof(EditorAlias)); + set => SetPropertyValueAndDetectChanges(value, ref _editorAlias!, nameof(EditorAlias)); } public object DeepClone() @@ -138,7 +140,7 @@ namespace Umbraco.Cms.Core.Models return string.Equals(_alias, other._alias) && _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/Models/MacroPropertyCollection.cs b/src/Umbraco.Core/Models/MacroPropertyCollection.cs index f2f0b6520f..cda46d2af7 100644 --- a/src/Umbraco.Core/Models/MacroPropertyCollection.cs +++ b/src/Umbraco.Core/Models/MacroPropertyCollection.cs @@ -34,7 +34,7 @@ namespace Umbraco.Cms.Core.Models /// The existing property alias /// /// - public void UpdateProperty(string currentAlias, string name = null, int? sortOrder = null, string editorAlias = null, string newAlias = null) + public void UpdateProperty(string currentAlias, string? name = null, int? sortOrder = null, string? editorAlias = null, string? newAlias = null) { var prop = this[currentAlias]; if (prop == null) @@ -50,12 +50,12 @@ namespace Umbraco.Cms.Core.Models { prop.SortOrder = sortOrder.Value; } - if (name.IsNullOrWhiteSpace() == false) + if (name.IsNullOrWhiteSpace() == false && editorAlias is not null) { prop.EditorAlias = editorAlias; } - if (newAlias.IsNullOrWhiteSpace() == false && currentAlias != newAlias) + if (newAlias.IsNullOrWhiteSpace() == false && currentAlias != newAlias && newAlias is not null) { prop.Alias = newAlias; ChangeKey(currentAlias, newAlias); diff --git a/src/Umbraco.Core/Models/Mapping/CommonMapper.cs b/src/Umbraco.Core/Models/Mapping/CommonMapper.cs index 3cfcc89085..20b7eca922 100644 --- a/src/Umbraco.Core/Models/Mapping/CommonMapper.cs +++ b/src/Umbraco.Core/Models/Mapping/CommonMapper.cs @@ -28,13 +28,13 @@ namespace Umbraco.Cms.Core.Models.Mapping _localizedTextService = localizedTextService; } - public UserProfile GetOwner(IContentBase source, MapperContext context) + public UserProfile? GetOwner(IContentBase source, MapperContext context) { var profile = source.GetCreatorProfile(_userService); return profile == null ? null : context.Map(profile); } - public UserProfile GetCreator(IContent source, MapperContext context) + public UserProfile? GetCreator(IContent source, MapperContext context) { var profile = source.GetWriterProfile(_userService); return profile == null ? null : context.Map(profile); diff --git a/src/Umbraco.Core/Models/Mapping/ContentPropertyDisplayMapper.cs b/src/Umbraco.Core/Models/Mapping/ContentPropertyDisplayMapper.cs index 3957699deb..86d0d37f58 100644 --- a/src/Umbraco.Core/Models/Mapping/ContentPropertyDisplayMapper.cs +++ b/src/Umbraco.Core/Models/Mapping/ContentPropertyDisplayMapper.cs @@ -38,13 +38,13 @@ namespace Umbraco.Cms.Core.Models.Mapping // - does it make any sense to use a IDataValueEditor without configuring it? // configure the editor for display with configuration - var valEditor = dest.PropertyEditor.GetValueEditor(config); + var valEditor = dest.PropertyEditor?.GetValueEditor(config); //set the display properties after mapping dest.Alias = originalProp.Alias; dest.Description = originalProp.PropertyType.Description; dest.Label = originalProp.PropertyType.Name; - dest.HideLabel = valEditor.HideLabel; + dest.HideLabel = valEditor?.HideLabel ?? false; dest.LabelOnTop = originalProp.PropertyType.LabelOnTop; //add the validation information @@ -64,7 +64,7 @@ namespace Umbraco.Cms.Core.Models.Mapping { //let the property editor format the pre-values dest.Config = dest.PropertyEditor.GetConfigurationEditor().ToValueEditor(config); - dest.View = valEditor.View; + dest.View = valEditor?.View; } //Translate diff --git a/src/Umbraco.Core/Models/Mapping/ContentTypeMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/ContentTypeMapDefinition.cs index 3625e90a14..2bea03098d 100644 --- a/src/Umbraco.Core/Models/Mapping/ContentTypeMapDefinition.cs +++ b/src/Umbraco.Core/Models/Mapping/ContentTypeMapDefinition.cs @@ -163,8 +163,8 @@ namespace Umbraco.Cms.Core.Models.Mapping foreach (MemberPropertyTypeBasic propertyType in source.Groups.SelectMany(x => x.Properties)) { MemberPropertyTypeBasic localCopy = propertyType; - IPropertyType destProp = - target.PropertyTypes.SingleOrDefault(x => x.Alias.InvariantEquals(localCopy.Alias)); + IPropertyType? destProp = + target.PropertyTypes.SingleOrDefault(x => x.Alias?.InvariantEquals(localCopy.Alias) ?? false); if (destProp == null) { continue; @@ -199,7 +199,10 @@ namespace Umbraco.Cms.Core.Models.Mapping target.ContentApps = _commonMapper.GetContentApps(source); //sync templates - target.AllowedTemplates = context.MapEnumerable(source.AllowedTemplates); + if (source.AllowedTemplates is not null) + { + target.AllowedTemplates = context.MapEnumerable(source.AllowedTemplates); + } if (source.DefaultTemplate != null) { @@ -251,8 +254,8 @@ namespace Umbraco.Cms.Core.Models.Mapping foreach (IPropertyType propertyType in source.PropertyTypes) { IPropertyType localCopy = propertyType; - MemberPropertyTypeDisplay displayProp = target.Groups.SelectMany(dest => dest.Properties) - .SingleOrDefault(dest => dest.Alias.InvariantEquals(localCopy.Alias)); + MemberPropertyTypeDisplay? displayProp = target.Groups.SelectMany(dest => dest.Properties) + .SingleOrDefault(dest => dest.Alias?.InvariantEquals(localCopy.Alias) ?? false); if (displayProp == null) { continue; @@ -314,10 +317,10 @@ namespace Umbraco.Cms.Core.Models.Mapping target.Name = source.Label; target.DataTypeId = source.DataTypeId; target.DataTypeKey = source.DataTypeKey; - target.Mandatory = source.Validation.Mandatory; - target.MandatoryMessage = source.Validation.MandatoryMessage; - target.ValidationRegExp = source.Validation.Pattern; - target.ValidationRegExpMessage = source.Validation.PatternMessage; + target.Mandatory = source.Validation?.Mandatory; + target.MandatoryMessage = source.Validation?.MandatoryMessage; + target.ValidationRegExp = source.Validation?.Pattern; + target.ValidationRegExpMessage = source.Validation?.PatternMessage; target.SetVariesBy(ContentVariation.Culture, source.AllowCultureVariant); target.SetVariesBy(ContentVariation.Segment, source.AllowSegmentVariant); @@ -344,7 +347,7 @@ namespace Umbraco.Cms.Core.Models.Mapping target, context); //sync templates - IEnumerable destAllowedTemplateAliases = target.AllowedTemplates.Select(x => x.Alias); + IEnumerable destAllowedTemplateAliases = target.AllowedTemplates.Select(x => x.Alias); //if the dest is set and it's the same as the source, then don't change if (destAllowedTemplateAliases.SequenceEqual(source.AllowedTemplates) == false) { @@ -352,7 +355,7 @@ namespace Umbraco.Cms.Core.Models.Mapping target.AllowedTemplates = source.AllowedTemplates .Select(x => { - ITemplate template = templates.SingleOrDefault(t => t.Alias == x); + ITemplate? template = templates.SingleOrDefault(t => t.Alias == x); return template != null ? context.Map(template) : null; @@ -586,7 +589,7 @@ namespace Umbraco.Cms.Core.Models.Mapping // the old groups - they are just gone and will be cleared by the repository // handle non-grouped (ie generic) properties - PropertyGroupBasic genericPropertiesGroup = + PropertyGroupBasic? genericPropertiesGroup = source.Groups.FirstOrDefault(x => x.IsGenericProperties); if (genericPropertiesGroup != null) { @@ -630,7 +633,7 @@ namespace Umbraco.Cms.Core.Models.Mapping target.Udi = MapContentTypeUdi(source); target.UpdateDate = source.UpdateDate; - target.AllowedContentTypes = source.AllowedContentTypes.OrderBy(c => c.SortOrder).Select(x => x.Id.Value); + target.AllowedContentTypes = source.AllowedContentTypes?.OrderBy(c => c.SortOrder).Select(x => x.Id.Value); target.CompositeContentTypes = source.ContentTypeComposition.Select(x => x.Alias); target.LockedCompositeContentTypes = MapLockedCompositions(source); } @@ -706,23 +709,27 @@ namespace Umbraco.Cms.Core.Models.Mapping } var aliases = new List(); - IEnumerable ancestorIds = parent.Path.Split(Constants.CharArrays.Comma) + IEnumerable? ancestorIds = parent.Path?.Split(Constants.CharArrays.Comma) .Select(s => int.Parse(s, CultureInfo.InvariantCulture)); // loop through all content types and return ordered aliases of ancestors IContentType[] allContentTypes = _contentTypeService.GetAll().ToArray(); - foreach (var ancestorId in ancestorIds) + if (ancestorIds is not null) { - IContentType ancestor = allContentTypes.FirstOrDefault(x => x.Id == ancestorId); - if (ancestor != null) + foreach (var ancestorId in ancestorIds) { - aliases.Add(ancestor.Alias); + IContentType? ancestor = allContentTypes.FirstOrDefault(x => x.Id == ancestorId); + if (ancestor is not null && ancestor.Alias is not null) + { + aliases.Add(ancestor.Alias); + } } } + return aliases.OrderBy(x => x); } - public static Udi MapContentTypeUdi(IContentTypeComposition source) + public static Udi? MapContentTypeUdi(IContentTypeComposition source) { if (source == null) { @@ -752,7 +759,7 @@ namespace Umbraco.Cms.Core.Models.Mapping IEnumerable destOrigGroups, MapperContext context) where TPropertyType : PropertyTypeBasic { - PropertyGroup destGroup; + PropertyGroup? destGroup; if (sourceGroup.Id > 0) { // update an existing group @@ -778,7 +785,7 @@ namespace Umbraco.Cms.Core.Models.Mapping private static IPropertyType MapSaveProperty(PropertyTypeBasic sourceProperty, IEnumerable destOrigProperties, MapperContext context) { - IPropertyType destProperty; + IPropertyType? destProperty; if (sourceProperty.Id > 0) { // updating an existing property diff --git a/src/Umbraco.Core/Models/Mapping/ContentVariantMapper.cs b/src/Umbraco.Core/Models/Mapping/ContentVariantMapper.cs index d735757508..13133e0e49 100644 --- a/src/Umbraco.Core/Models/Mapping/ContentVariantMapper.cs +++ b/src/Umbraco.Core/Models/Mapping/ContentVariantMapper.cs @@ -19,7 +19,7 @@ namespace Umbraco.Cms.Core.Models.Mapping _localizedTextService = localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService)); } - public IEnumerable Map(IContent source, MapperContext context) where TVariant : ContentVariantDisplay + public IEnumerable? Map(IContent source, MapperContext context) where TVariant : ContentVariantDisplay { var variesByCulture = source.ContentType.VariesByCulture(); var variesBySegment = source.ContentType.VariesBySegment(); @@ -70,7 +70,7 @@ namespace Umbraco.Cms.Core.Models.Mapping - private IList SortVariants(IList variants) where TVariant : ContentVariantDisplay + private IList? SortVariants(IList variants) where TVariant : ContentVariantDisplay { if (variants == null || variants.Count <= 1) { @@ -117,11 +117,11 @@ namespace Umbraco.Cms.Core.Models.Mapping /// /// Returns all segments assigned to the content including the default `null` segment. /// - private IEnumerable GetSegments(IContent content) + private IEnumerable GetSegments(IContent content) { // The default segment (null) is always there, // even when there is no property data at all yet - var segments = new List { null }; + var segments = new List { null }; // Add actual segments based on the property values segments.AddRange(content.Properties.SelectMany(p => p.Values.Select(v => v.Segment))); @@ -130,7 +130,7 @@ namespace Umbraco.Cms.Core.Models.Mapping return segments.Distinct(); } - private TVariant CreateVariantDisplay(MapperContext context, IContent content, ContentEditing.Language language, string segment) where TVariant : ContentVariantDisplay + private TVariant CreateVariantDisplay(MapperContext context, IContent content, ContentEditing.Language? language, string? segment) where TVariant : ContentVariantDisplay { context.SetCulture(language?.IsoCode); context.SetSegment(segment); @@ -145,9 +145,9 @@ namespace Umbraco.Cms.Core.Models.Mapping return variantDisplay; } - private string GetDisplayName(ContentEditing.Language language, string segment) + private string GetDisplayName(ContentEditing.Language? language, string? segment) { - var isCultureVariant = language != null; + var isCultureVariant = language is not null; var isSegmentVariant = !segment.IsNullOrWhiteSpace(); if(!isCultureVariant && !isSegmentVariant) @@ -158,10 +158,10 @@ namespace Umbraco.Cms.Core.Models.Mapping var parts = new List(); if (isSegmentVariant) - parts.Add(segment); + parts.Add(segment!); if (isCultureVariant) - parts.Add(language.Name); + parts.Add(language?.Name!); return string.Join(" — ", parts); diff --git a/src/Umbraco.Core/Models/Mapping/DataTypeMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/DataTypeMapDefinition.cs index b1302e50ad..d362016dbb 100644 --- a/src/Umbraco.Core/Models/Mapping/DataTypeMapDefinition.cs +++ b/src/Umbraco.Core/Models/Mapping/DataTypeMapDefinition.cs @@ -155,7 +155,7 @@ namespace Umbraco.Cms.Core.Models.Mapping return fields; } - private void MapConfigurationFields(IDataType dataType, List fields, IDictionary configuration) + private void MapConfigurationFields(IDataType? dataType, List fields, IDictionary configuration) { if (fields == null) throw new ArgumentNullException(nameof(fields)); if (configuration == null) throw new ArgumentNullException(nameof(configuration)); diff --git a/src/Umbraco.Core/Models/Mapping/DictionaryMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/DictionaryMapDefinition.cs index 4c000f0173..290742eb1a 100644 --- a/src/Umbraco.Core/Models/Mapping/DictionaryMapDefinition.cs +++ b/src/Umbraco.Core/Models/Mapping/DictionaryMapDefinition.cs @@ -66,13 +66,13 @@ namespace Umbraco.Cms.Core.Models.Mapping foreach (var lang in _localizationService.GetAllLanguages()) { var langId = lang.Id; - var translation = source.Translations.FirstOrDefault(x => x.LanguageId == langId); + var translation = source.Translations?.FirstOrDefault(x => x.LanguageId == langId); target.Translations.Add(new DictionaryTranslationDisplay { IsoCode = lang.IsoCode, - DisplayName = lang.CultureInfo.DisplayName, - Translation = (translation != null) ? translation.Value : string.Empty, + DisplayName = lang.CultureInfo?.DisplayName, + Translation = translation?.Value ?? string.Empty, LanguageId = lang.Id }); } @@ -88,12 +88,12 @@ namespace Umbraco.Cms.Core.Models.Mapping foreach (var lang in _localizationService.GetAllLanguages()) { var langId = lang.Id; - var translation = source.Translations.FirstOrDefault(x => x.LanguageId == langId); + var translation = source.Translations?.FirstOrDefault(x => x.LanguageId == langId); target.Translations.Add( new DictionaryOverviewTranslationDisplay { - DisplayName = lang.CultureInfo.DisplayName, + DisplayName = lang.CultureInfo?.DisplayName, HasTranslation = translation != null && string.IsNullOrEmpty(translation.Value) == false }); } diff --git a/src/Umbraco.Core/Models/Mapping/LanguageMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/LanguageMapDefinition.cs index 9c14d4249d..b98956eac7 100644 --- a/src/Umbraco.Core/Models/Mapping/LanguageMapDefinition.cs +++ b/src/Umbraco.Core/Models/Mapping/LanguageMapDefinition.cs @@ -30,7 +30,7 @@ namespace Umbraco.Cms.Core.Models.Mapping { target.Id = source.Id; target.IsoCode = source.IsoCode; - target.Name = source.CultureInfo.DisplayName; + target.Name = source.CultureInfo?.DisplayName; target.IsDefault = source.IsDefault; target.IsMandatory = source.IsMandatory; target.FallbackLanguageId = source.FallbackLanguageId; @@ -49,8 +49,11 @@ namespace Umbraco.Cms.Core.Models.Mapping var defaultLang = temp.SingleOrDefault(x => x.IsDefault); // insert default lang first, then remaining language a-z - list.Add(defaultLang); - list.AddRange(temp.Where(x => x != defaultLang).OrderBy(x => x.Name)); + if (defaultLang is not null) + { + list.Add(defaultLang); + list.AddRange(temp.Where(x => x != defaultLang).OrderBy(x => x.Name)); + } } } } diff --git a/src/Umbraco.Core/Models/Mapping/MapperContextExtensions.cs b/src/Umbraco.Core/Models/Mapping/MapperContextExtensions.cs index e385a693cb..89cdc22106 100644 --- a/src/Umbraco.Core/Models/Mapping/MapperContextExtensions.cs +++ b/src/Umbraco.Core/Models/Mapping/MapperContextExtensions.cs @@ -14,7 +14,7 @@ namespace Umbraco.Extensions /// /// Gets the context culture. /// - public static string GetCulture(this MapperContext context) + public static string? GetCulture(this MapperContext context) { return context.HasItems && context.Items.TryGetValue(CultureKey, out var obj) && obj is string s ? s : null; } @@ -22,7 +22,7 @@ namespace Umbraco.Extensions /// /// Gets the context segment. /// - public static string GetSegment(this MapperContext context) + public static string? GetSegment(this MapperContext context) { return context.HasItems && context.Items.TryGetValue(SegmentKey, out var obj) && obj is string s ? s : null; } @@ -30,23 +30,29 @@ namespace Umbraco.Extensions /// /// Sets a context culture. /// - public static void SetCulture(this MapperContext context, string culture) + public static void SetCulture(this MapperContext context, string? culture) { - context.Items[CultureKey] = culture; + if (culture is not null) + { + context.Items[CultureKey] = culture; + } } /// /// Sets a context segment. /// - public static void SetSegment(this MapperContext context, string segment) + public static void SetSegment(this MapperContext context, string? segment) { - context.Items[SegmentKey] = segment; + if (segment is not null) + { + context.Items[SegmentKey] = segment; + } } /// /// Get included properties. /// - public static string[] GetIncludedProperties(this MapperContext context) + public static string[]? GetIncludedProperties(this MapperContext context) { return context.HasItems && context.Items.TryGetValue(IncludedPropertiesKey, out var obj) && obj is string[] s ? s : null; } diff --git a/src/Umbraco.Core/Models/Mapping/MemberTabsAndPropertiesMapper.cs b/src/Umbraco.Core/Models/Mapping/MemberTabsAndPropertiesMapper.cs index d61e32d88a..83398e9951 100644 --- a/src/Umbraco.Core/Models/Mapping/MemberTabsAndPropertiesMapper.cs +++ b/src/Umbraco.Core/Models/Mapping/MemberTabsAndPropertiesMapper.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Xml.Schema; using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Dictionary; @@ -68,7 +69,7 @@ namespace Umbraco.Cms.Core.Models.Mapping // This is kind of a hack because a developer is supposed to be allowed to set their property editor - would have been much easier // if we just had all of the membership provider fields on the member table :( // TODO: But is there a way to map the IMember.IsLockedOut to the property ? i dunno. - var isLockedOutProperty = resolved.SelectMany(x => x.Properties).FirstOrDefault(x => x.Alias == Constants.Conventions.Member.IsLockedOut); + var isLockedOutProperty = resolved.Where(x => x.Properties is not null).SelectMany(x => x.Properties!).FirstOrDefault(x => x.Alias == Constants.Conventions.Member.IsLockedOut); if (isLockedOutProperty?.Value != null && isLockedOutProperty.Value.ToString() != "1") { isLockedOutProperty.View = "readonlyvalue"; @@ -160,9 +161,9 @@ namespace Umbraco.Cms.Core.Models.Mapping return prop; } - internal IDictionary GetMemberGroupValue(string username) + internal IDictionary GetMemberGroupValue(string? username) { - IEnumerable userRoles = username.IsNullOrWhiteSpace() ? null : _memberService.GetAllRoles(username); + IEnumerable? userRoles = username.IsNullOrWhiteSpace() ? null : _memberService.GetAllRoles(username); // create a dictionary of all roles (except internal roles) + "false" var result = _memberGroupService.GetAll() @@ -187,7 +188,7 @@ namespace Umbraco.Cms.Core.Models.Mapping return result; } - public IEnumerable MapMembershipProperties(IMember member, MapperContext context) + public IEnumerable MapMembershipProperties(IMember member, MapperContext? context) { var properties = new List { @@ -218,7 +219,7 @@ namespace Umbraco.Cms.Core.Models.Mapping { Alias = $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}password", Label = _localizedTextService.Localize(null,"password"), - Value = new Dictionary + Value = new Dictionary { // TODO: why ignoreCase, what are we doing here?! {"newPassword", member.GetAdditionalDataValueIgnoreCase("NewPassword", null)}, diff --git a/src/Umbraco.Core/Models/Mapping/PropertyTypeGroupMapper.cs b/src/Umbraco.Core/Models/Mapping/PropertyTypeGroupMapper.cs index eb4df424ba..d130f17d66 100644 --- a/src/Umbraco.Core/Models/Mapping/PropertyTypeGroupMapper.cs +++ b/src/Umbraco.Core/Models/Mapping/PropertyTypeGroupMapper.cs @@ -32,7 +32,7 @@ namespace Umbraco.Cms.Core.Models.Mapping /// The composition. /// The identifier of the property group. /// The composition content type that defines the specified property group. - private static IContentTypeComposition GetContentTypeForPropertyGroup(IContentTypeComposition contentType, int propertyGroupId) + private static IContentTypeComposition? GetContentTypeForPropertyGroup(IContentTypeComposition contentType, int propertyGroupId) { // test local groups if (contentType.PropertyGroups.Any(x => x.Id == propertyGroupId)) @@ -52,7 +52,7 @@ namespace Umbraco.Cms.Core.Models.Mapping /// The composition. /// The identifier of the property type. /// The composition content type that defines the specified property group. - private static IContentTypeComposition GetContentTypeForPropertyType(IContentTypeComposition contentType, int propertyTypeId) + private static IContentTypeComposition? GetContentTypeForPropertyType(IContentTypeComposition contentType, int propertyTypeId) { // test local property types if (contentType.PropertyTypes.Any(x => x.Id == propertyTypeId)) @@ -165,7 +165,10 @@ namespace Umbraco.Cms.Core.Models.Mapping // lock properties by aliases foreach (var property in groups.SelectMany(x => x.Properties)) { - property.Locked = lockedPropertyAliases.Contains(property.Alias); + if (property.Alias is not null) + { + property.Locked = lockedPropertyAliases.Contains(property.Alias); + } } // now merge tabs based on alias @@ -239,7 +242,7 @@ namespace Umbraco.Cms.Core.Models.Mapping PatternMessage = p.ValidationRegExpMessage, }, Label = p.Name, - View = propertyEditor.GetValueEditor().View, + View = propertyEditor?.GetValueEditor().View, Config = config, //Value = "", GroupId = groupId, @@ -247,7 +250,7 @@ namespace Umbraco.Cms.Core.Models.Mapping DataTypeId = p.DataTypeId, DataTypeKey = p.DataTypeKey, DataTypeName = dataType.Name, - DataTypeIcon = propertyEditor.Icon, + DataTypeIcon = propertyEditor?.Icon, SortOrder = p.SortOrder, ContentTypeId = contentType.Id, ContentTypeName = contentType.Name, diff --git a/src/Umbraco.Core/Models/Mapping/TabsAndPropertiesMapper.cs b/src/Umbraco.Core/Models/Mapping/TabsAndPropertiesMapper.cs index fbab50afe3..a3faac8588 100644 --- a/src/Umbraco.Core/Models/Mapping/TabsAndPropertiesMapper.cs +++ b/src/Umbraco.Core/Models/Mapping/TabsAndPropertiesMapper.cs @@ -13,7 +13,7 @@ namespace Umbraco.Cms.Core.Models.Mapping { protected ICultureDictionary CultureDictionary { get; } protected ILocalizedTextService LocalizedTextService { get; } - protected IEnumerable IgnoreProperties { get; set; } + protected IEnumerable IgnoreProperties { get; set; } protected TabsAndPropertiesMapper(ICultureDictionary cultureDictionary, ILocalizedTextService localizedTextService) : this(cultureDictionary, localizedTextService, new List()) diff --git a/src/Umbraco.Core/Models/Mapping/UserMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/UserMapDefinition.cs index e4d101ff06..9fa332252c 100644 --- a/src/Umbraco.Core/Models/Mapping/UserMapDefinition.cs +++ b/src/Umbraco.Core/Models/Mapping/UserMapDefinition.cs @@ -94,8 +94,14 @@ namespace Umbraco.Cms.Core.Models.Mapping target.Id = id; target.ClearAllowedSections(); - foreach (var section in source.Sections) - target.AddAllowedSection(section); + if (source.Sections is not null) + { + foreach (var section in source.Sections) + { + target.AddAllowedSection(section); + } + } + } // Umbraco.Code.MapAll -CreateDate -UpdateDate -DeleteDate @@ -289,7 +295,7 @@ namespace Umbraco.Cms.Core.Models.Mapping target.CreateDate = source.CreateDate; target.Culture = source.GetUserCulture(_textService, _globalSettings).ToString(); target.Email = source.Email; - target.EmailHash = source.Email.ToLowerInvariant().Trim().GenerateHash(); + target.EmailHash = source.Email?.ToLowerInvariant().Trim().GenerateHash(); target.FailedPasswordAttempts = source.FailedPasswordAttempts; target.Id = source.Id; target.Key = source.Key; @@ -300,8 +306,8 @@ namespace Umbraco.Cms.Core.Models.Mapping target.Navigation = CreateUserEditorNavigation(); target.ParentId = -1; target.Path = "-1," + source.Id; - target.StartContentIds = GetStartNodes(source.StartContentIds.ToArray(), UmbracoObjectTypes.Document, "content","contentRoot", context); - target.StartMediaIds = GetStartNodes(source.StartMediaIds.ToArray(), UmbracoObjectTypes.Media, "media","mediaRoot", context); + target.StartContentIds = GetStartNodes(source.StartContentIds?.ToArray(), UmbracoObjectTypes.Document, "content","contentRoot", context); + target.StartMediaIds = GetStartNodes(source.StartMediaIds?.ToArray(), UmbracoObjectTypes.Media, "media","mediaRoot", context); target.UpdateDate = source.UpdateDate; target.UserGroups = context.MapEnumerable(source.Groups); target.Username = source.Username; @@ -317,7 +323,7 @@ namespace Umbraco.Cms.Core.Models.Mapping target.Avatars = source.GetUserAvatarUrls(_appCaches.RuntimeCache, _mediaFileManager, _imageUrlGenerator); target.Culture = source.GetUserCulture(_textService, _globalSettings).ToString(); target.Email = source.Email; - target.EmailHash = source.Email.ToLowerInvariant().Trim().GenerateHash(); + target.EmailHash = source.Email?.ToLowerInvariant().Trim().GenerateHash(); target.Id = source.Id; target.Key = source.Key; target.LastLoginDate = source.LastLoginDate == default ? null : (DateTime?)source.LastLoginDate; @@ -336,7 +342,7 @@ namespace Umbraco.Cms.Core.Models.Mapping target.Avatars = source.GetUserAvatarUrls(_appCaches.RuntimeCache, _mediaFileManager, _imageUrlGenerator); target.Culture = source.GetUserCulture(_textService, _globalSettings).ToString(); target.Email = source.Email; - target.EmailHash = source.Email.ToLowerInvariant().Trim().GenerateHash(); + target.EmailHash = source.Email?.ToLowerInvariant().Trim().GenerateHash(); target.Name = source.Name; target.StartContentIds = source.CalculateContentStartNodeIds(_entityService, _appCaches); target.StartMediaIds = source.CalculateMediaStartNodeIds(_entityService, _appCaches); @@ -391,12 +397,12 @@ namespace Umbraco.Cms.Core.Models.Mapping .ToDictionary(x => x.Key, x => (IEnumerable)x.ToArray()); } - private static string MapContentTypeIcon(IEntitySlim entity) + private static string? MapContentTypeIcon(IEntitySlim entity) => entity is IContentEntitySlim contentEntity ? contentEntity.ContentTypeIcon : null; - private IEnumerable GetStartNodes(int[] startNodeIds, UmbracoObjectTypes objectType, string localizedArea,string localizedAlias, MapperContext context) + private IEnumerable GetStartNodes(int[]? startNodeIds, UmbracoObjectTypes objectType, string localizedArea,string localizedAlias, MapperContext context) { - if (startNodeIds.Length <= 0) + if (startNodeIds is null || startNodeIds.Length <= 0) return Enumerable.Empty(); var startNodes = new List(); @@ -423,7 +429,7 @@ namespace Umbraco.Cms.Core.Models.Mapping }; } - private static int GetIntId(object id) + private static int GetIntId(object? id) { if (id is string strId && int.TryParse(strId, NumberStyles.Integer, CultureInfo.InvariantCulture, out var asInt)) { diff --git a/src/Umbraco.Core/Models/MediaExtensions.cs b/src/Umbraco.Core/Models/MediaExtensions.cs index 616dbd1d12..236ec9deb7 100644 --- a/src/Umbraco.Core/Models/MediaExtensions.cs +++ b/src/Umbraco.Core/Models/MediaExtensions.cs @@ -10,7 +10,7 @@ namespace Umbraco.Extensions /// /// Gets the URL of a media item. /// - public static string GetUrl(this IMedia media, string propertyAlias, MediaUrlGeneratorCollection mediaUrlGenerators) + public static string? GetUrl(this IMedia media, string propertyAlias, MediaUrlGeneratorCollection mediaUrlGenerators) { if (media.TryGetMediaPath(propertyAlias, mediaUrlGenerators, out var mediaPath)) { @@ -23,7 +23,7 @@ namespace Umbraco.Extensions /// /// Gets the URLs of a media item. /// - public static string[] GetUrls(this IMedia media, ContentSettings contentSettings, MediaUrlGeneratorCollection mediaUrlGenerators) + public static string?[] GetUrls(this IMedia media, ContentSettings contentSettings, MediaUrlGeneratorCollection mediaUrlGenerators) => contentSettings.Imaging.AutoFillImageProperties .Select(field => media.GetUrl(field.Alias, mediaUrlGenerators)) .Where(link => string.IsNullOrWhiteSpace(link) == false) diff --git a/src/Umbraco.Core/Models/MediaType.cs b/src/Umbraco.Core/Models/MediaType.cs index dbdf1eeb15..a529dc3189 100644 --- a/src/Umbraco.Core/Models/MediaType.cs +++ b/src/Umbraco.Core/Models/MediaType.cs @@ -27,7 +27,7 @@ namespace Umbraco.Cms.Core.Models /// /// Use this to ensure inheritance from parent. /// - public MediaType(IShortStringHelper shortStringHelper,IMediaType parent) : this(shortStringHelper, parent, null) + public MediaType(IShortStringHelper shortStringHelper,IMediaType parent) : this(shortStringHelper, parent, string.Empty) { } diff --git a/src/Umbraco.Core/Models/Member.cs b/src/Umbraco.Core/Models/Member.cs index 146f19bf36..05213f68b5 100644 --- a/src/Umbraco.Core/Models/Member.cs +++ b/src/Umbraco.Core/Models/Member.cs @@ -14,13 +14,13 @@ namespace Umbraco.Cms.Core.Models [DataContract(IsReference = true)] public class Member : ContentBase, IMember { - private IDictionary _additionalData; - private string _username; - private string _email; - private string _rawPasswordValue; - private string _passwordConfig; + private IDictionary? _additionalData; + private string? _username; + private string? _email; + private string? _rawPasswordValue; + private string? _passwordConfig; private DateTime? _emailConfirmedDate; - private string _securityStamp; + private string? _securityStamp; /// /// Initializes a new instance of the class. @@ -187,7 +187,7 @@ namespace Umbraco.Cms.Core.Models /// Gets or sets the Username /// [DataMember] - public string Username + public string? Username { get => _username; set => SetPropertyValueAndDetectChanges(value, ref _username, nameof(Username)); @@ -197,7 +197,7 @@ namespace Umbraco.Cms.Core.Models /// Gets or sets the Email /// [DataMember] - public string Email + public string? Email { get => _email; set => SetPropertyValueAndDetectChanges(value, ref _email, nameof(Email)); @@ -214,7 +214,7 @@ namespace Umbraco.Cms.Core.Models /// Gets or sets the raw password value /// [IgnoreDataMember] - public string RawPasswordValue + public string? RawPasswordValue { get => _rawPasswordValue; set @@ -233,7 +233,7 @@ namespace Umbraco.Cms.Core.Models } [IgnoreDataMember] - public string PasswordConfiguration + public string? PasswordConfiguration { get => _passwordConfig; set => SetPropertyValueAndDetectChanges(value, ref _passwordConfig, nameof(PasswordConfiguration)); @@ -243,7 +243,7 @@ namespace Umbraco.Cms.Core.Models /// Gets or sets the Groups that Member is part of /// [DataMember] - public IEnumerable Groups { get; set; } + public IEnumerable? Groups { get; set; } // TODO: When get/setting all of these properties we MUST: // * Check if we are using the umbraco membership provider, if so then we need to use the configured fields - not the explicit fields below @@ -257,7 +257,7 @@ namespace Umbraco.Cms.Core.Models /// Part of the standard properties collection. /// [DataMember] - public string Comments + public string? Comments { get { @@ -267,7 +267,7 @@ namespace Umbraco.Cms.Core.Models return Properties[Constants.Conventions.Member.Comments].GetValue() == null ? string.Empty - : Properties[Constants.Conventions.Member.Comments].GetValue().ToString(); + : Properties[Constants.Conventions.Member.Comments].GetValue()?.ToString(); } set { @@ -300,7 +300,7 @@ namespace Umbraco.Cms.Core.Models if (Properties[Constants.Conventions.Member.IsApproved].GetValue() == null) return true; var tryConvert = Properties[Constants.Conventions.Member.IsApproved].GetValue().TryConvertTo(); - if (tryConvert.Success) + if (tryConvert.Success ?? false) { return tryConvert.Result; } @@ -336,7 +336,7 @@ namespace Umbraco.Cms.Core.Models if (Properties[Constants.Conventions.Member.IsLockedOut].GetValue() == null) return false; var tryConvert = Properties[Constants.Conventions.Member.IsLockedOut].GetValue().TryConvertTo(); - if (tryConvert.Success) + if (tryConvert.Success ?? false) { return tryConvert.Result; } @@ -372,7 +372,7 @@ namespace Umbraco.Cms.Core.Models if (Properties[Constants.Conventions.Member.LastLoginDate].GetValue() == null) return default(DateTime); var tryConvert = Properties[Constants.Conventions.Member.LastLoginDate].GetValue().TryConvertTo(); - if (tryConvert.Success) + if (tryConvert.Success ?? false) { return tryConvert.Result; } @@ -408,7 +408,7 @@ namespace Umbraco.Cms.Core.Models if (Properties[Constants.Conventions.Member.LastPasswordChangeDate].GetValue() == null) return default(DateTime); var tryConvert = Properties[Constants.Conventions.Member.LastPasswordChangeDate].GetValue().TryConvertTo(); - if (tryConvert.Success) + if (tryConvert.Success ?? false) { return tryConvert.Result; } @@ -444,7 +444,7 @@ namespace Umbraco.Cms.Core.Models if (Properties[Constants.Conventions.Member.LastLockoutDate].GetValue() == null) return default(DateTime); var tryConvert = Properties[Constants.Conventions.Member.LastLockoutDate].GetValue().TryConvertTo(); - if (tryConvert.Success) + if (tryConvert.Success ?? false) { return tryConvert.Result; } @@ -481,7 +481,7 @@ namespace Umbraco.Cms.Core.Models if (Properties[Constants.Conventions.Member.FailedPasswordAttempts].GetValue() == null) return default(int); var tryConvert = Properties[Constants.Conventions.Member.FailedPasswordAttempts].GetValue().TryConvertTo(); - if (tryConvert.Success) + if (tryConvert.Success ?? false) { return tryConvert.Result; } @@ -509,7 +509,7 @@ namespace Umbraco.Cms.Core.Models /// The security stamp used by ASP.Net identity /// [IgnoreDataMember] - public string SecurityStamp + public string? SecurityStamp { get => _securityStamp; set => SetPropertyValueAndDetectChanges(value, ref _securityStamp, nameof(SecurityStamp)); @@ -524,7 +524,7 @@ namespace Umbraco.Cms.Core.Models /// [IgnoreDataMember] [EditorBrowsable(EditorBrowsableState.Never)] - public string LongStringPropertyValue { get; set; } + public string? LongStringPropertyValue { get; set; } /// /// Internal/Experimental - only used for mapping queries. /// @@ -533,7 +533,7 @@ namespace Umbraco.Cms.Core.Models /// [IgnoreDataMember] [EditorBrowsable(EditorBrowsableState.Never)] - public string ShortStringPropertyValue { get; set; } + public string? ShortStringPropertyValue { get; set; } /// /// Internal/Experimental - only used for mapping queries. /// @@ -569,7 +569,7 @@ namespace Umbraco.Cms.Core.Models /// [IgnoreDataMember] [EditorBrowsable(EditorBrowsableState.Never)] - public string PropertyTypeAlias { get; set; } + public string? PropertyTypeAlias { get; set; } private Attempt WarnIfPropertyTypeNotFoundOnGet(string propertyAlias, string propertyName, T defaultVal) { @@ -623,7 +623,7 @@ namespace Umbraco.Cms.Core.Models /// [DataMember] [DoNotClone] - public IDictionary AdditionalData => _additionalData ?? (_additionalData = new Dictionary()); + public IDictionary? AdditionalData => _additionalData ?? (_additionalData = new Dictionary()); /// [IgnoreDataMember] diff --git a/src/Umbraco.Core/Models/MemberGroup.cs b/src/Umbraco.Core/Models/MemberGroup.cs index 3e712bbb61..7a35b78875 100644 --- a/src/Umbraco.Core/Models/MemberGroup.cs +++ b/src/Umbraco.Core/Models/MemberGroup.cs @@ -12,21 +12,21 @@ namespace Umbraco.Cms.Core.Models [DataContract(IsReference = true)] public class MemberGroup : EntityBase, IMemberGroup { - private IDictionary _additionalData; - private string _name; + private IDictionary? _additionalData; + private string? _name; private int _creatorId; /// [DataMember] [DoNotClone] - public IDictionary AdditionalData => _additionalData ?? (_additionalData = new Dictionary()); + public IDictionary AdditionalData => _additionalData ?? (_additionalData = new Dictionary()); /// [IgnoreDataMember] public bool HasAdditionalData => _additionalData != null; [DataMember] - public string Name + public string? Name { get => _name; set diff --git a/src/Umbraco.Core/Models/MemberType.cs b/src/Umbraco.Core/Models/MemberType.cs index b55c598cac..cb74bd7e57 100644 --- a/src/Umbraco.Core/Models/MemberType.cs +++ b/src/Umbraco.Core/Models/MemberType.cs @@ -17,7 +17,7 @@ namespace Umbraco.Cms.Core.Models public const bool SupportsPublishingConst = false; //Dictionary is divided into string: PropertyTypeAlias, Tuple: MemberCanEdit, VisibleOnProfile, PropertyTypeId - private string _alias; + private string _alias = string.Empty; public MemberType(IShortStringHelper shortStringHelper, int parentId) : base(shortStringHelper, parentId) { @@ -25,7 +25,7 @@ namespace Umbraco.Cms.Core.Models _memberTypePropertyTypes = new Dictionary(); } - public MemberType(IShortStringHelper shortStringHelper, IContentTypeComposition parent) : this(shortStringHelper, parent, null) + public MemberType(IShortStringHelper shortStringHelper, IContentTypeComposition parent) : this(shortStringHelper, parent, string.Empty) { } @@ -74,7 +74,7 @@ namespace Umbraco.Cms.Core.Models ? value : (value == null ? string.Empty : value.ToSafeAlias(_shortStringHelper)); - SetPropertyValueAndDetectChanges(newVal, ref _alias, nameof(Alias)); + SetPropertyValueAndDetectChanges(newVal, ref _alias!, nameof(Alias)); } } diff --git a/src/Umbraco.Core/Models/Membership/EntityPermission.cs b/src/Umbraco.Core/Models/Membership/EntityPermission.cs index 4fc975eb50..a86c844622 100644 --- a/src/Umbraco.Core/Models/Membership/EntityPermission.cs +++ b/src/Umbraco.Core/Models/Membership/EntityPermission.cs @@ -39,14 +39,14 @@ namespace Umbraco.Cms.Core.Models.Membership /// public bool IsDefaultPermissions { get; private set; } - public bool Equals(EntityPermission other) + public bool Equals(EntityPermission? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return EntityId == other.EntityId && UserGroupId == other.UserGroupId; } - 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/Models/Membership/EntityPermissionCollection.cs b/src/Umbraco.Core/Models/Membership/EntityPermissionCollection.cs index f1fb0c2297..ac03ef75d8 100644 --- a/src/Umbraco.Core/Models/Membership/EntityPermissionCollection.cs +++ b/src/Umbraco.Core/Models/Membership/EntityPermissionCollection.cs @@ -28,7 +28,7 @@ namespace Umbraco.Cms.Core.Models.Membership if (_aggregateNodePermissions == null) _aggregateNodePermissions = new Dictionary(); - string[] entityPermissions; + string[]? entityPermissions; if (_aggregateNodePermissions.TryGetValue(entityId, out entityPermissions) == false) { entityPermissions = this.Where(x => x.EntityId == entityId).SelectMany(x => x.AssignedPermissions).Distinct().ToArray(); @@ -37,7 +37,7 @@ namespace Umbraco.Cms.Core.Models.Membership return entityPermissions; } - private Dictionary _aggregateNodePermissions; + private Dictionary? _aggregateNodePermissions; /// /// Returns the aggregate permissions in the permission set for all nodes @@ -52,6 +52,6 @@ namespace Umbraco.Cms.Core.Models.Membership this.SelectMany(x => x.AssignedPermissions).Distinct().ToArray()); } - private string[] _aggregatePermissions; + private string[]? _aggregatePermissions; } } diff --git a/src/Umbraco.Core/Models/Membership/IMembershipUser.cs b/src/Umbraco.Core/Models/Membership/IMembershipUser.cs index 29a6bf4cdb..29f0d320a5 100644 --- a/src/Umbraco.Core/Models/Membership/IMembershipUser.cs +++ b/src/Umbraco.Core/Models/Membership/IMembershipUser.cs @@ -8,21 +8,21 @@ namespace Umbraco.Cms.Core.Models.Membership /// public interface IMembershipUser : IEntity { - string Username { get; set; } - string Email { get; set; } + string? Username { get; set; } + string? Email { get; set; } DateTime? EmailConfirmedDate { get; set; } /// /// Gets or sets the raw password value /// - string RawPasswordValue { get; set; } + string? RawPasswordValue { get; set; } /// /// The user's specific password config (i.e. algorithm type, etc...) /// - string PasswordConfiguration { get; set; } + string? PasswordConfiguration { get; set; } - string Comments { get; set; } + string? Comments { get; set; } bool IsApproved { get; set; } bool IsLockedOut { get; set; } DateTime LastLoginDate { get; set; } @@ -42,7 +42,7 @@ namespace Umbraco.Cms.Core.Models.Membership /// /// Gets or sets the security stamp used by ASP.NET Identity /// - string SecurityStamp { get; set; } + string? SecurityStamp { get; set; } //object ProfileId { get; set; } //IEnumerable Groups { get; set; } diff --git a/src/Umbraco.Core/Models/Membership/IProfile.cs b/src/Umbraco.Core/Models/Membership/IProfile.cs index 773b7f5607..395ebe0de8 100644 --- a/src/Umbraco.Core/Models/Membership/IProfile.cs +++ b/src/Umbraco.Core/Models/Membership/IProfile.cs @@ -6,6 +6,6 @@ public interface IProfile { int Id { get; } - string Name { get; } + string? Name { get; } } } diff --git a/src/Umbraco.Core/Models/Membership/IReadOnlyUserGroup.cs b/src/Umbraco.Core/Models/Membership/IReadOnlyUserGroup.cs index f75d42d790..be84b4bca6 100644 --- a/src/Umbraco.Core/Models/Membership/IReadOnlyUserGroup.cs +++ b/src/Umbraco.Core/Models/Membership/IReadOnlyUserGroup.cs @@ -7,8 +7,8 @@ namespace Umbraco.Cms.Core.Models.Membership /// public interface IReadOnlyUserGroup { - string Name { get; } - string Icon { get; } + string? Name { get; } + string? Icon { get; } int Id { get; } int? StartContentId { get; } int? StartMediaId { get; } @@ -24,7 +24,7 @@ namespace Umbraco.Cms.Core.Models.Membership /// /// By default each permission is simply a single char but we've made this an enumerable{string} to support a more flexible permissions structure in the future. /// - IEnumerable Permissions { get; set; } + IEnumerable? Permissions { get; set; } IEnumerable AllowedSections { get; } } diff --git a/src/Umbraco.Core/Models/Membership/IUser.cs b/src/Umbraco.Core/Models/Membership/IUser.cs index 15a83d2758..c7c68dabda 100644 --- a/src/Umbraco.Core/Models/Membership/IUser.cs +++ b/src/Umbraco.Core/Models/Membership/IUser.cs @@ -13,11 +13,11 @@ namespace Umbraco.Cms.Core.Models.Membership { UserState UserState { get; } - string Name { get; set; } + string? Name { get; set; } int SessionTimeout { get; set; } - int[] StartContentIds { get; set; } - int[] StartMediaIds { get; set; } - string Language { get; set; } + int[]? StartContentIds { get; set; } + int[]? StartMediaIds { get; set; } + string? Language { get; set; } DateTime? InvitedDate { get; set; } @@ -40,11 +40,11 @@ namespace Umbraco.Cms.Core.Models.Membership /// /// Will hold the media file system relative path of the users custom avatar if they uploaded one /// - string Avatar { get; set; } + string? Avatar { get; set; } /// /// A Json blob stored for recording tour data for a user /// - string TourData { get; set; } + string? TourData { get; set; } } } diff --git a/src/Umbraco.Core/Models/Membership/IUserGroup.cs b/src/Umbraco.Core/Models/Membership/IUserGroup.cs index 7278ef5ecc..96ae3c6dfb 100644 --- a/src/Umbraco.Core/Models/Membership/IUserGroup.cs +++ b/src/Umbraco.Core/Models/Membership/IUserGroup.cs @@ -13,12 +13,12 @@ namespace Umbraco.Cms.Core.Models.Membership /// /// The icon /// - string Icon { get; set; } + string? Icon { get; set; } /// /// The name /// - string Name { get; set; } + string? Name { get; set; } /// /// The set of default permissions @@ -26,7 +26,7 @@ namespace Umbraco.Cms.Core.Models.Membership /// /// By default each permission is simply a single char but we've made this an enumerable{string} to support a more flexible permissions structure in the future. /// - IEnumerable Permissions { get; set; } + IEnumerable? Permissions { get; set; } IEnumerable AllowedSections { get; } diff --git a/src/Umbraco.Core/Models/Membership/ReadOnlyUserGroup.cs b/src/Umbraco.Core/Models/Membership/ReadOnlyUserGroup.cs index 1d8457e20f..9767ee19b2 100644 --- a/src/Umbraco.Core/Models/Membership/ReadOnlyUserGroup.cs +++ b/src/Umbraco.Core/Models/Membership/ReadOnlyUserGroup.cs @@ -6,15 +6,15 @@ namespace Umbraco.Cms.Core.Models.Membership { public class ReadOnlyUserGroup : IReadOnlyUserGroup, IEquatable { - public ReadOnlyUserGroup(int id, string name, string icon, int? startContentId, int? startMediaId, string @alias, - IEnumerable allowedSections, IEnumerable permissions) + public ReadOnlyUserGroup(int id, string? name, string? icon, int? startContentId, int? startMediaId, string @alias, + IEnumerable allowedSections, IEnumerable? permissions) { Name = name; Icon = icon; Id = id; Alias = alias; AllowedSections = allowedSections.ToArray(); - Permissions = permissions.ToArray(); + Permissions = permissions?.ToArray(); //Zero is invalid and will be treated as Null StartContentId = startContentId == 0 ? null : startContentId; @@ -22,8 +22,8 @@ namespace Umbraco.Cms.Core.Models.Membership } public int Id { get; private set; } - public string Name { get; private set; } - public string Icon { get; private set; } + public string? Name { get; private set; } + public string? Icon { get; private set; } public int? StartContentId { get; private set; } public int? StartMediaId { get; private set; } public string Alias { get; private set; } @@ -34,17 +34,17 @@ namespace Umbraco.Cms.Core.Models.Membership /// /// By default each permission is simply a single char but we've made this an enumerable{string} to support a more flexible permissions structure in the future. /// - public IEnumerable Permissions { get; set; } + public IEnumerable? Permissions { get; set; } public IEnumerable AllowedSections { get; private set; } - public bool Equals(ReadOnlyUserGroup other) + public bool Equals(ReadOnlyUserGroup? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return string.Equals(Alias, other.Alias); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; @@ -54,7 +54,7 @@ namespace Umbraco.Cms.Core.Models.Membership public override int GetHashCode() { - return Alias.GetHashCode(); + return Alias?.GetHashCode() ?? base.GetHashCode(); } public static bool operator ==(ReadOnlyUserGroup left, ReadOnlyUserGroup right) diff --git a/src/Umbraco.Core/Models/Membership/User.cs b/src/Umbraco.Core/Models/Membership/User.cs index 5525532f9d..f8b1da4251 100644 --- a/src/Umbraco.Core/Models/Membership/User.cs +++ b/src/Umbraco.Core/Models/Membership/User.cs @@ -96,26 +96,26 @@ namespace Umbraco.Cms.Core.Models.Membership _startMediaIds = startMediaIds; } - private string _name; - private string _securityStamp; - private string _avatar; - private string _tourData; + private string? _name; + private string? _securityStamp; + private string? _avatar; + private string? _tourData; private int _sessionTimeout; - private int[] _startContentIds; - private int[] _startMediaIds; + private int[]? _startContentIds; + private int[]? _startMediaIds; private int _failedLoginAttempts; - private string _username; + private string? _username; private DateTime? _emailConfirmedDate; private DateTime? _invitedDate; - private string _email; - private string _rawPasswordValue; - private string _passwordConfig; - private IEnumerable _allowedSections; + private string? _email; + private string? _rawPasswordValue; + private string? _passwordConfig; + private IEnumerable? _allowedSections; private HashSet _userGroups; private bool _isApproved; private bool _isLockedOut; - private string _language; + private string? _language; private DateTime _lastPasswordChangedDate; private DateTime _lastLoginDate; private DateTime _lastLockoutDate; @@ -142,28 +142,28 @@ namespace Umbraco.Cms.Core.Models.Membership } [DataMember] - public string Username + public string? Username { get => _username; set => SetPropertyValueAndDetectChanges(value, ref _username, nameof(Username)); } [DataMember] - public string Email + public string? Email { get => _email; set => SetPropertyValueAndDetectChanges(value, ref _email, nameof(Email)); } [IgnoreDataMember] - public string RawPasswordValue + public string? RawPasswordValue { get => _rawPasswordValue; set => SetPropertyValueAndDetectChanges(value, ref _rawPasswordValue, nameof(RawPasswordValue)); } [IgnoreDataMember] - public string PasswordConfiguration + public string? PasswordConfiguration { get => _passwordConfig; set => SetPropertyValueAndDetectChanges(value, ref _passwordConfig, nameof(PasswordConfiguration)); @@ -212,7 +212,7 @@ namespace Umbraco.Cms.Core.Models.Membership } [IgnoreDataMember] - public string Comments { get; set; } + public string? Comments { get; set; } public UserState UserState { @@ -235,7 +235,7 @@ namespace Umbraco.Cms.Core.Models.Membership } [DataMember] - public string Name + public string? Name { get => _name; set => SetPropertyValueAndDetectChanges(value, ref _name, nameof(Name)); @@ -252,14 +252,14 @@ namespace Umbraco.Cms.Core.Models.Membership /// The security stamp used by ASP.Net identity /// [IgnoreDataMember] - public string SecurityStamp + public string? SecurityStamp { get => _securityStamp; set => SetPropertyValueAndDetectChanges(value, ref _securityStamp, nameof(SecurityStamp)); } [DataMember] - public string Avatar + public string? Avatar { get => _avatar; set => SetPropertyValueAndDetectChanges(value, ref _avatar, nameof(Avatar)); @@ -269,7 +269,7 @@ namespace Umbraco.Cms.Core.Models.Membership /// A Json blob stored for recording tour data for a user /// [DataMember] - public string TourData + public string? TourData { get => _tourData; set => SetPropertyValueAndDetectChanges(value, ref _tourData, nameof(TourData)); @@ -296,7 +296,7 @@ namespace Umbraco.Cms.Core.Models.Membership /// [DataMember] [DoNotClone] - public int[] StartContentIds + public int[]? StartContentIds { get => _startContentIds; set => SetPropertyValueAndDetectChanges(value, ref _startContentIds, nameof(StartContentIds), IntegerEnumerableComparer); @@ -310,14 +310,14 @@ namespace Umbraco.Cms.Core.Models.Membership /// [DataMember] [DoNotClone] - public int[] StartMediaIds + public int[]? StartMediaIds { get => _startMediaIds; set => SetPropertyValueAndDetectChanges(value, ref _startMediaIds, nameof(StartMediaIds), IntegerEnumerableComparer); } [DataMember] - public string Language + public string? Language { get => _language; set => SetPropertyValueAndDetectChanges(value, ref _language, nameof(Language)); @@ -371,8 +371,8 @@ namespace Umbraco.Cms.Core.Models.Membership var clonedEntity = (User)clone; //manually clone the start node props - clonedEntity._startContentIds = _startContentIds.ToArray(); - clonedEntity._startMediaIds = _startMediaIds.ToArray(); + clonedEntity._startContentIds = _startContentIds?.ToArray(); + clonedEntity._startMediaIds = _startMediaIds?.ToArray(); //need to create new collections otherwise they'll get copied by ref clonedEntity._userGroups = new HashSet(_userGroups); clonedEntity._allowedSections = _allowedSections != null ? new List(_allowedSections) : null; @@ -393,14 +393,14 @@ namespace Umbraco.Cms.Core.Models.Membership public int Id => _user.Id; - public string Name => _user.Name; + public string? Name => _user.Name; private bool Equals(WrappedUserProfile other) { return _user.Equals(other._user); } - 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/Models/Membership/UserGroup.cs b/src/Umbraco.Core/Models/Membership/UserGroup.cs index fd173caa73..aff58b670a 100644 --- a/src/Umbraco.Core/Models/Membership/UserGroup.cs +++ b/src/Umbraco.Core/Models/Membership/UserGroup.cs @@ -18,9 +18,9 @@ namespace Umbraco.Cms.Core.Models.Membership private int? _startContentId; private int? _startMediaId; private string _alias; - private string _icon; - private string _name; - private IEnumerable _permissions; + private string? _icon; + private string? _name; + private IEnumerable? _permissions; private List _sectionCollection; //Custom comparer for enumerable @@ -34,6 +34,7 @@ namespace Umbraco.Cms.Core.Models.Membership /// public UserGroup(IShortStringHelper shortStringHelper) { + _alias = string.Empty; _shortStringHelper = shortStringHelper; _sectionCollection = new List(); } @@ -71,7 +72,7 @@ namespace Umbraco.Cms.Core.Models.Membership } [DataMember] - public string Icon + public string? Icon { get => _icon; set => SetPropertyValueAndDetectChanges(value, ref _icon, nameof(Icon)); @@ -81,11 +82,11 @@ namespace Umbraco.Cms.Core.Models.Membership public string Alias { get => _alias; - set => SetPropertyValueAndDetectChanges(value.ToCleanString(_shortStringHelper, CleanStringType.Alias | CleanStringType.UmbracoCase), ref _alias, nameof(Alias)); + set => SetPropertyValueAndDetectChanges(value.ToCleanString(_shortStringHelper, CleanStringType.Alias | CleanStringType.UmbracoCase), ref _alias!, nameof(Alias)); } [DataMember] - public string Name + public string? Name { get => _name; set => SetPropertyValueAndDetectChanges(value, ref _name, nameof(Name)); @@ -98,7 +99,7 @@ namespace Umbraco.Cms.Core.Models.Membership /// By default each permission is simply a single char but we've made this an enumerable{string} to support a more flexible permissions structure in the future. /// [DataMember] - public IEnumerable Permissions + public IEnumerable? Permissions { get => _permissions; set => SetPropertyValueAndDetectChanges(value, ref _permissions, nameof(Permissions), StringEnumerableComparer); diff --git a/src/Umbraco.Core/Models/Membership/UserGroupExtensions.cs b/src/Umbraco.Core/Models/Membership/UserGroupExtensions.cs index 1dabc044f3..84b165b81e 100644 --- a/src/Umbraco.Core/Models/Membership/UserGroupExtensions.cs +++ b/src/Umbraco.Core/Models/Membership/UserGroupExtensions.cs @@ -21,7 +21,7 @@ namespace Umbraco.Extensions public static bool IsSystemUserGroup(this IReadOnlyUserGroup group) => IsSystemUserGroup(group.Alias); - private static bool IsSystemUserGroup(this string groupAlias) + private static bool IsSystemUserGroup(this string? groupAlias) { return groupAlias == Constants.Security.AdminGroupAlias || groupAlias == Constants.Security.SensitiveDataGroupAlias diff --git a/src/Umbraco.Core/Models/Membership/UserProfile.cs b/src/Umbraco.Core/Models/Membership/UserProfile.cs index edda94aa8f..752dab2498 100644 --- a/src/Umbraco.Core/Models/Membership/UserProfile.cs +++ b/src/Umbraco.Core/Models/Membership/UserProfile.cs @@ -13,14 +13,14 @@ namespace Umbraco.Cms.Core.Models.Membership public int Id { get; private set; } public string Name { get; private set; } - public bool Equals(UserProfile other) + public bool Equals(UserProfile? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return 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/Models/MigrationEntry.cs b/src/Umbraco.Core/Models/MigrationEntry.cs index 2fc5ea5340..f62dc7eb60 100644 --- a/src/Umbraco.Core/Models/MigrationEntry.cs +++ b/src/Umbraco.Core/Models/MigrationEntry.cs @@ -18,16 +18,16 @@ namespace Umbraco.Cms.Core.Models _version = version; } - private string _migrationName; - private SemVersion _version; + private string? _migrationName; + private SemVersion? _version; - public string MigrationName + public string? MigrationName { get => _migrationName; set => SetPropertyValueAndDetectChanges(value, ref _migrationName, nameof(MigrationName)); } - public SemVersion Version + public SemVersion? Version { get => _version; set => SetPropertyValueAndDetectChanges(value, ref _version, nameof(Version)); diff --git a/src/Umbraco.Core/Models/ObjectTypes.cs b/src/Umbraco.Core/Models/ObjectTypes.cs index 38211f23fa..8e4eef3246 100644 --- a/src/Umbraco.Core/Models/ObjectTypes.cs +++ b/src/Umbraco.Core/Models/ObjectTypes.cs @@ -14,17 +14,17 @@ namespace Umbraco.Cms.Core.Models private static readonly ConcurrentDictionary UmbracoGuids = new ConcurrentDictionary(); private static readonly ConcurrentDictionary UmbracoUdiTypes = new ConcurrentDictionary(); private static readonly ConcurrentDictionary UmbracoFriendlyNames = new ConcurrentDictionary(); - private static readonly ConcurrentDictionary UmbracoTypes = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary UmbracoTypes = new ConcurrentDictionary(); private static readonly ConcurrentDictionary GuidUdiTypes = new ConcurrentDictionary(); private static readonly ConcurrentDictionary GuidObjectTypes = new ConcurrentDictionary(); - private static readonly ConcurrentDictionary GuidTypes = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary GuidTypes = new ConcurrentDictionary(); - private static FieldInfo GetEnumField(string name) + private static FieldInfo? GetEnumField(string name) { return typeof (UmbracoObjectTypes).GetField(name, BindingFlags.Public | BindingFlags.Static); } - private static FieldInfo GetEnumField(Guid guid) + private static FieldInfo? GetEnumField(Guid guid) { var fields = typeof (UmbracoObjectTypes).GetFields(BindingFlags.Public | BindingFlags.Static); foreach (var field in fields) @@ -56,7 +56,7 @@ namespace Umbraco.Cms.Core.Models var field = GetEnumField(objectType); if (field == null) return UmbracoObjectTypes.Unknown; - return (UmbracoObjectTypes) field.GetValue(null); + return (UmbracoObjectTypes?)field.GetValue(null) ?? UmbracoObjectTypes.Unknown; }); } @@ -78,7 +78,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets the CLR type corresponding to an object type Guid. /// - public static Type GetClrType(Guid objectType) + public static Type? GetClrType(Guid objectType) { return GuidTypes.GetOrAdd(objectType, t => { @@ -102,7 +102,7 @@ namespace Umbraco.Cms.Core.Models return UmbracoGuids.GetOrAdd(objectType, t => { var field = GetEnumField(t.ToString()); - var attribute = field.GetCustomAttribute(false); + var attribute = field?.GetCustomAttribute(false); return attribute?.ObjectId ?? Guid.Empty; }); @@ -116,7 +116,7 @@ namespace Umbraco.Cms.Core.Models return UmbracoUdiTypes.GetOrAdd(objectType, t => { var field = GetEnumField(t.ToString()); - var attribute = field.GetCustomAttribute(false); + var attribute = field?.GetCustomAttribute(false); return attribute?.UdiType ?? Constants.UdiEntityType.Unknown; }); @@ -125,7 +125,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets the name corresponding to this Umbraco object type. /// - public static string GetName(this UmbracoObjectTypes objectType) + public static string? GetName(this UmbracoObjectTypes objectType) { return Enum.GetName(typeof (UmbracoObjectTypes), objectType); } @@ -138,7 +138,7 @@ namespace Umbraco.Cms.Core.Models return UmbracoFriendlyNames.GetOrAdd(objectType, t => { var field = GetEnumField(t.ToString()); - var attribute = field.GetCustomAttribute(false); + var attribute = field?.GetCustomAttribute(false); return attribute?.ToString() ?? string.Empty; }); @@ -147,12 +147,12 @@ namespace Umbraco.Cms.Core.Models /// /// Gets the CLR type corresponding to this Umbraco object type. /// - public static Type GetClrType(this UmbracoObjectTypes objectType) + public static Type? GetClrType(this UmbracoObjectTypes objectType) { return UmbracoTypes.GetOrAdd(objectType, t => { var field = GetEnumField(t.ToString()); - var attribute = field.GetCustomAttribute(false); + var attribute = field?.GetCustomAttribute(false); return attribute?.ModelType; }); diff --git a/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs b/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs index 6e963bd2da..127347e528 100644 --- a/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs +++ b/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs @@ -10,21 +10,21 @@ namespace Umbraco.Cms.Core.Models.Packaging /// public class CompiledPackage { - public FileInfo PackageFile { get; set; } - public string Name { get; set; } + public FileInfo? PackageFile { get; set; } + public string? Name { get; set; } public InstallWarnings Warnings { get; set; } = new InstallWarnings(); - public IEnumerable Macros { get; set; } // TODO: make strongly typed - public IEnumerable MacroPartialViews { get; set; } // TODO: make strongly typed - public IEnumerable Templates { get; set; } // TODO: make strongly typed - public IEnumerable Stylesheets { get; set; } // TODO: make strongly typed - public IEnumerable Scripts { get; set; } // TODO: make strongly typed - public IEnumerable PartialViews { get; set; } // TODO: make strongly typed - public IEnumerable DataTypes { get; set; } // TODO: make strongly typed - public IEnumerable Languages { get; set; } // TODO: make strongly typed - public IEnumerable DictionaryItems { get; set; } // TODO: make strongly typed - public IEnumerable DocumentTypes { get; set; } // TODO: make strongly typed - public IEnumerable MediaTypes { get; set; } // TODO: make strongly typed - public IEnumerable Documents { get; set; } - public IEnumerable Media { get; set; } + public IEnumerable? Macros { get; set; } // TODO: make strongly typed + public IEnumerable? MacroPartialViews { get; set; } // TODO: make strongly typed + public IEnumerable? Templates { get; set; } // TODO: make strongly typed + public IEnumerable? Stylesheets { get; set; } // TODO: make strongly typed + public IEnumerable? Scripts { get; set; } // TODO: make strongly typed + public IEnumerable? PartialViews { get; set; } // TODO: make strongly typed + public IEnumerable? DataTypes { get; set; } // TODO: make strongly typed + public IEnumerable? Languages { get; set; } // TODO: make strongly typed + public IEnumerable? DictionaryItems { get; set; } // TODO: make strongly typed + public IEnumerable? DocumentTypes { get; set; } // TODO: make strongly typed + public IEnumerable? MediaTypes { get; set; } // TODO: make strongly typed + public IEnumerable? Documents { get; set; } + public IEnumerable? Media { get; set; } } } diff --git a/src/Umbraco.Core/Models/Packaging/CompiledPackageContentBase.cs b/src/Umbraco.Core/Models/Packaging/CompiledPackageContentBase.cs index d1e98376aa..476b4a5dac 100644 --- a/src/Umbraco.Core/Models/Packaging/CompiledPackageContentBase.cs +++ b/src/Umbraco.Core/Models/Packaging/CompiledPackageContentBase.cs @@ -15,11 +15,11 @@ namespace Umbraco.Cms.Core.Models.Packaging ImportMode = xml.AttributeValue("importMode") }; - public string ImportMode { get; set; } //this is never used + public string? ImportMode { get; set; } //this is never used /// /// The serialized version of the content /// - public XElement XmlData { get; set; } + public XElement? XmlData { get; set; } } } diff --git a/src/Umbraco.Core/Models/Packaging/InstallWarnings.cs b/src/Umbraco.Core/Models/Packaging/InstallWarnings.cs index 61e8c5f4c5..2425465989 100644 --- a/src/Umbraco.Core/Models/Packaging/InstallWarnings.cs +++ b/src/Umbraco.Core/Models/Packaging/InstallWarnings.cs @@ -7,8 +7,8 @@ namespace Umbraco.Cms.Core.Models.Packaging public class InstallWarnings { // TODO: Shouldn't we detect other conflicting entities too ? - public IEnumerable ConflictingMacros { get; set; } = Enumerable.Empty(); - public IEnumerable ConflictingTemplates { get; set; } = Enumerable.Empty(); - public IEnumerable ConflictingStylesheets { get; set; } = Enumerable.Empty(); + public IEnumerable? ConflictingMacros { get; set; } = Enumerable.Empty(); + public IEnumerable? ConflictingTemplates { get; set; } = Enumerable.Empty(); + public IEnumerable? ConflictingStylesheets { get; set; } = Enumerable.Empty(); } } diff --git a/src/Umbraco.Core/Models/PagedResultOfT.cs b/src/Umbraco.Core/Models/PagedResultOfT.cs index dc51cfdb1b..125256ec3b 100644 --- a/src/Umbraco.Core/Models/PagedResultOfT.cs +++ b/src/Umbraco.Core/Models/PagedResultOfT.cs @@ -15,6 +15,6 @@ namespace Umbraco.Cms.Core.Models { } [DataMember(Name = "items")] - public IEnumerable Items { get; set; } + public IEnumerable? Items { get; set; } } } diff --git a/src/Umbraco.Core/Models/PartialView.cs b/src/Umbraco.Core/Models/PartialView.cs index fa090305b2..d78a6603bb 100644 --- a/src/Umbraco.Core/Models/PartialView.cs +++ b/src/Umbraco.Core/Models/PartialView.cs @@ -14,7 +14,7 @@ namespace Umbraco.Cms.Core.Models : this(viewType, path, null) { } - public PartialView(PartialViewType viewType, string path, Func getFileContent) + public PartialView(PartialViewType viewType, string path, Func? getFileContent) : base(path, getFileContent) { ViewType = viewType; diff --git a/src/Umbraco.Core/Models/PartialViewMacroModelExtensions.cs b/src/Umbraco.Core/Models/PartialViewMacroModelExtensions.cs index 8ec2206d60..64d26e8939 100644 --- a/src/Umbraco.Core/Models/PartialViewMacroModelExtensions.cs +++ b/src/Umbraco.Core/Models/PartialViewMacroModelExtensions.cs @@ -14,14 +14,14 @@ namespace Umbraco.Extensions /// /// /// Parameter value if available, the default value that was passed otherwise. - public static T GetParameterValue(this PartialViewMacroModel partialViewMacroModel, string parameterAlias, T defaultValue) + public static T? GetParameterValue(this PartialViewMacroModel partialViewMacroModel, string parameterAlias, T defaultValue) { if (partialViewMacroModel.MacroParameters.ContainsKey(parameterAlias) == false || string.IsNullOrEmpty(partialViewMacroModel.MacroParameters[parameterAlias].ToString())) return defaultValue; var attempt = partialViewMacroModel.MacroParameters[parameterAlias].TryConvertTo(typeof(T)); - return attempt.Success ? (T) attempt.Result : defaultValue; + return attempt.Success ?? false ? (T?) attempt.Result : defaultValue; } /// @@ -30,7 +30,7 @@ namespace Umbraco.Extensions /// /// /// Parameter value if available, the default value for the type otherwise. - public static T GetParameterValue(this PartialViewMacroModel partialViewMacroModel, string parameterAlias) + public static T? GetParameterValue(this PartialViewMacroModel partialViewMacroModel, string parameterAlias) { return partialViewMacroModel.GetParameterValue(parameterAlias, default(T)); } diff --git a/src/Umbraco.Core/Models/Property.cs b/src/Umbraco.Core/Models/Property.cs index 6c172030c7..8cf58fa9be 100644 --- a/src/Umbraco.Core/Models/Property.cs +++ b/src/Umbraco.Core/Models/Property.cs @@ -20,16 +20,10 @@ namespace Umbraco.Cms.Core.Models private List _values = new List(); // _pvalue contains the invariant-neutral property value - private IPropertyValue _pvalue; + private IPropertyValue? _pvalue; // _vvalues contains the (indexed) variant property values - private Dictionary _vvalues; - - /// - /// Initializes a new instance of the class. - /// - protected Property() - { } + private Dictionary? _vvalues; /// /// Initializes a new instance of the class. @@ -104,18 +98,18 @@ namespace Umbraco.Cms.Core.Models // TODO: Either we allow change tracking at this class level, or we add some special change tracking collections to the Property // class to deal with change tracking which variants have changed - private string _culture; - private string _segment; + private string? _culture; + private string? _segment; /// /// Gets or sets the culture of the property. /// /// The culture is either null (invariant) or a non-empty string. If the property is /// set with an empty or whitespace value, its value is converted to null. - public string Culture + public string? Culture { get => _culture; - set => _culture = value.IsNullOrWhiteSpace() ? null : value.ToLowerInvariant(); + set => _culture = value.IsNullOrWhiteSpace() ? null : value!.ToLowerInvariant(); } /// @@ -123,7 +117,7 @@ namespace Umbraco.Cms.Core.Models /// /// The segment is either null (neutral) or a non-empty string. If the property is /// set with an empty or whitespace value, its value is converted to null. - public string Segment + public string? Segment { get => _segment; set => _segment = value?.ToLowerInvariant(); @@ -132,12 +126,12 @@ namespace Umbraco.Cms.Core.Models /// /// Gets or sets the edited value of the property. /// - public object EditedValue { get; set; } + public object? EditedValue { get; set; } /// /// Gets or sets the published value of the property. /// - public object PublishedValue { get; set; } + public object? PublishedValue { get; set; } /// /// Clones the property value. @@ -147,12 +141,12 @@ namespace Umbraco.Cms.Core.Models public object DeepClone() => Clone(); - public override bool Equals(object obj) + public override bool Equals(object? obj) { return Equals(obj as PropertyValue); } - public bool Equals(PropertyValue other) + public bool Equals(PropertyValue? other) { return other != null && _culture == other._culture && @@ -164,15 +158,30 @@ namespace Umbraco.Cms.Core.Models public override int GetHashCode() { var hashCode = 1885328050; - hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(_culture); - hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(_segment); - hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(EditedValue); - hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(PublishedValue); + if (_culture is not null) + { + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(_culture); + } + + if (_segment is not null) + { + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(_segment); + } + + if (EditedValue is not null) + { + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(EditedValue); + } + + if (PublishedValue is not null) + { + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(PublishedValue); + } return hashCode; } } - private static readonly DelegateEqualityComparer PropertyValueComparer = new DelegateEqualityComparer( + private static readonly DelegateEqualityComparer PropertyValueComparer = new DelegateEqualityComparer( (o, o1) => { if (o == null && o1 == null) return true; @@ -209,7 +218,7 @@ namespace Umbraco.Cms.Core.Models { // make sure we filter out invalid variations // make sure we leave _vvalues null if possible - _values = value.Where(x => PropertyType.SupportsVariation(x.Culture, x.Segment)).ToList(); + _values = value.Where(x => PropertyType?.SupportsVariation(x.Culture, x.Segment) ?? false).ToList(); _pvalue = _values.FirstOrDefault(x => x.Culture == null && x.Segment == null); _vvalues = _values.Count > (_pvalue == null ? 0 : 1) ? _values.Where(x => x != _pvalue).ToDictionary(x => new CompositeNStringNStringKey(x.Culture, x.Segment), x => x) @@ -241,11 +250,11 @@ namespace Umbraco.Cms.Core.Models /// /// Gets the value. /// - public object GetValue(string culture = null, string? segment = null, bool published = false) + public object? GetValue(string? culture = null, string? segment = null, bool published = false) { // ensure null or whitespace are nulls - culture = culture.NullOrWhiteSpaceAsNull(); - segment = segment.NullOrWhiteSpaceAsNull(); + culture = culture?.NullOrWhiteSpaceAsNull(); + segment = segment?.NullOrWhiteSpaceAsNull(); if (!PropertyType.SupportsVariation(culture, segment)) return null; if (culture == null && segment == null) return GetPropertyValue(_pvalue, published); @@ -255,7 +264,7 @@ namespace Umbraco.Cms.Core.Models : null; } - private object GetPropertyValue(IPropertyValue pvalue, bool published) + private object? GetPropertyValue(IPropertyValue? pvalue, bool published) { if (pvalue == null) return null; @@ -266,10 +275,10 @@ namespace Umbraco.Cms.Core.Models // internal - must be invoked by the content item // does *not* validate the value - content item must validate first - public void PublishValues(string culture = "*", string segment = "*") + public void PublishValues(string? culture = "*", string? segment = "*") { - culture = culture.NullOrWhiteSpaceAsNull(); - segment = segment.NullOrWhiteSpaceAsNull(); + culture = culture?.NullOrWhiteSpaceAsNull(); + segment = segment?.NullOrWhiteSpaceAsNull(); // if invariant or all, and invariant-neutral is supported, publish invariant-neutral if ((culture == null || culture == "*") && (segment == null || segment == "*") && PropertyType.SupportsVariation(null, null)) @@ -282,8 +291,8 @@ namespace Umbraco.Cms.Core.Models // and match the specified culture and segment (or anything when '*'). var pvalues = _vvalues.Where(x => PropertyType.SupportsVariation(x.Value.Culture, x.Value.Segment, true) && // the value variation is ok - (culture == "*" || x.Value.Culture.InvariantEquals(culture)) && // the culture matches - (segment == "*" || x.Value.Segment.InvariantEquals(segment))) // the segment matches + (culture == "*" || (x.Value.Culture?.InvariantEquals(culture) ?? false)) && // the culture matches + (segment == "*" || (x.Value.Segment?.InvariantEquals(segment) ?? false))) // the segment matches .Select(x => x.Value); foreach (var pvalue in pvalues) @@ -291,10 +300,10 @@ namespace Umbraco.Cms.Core.Models } // internal - must be invoked by the content item - public void UnpublishValues(string culture = "*", string segment = "*") + public void UnpublishValues(string? culture = "*", string? segment = "*") { - culture = culture.NullOrWhiteSpaceAsNull(); - segment = segment.NullOrWhiteSpaceAsNull(); + culture = culture?.NullOrWhiteSpaceAsNull(); + segment = segment?.NullOrWhiteSpaceAsNull(); // if invariant or all, and invariant-neutral is supported, publish invariant-neutral if ((culture == null || culture == "*") && (segment == null || segment == "*") && PropertyType.SupportsVariation(null, null)) @@ -307,15 +316,15 @@ namespace Umbraco.Cms.Core.Models // and match the specified culture and segment (or anything when '*'). var pvalues = _vvalues.Where(x => PropertyType.SupportsVariation(x.Value.Culture, x.Value.Segment, true) && // the value variation is ok - (culture == "*" || x.Value.Culture.InvariantEquals(culture)) && // the culture matches - (segment == "*" || x.Value.Segment.InvariantEquals(segment))) // the segment matches + (culture == "*" || (x.Value.Culture?.InvariantEquals(culture) ?? false)) && // the culture matches + (segment == "*" || (x.Value.Segment?.InvariantEquals(segment) ?? false))) // the segment matches .Select(x => x.Value); foreach (var pvalue in pvalues) UnpublishValue(pvalue); } - private void PublishValue(IPropertyValue pvalue) + private void PublishValue(IPropertyValue? pvalue) { if (pvalue == null) return; @@ -326,7 +335,7 @@ namespace Umbraco.Cms.Core.Models DetectChanges(pvalue.EditedValue, origValue, nameof(Values), PropertyValueComparer, false); } - private void UnpublishValue(IPropertyValue pvalue) + private void UnpublishValue(IPropertyValue? pvalue) { if (pvalue == null) return; @@ -340,22 +349,25 @@ namespace Umbraco.Cms.Core.Models /// /// Sets a value. /// - public void SetValue(object value, string? culture = null, string? segment = null) + public void SetValue(object? value, string? culture = null, string? segment = null) { - culture = culture.NullOrWhiteSpaceAsNull(); - segment = segment.NullOrWhiteSpaceAsNull(); + culture = culture?.NullOrWhiteSpaceAsNull(); + segment = segment?.NullOrWhiteSpaceAsNull(); if (!PropertyType.SupportsVariation(culture, segment)) throw new NotSupportedException($"Variation \"{culture??""},{segment??""}\" is not supported by the property type."); var (pvalue, change) = GetPValue(culture, segment, true); - var origValue = pvalue.EditedValue; - var setValue = ConvertAssignedValue(value); + if (pvalue is not null) + { + var origValue = pvalue.EditedValue; + var setValue = ConvertAssignedValue(value); - pvalue.EditedValue = setValue; + pvalue.EditedValue = setValue; - DetectChanges(setValue, origValue, nameof(Values), PropertyValueComparer, change); + DetectChanges(setValue, origValue, nameof(Values), PropertyValueComparer, change); + } } // bypasses all changes detection and is the *only* way to set the published value @@ -363,13 +375,16 @@ namespace Umbraco.Cms.Core.Models { var (pvalue, _) = GetPValue(culture, segment, true); - if (published && PropertyType.SupportsPublishing) - pvalue.PublishedValue = value; - else - pvalue.EditedValue = value; + if (pvalue is not null) + { + if (published && PropertyType.SupportsPublishing) + pvalue.PublishedValue = value; + else + pvalue.EditedValue = value; + } } - private (IPropertyValue, bool) GetPValue(bool create) + private (IPropertyValue?, bool) GetPValue(bool create) { var change = false; if (_pvalue == null) @@ -382,7 +397,7 @@ namespace Umbraco.Cms.Core.Models return (_pvalue, change); } - private (IPropertyValue, bool) GetPValue(string culture, string segment, bool create) + private (IPropertyValue?, bool) GetPValue(string? culture, string? segment, bool create) { if (culture == null && segment == null) return GetPValue(create); @@ -408,7 +423,7 @@ namespace Umbraco.Cms.Core.Models } /// - public object ConvertAssignedValue(object value) => TryConvertAssignedValue(value, true, out var converted) ? converted : null; + public object? ConvertAssignedValue(object? value) => TryConvertAssignedValue(value, true, out var converted) ? converted : null; /// /// Tries to convert a value assigned to a property. @@ -416,7 +431,7 @@ namespace Umbraco.Cms.Core.Models /// /// /// - private bool TryConvertAssignedValue(object value, bool throwOnError, out object converted) + private bool TryConvertAssignedValue(object? value, bool throwOnError, out object? converted) { var isOfExpectedType = IsOfExpectedPropertyType(value); if (isOfExpectedType) @@ -429,7 +444,7 @@ namespace Umbraco.Cms.Core.Models // "garbage-in", accept what we can & convert // throw only if conversion is not possible - var s = value.ToString(); + var s = value?.ToString(); converted = null; switch (ValueStorageType) @@ -445,7 +460,7 @@ namespace Umbraco.Cms.Core.Models if (s.IsNullOrWhiteSpace()) return true; // assume empty means null var convInt = value.TryConvertTo(); - if (convInt) + if (convInt.Success.HasValue && convInt.Success.Value) { converted = convInt.Result; return true; @@ -459,7 +474,7 @@ namespace Umbraco.Cms.Core.Models if (s.IsNullOrWhiteSpace()) return true; // assume empty means null var convDecimal = value.TryConvertTo(); - if (convDecimal) + if (convDecimal.Success.HasValue && convDecimal.Success.Value) { // need to normalize the value (change the scaling factor and remove trailing zeros) // because the underlying database is going to mess with the scaling factor anyways. @@ -475,7 +490,7 @@ namespace Umbraco.Cms.Core.Models if (s.IsNullOrWhiteSpace()) return true; // assume empty means null var convDateTime = value.TryConvertTo(); - if (convDateTime) + if (convDateTime.Success.HasValue && convDateTime.Success.Value) { converted = convDateTime.Result; return true; @@ -490,9 +505,9 @@ namespace Umbraco.Cms.Core.Models } } - private static void ThrowTypeException(object value, Type expected, string alias) + private static void ThrowTypeException(object? value, Type expected, string alias) { - throw new InvalidOperationException($"Cannot assign value \"{value}\" of type \"{value.GetType()}\" to property \"{alias}\" expecting type \"{expected}\"."); + throw new InvalidOperationException($"Cannot assign value \"{value}\" of type \"{value?.GetType()}\" to property \"{alias}\" expecting type \"{expected}\"."); } /// @@ -502,7 +517,7 @@ namespace Umbraco.Cms.Core.Models /// If the value is of the expected type, it can be directly assigned to the property. /// Otherwise, some conversion is required. /// - private bool IsOfExpectedPropertyType(object value) + private bool IsOfExpectedPropertyType(object? value) { // null values are assumed to be ok if (value == null) diff --git a/src/Umbraco.Core/Models/PropertyType.cs b/src/Umbraco.Core/Models/PropertyType.cs index 29e3dd6f33..19abc7732b 100644 --- a/src/Umbraco.Core/Models/PropertyType.cs +++ b/src/Umbraco.Core/Models/PropertyType.cs @@ -52,7 +52,7 @@ namespace Umbraco.Cms.Core.Models /// /// Initializes a new instance of the class. /// - public PropertyType(IShortStringHelper shortStringHelper, IDataType dataType, string propertyTypeAlias) + public PropertyType(IShortStringHelper shortStringHelper, IDataType dataType, string? propertyTypeAlias) : this(shortStringHelper, dataType) { _alias = SanitizeAlias(propertyTypeAlias); @@ -246,19 +246,19 @@ namespace Umbraco.Cms.Core.Models /// /// Sanitizes a property type alias. /// - private string SanitizeAlias(string value) + private string? SanitizeAlias(string? value) { //NOTE: WE are doing this because we don't want to do a ToSafeAlias when the alias is the special case of // being prefixed with Constants.PropertyEditors.InternalGenericPropertiesPrefix // which is used internally - return value.StartsWith(Constants.PropertyEditors.InternalGenericPropertiesPrefix) + return value?.StartsWith(Constants.PropertyEditors.InternalGenericPropertiesPrefix) ?? false ? value - : value.ToCleanString(_shortStringHelper, CleanStringType.Alias | CleanStringType.UmbracoCase); + : value?.ToCleanString(_shortStringHelper, CleanStringType.Alias | CleanStringType.UmbracoCase); } /// - public bool Equals(PropertyType other) + public bool Equals(PropertyType? other) { return other != null && (base.Equals(other) || Alias.InvariantEquals(other.Alias)); } diff --git a/src/Umbraco.Core/Models/PublicAccessEntry.cs b/src/Umbraco.Core/Models/PublicAccessEntry.cs index d5bb3d95c0..00e05442d8 100644 --- a/src/Umbraco.Core/Models/PublicAccessEntry.cs +++ b/src/Umbraco.Core/Models/PublicAccessEntry.cs @@ -51,7 +51,7 @@ namespace Umbraco.Cms.Core.Models rule.AccessEntryId = Key; } - void _ruleCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + void _ruleCollection_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { OnPropertyChanged(nameof(Rules)); @@ -67,13 +67,15 @@ namespace Umbraco.Cms.Core.Models if (e.Action == NotifyCollectionChangedAction.Remove) { - var item = e.OldItems.Cast().First(); + var item = e.OldItems?.Cast().First(); - if (_removedRules.Contains(item.Key) == false) + if (item is not null) { - _removedRules.Add(item.Key); + if (_removedRules.Contains(item.Key) == false) + { + _removedRules.Add(item.Key); + } } - } } diff --git a/src/Umbraco.Core/Models/PublicAccessRule.cs b/src/Umbraco.Core/Models/PublicAccessRule.cs index 0b66c5a289..790d8b6a1b 100644 --- a/src/Umbraco.Core/Models/PublicAccessRule.cs +++ b/src/Umbraco.Core/Models/PublicAccessRule.cs @@ -8,8 +8,8 @@ namespace Umbraco.Cms.Core.Models [DataContract(IsReference = true)] public class PublicAccessRule : EntityBase { - private string _ruleValue; - private string _ruleType; + private string? _ruleValue; + private string? _ruleType; public PublicAccessRule(Guid id, Guid accessEntryId) { @@ -24,13 +24,13 @@ namespace Umbraco.Cms.Core.Models public Guid AccessEntryId { get; set; } - public string RuleValue + public string? RuleValue { get => _ruleValue; set => SetPropertyValueAndDetectChanges(value, ref _ruleValue, nameof(RuleValue)); } - public string RuleType + public string? RuleType { get => _ruleType; set => SetPropertyValueAndDetectChanges(value, ref _ruleType, nameof(RuleType)); diff --git a/src/Umbraco.Core/Models/PublishedContent/HttpContextVariationContextAccessor.cs b/src/Umbraco.Core/Models/PublishedContent/HttpContextVariationContextAccessor.cs index 47b8395897..3fb18fad2d 100644 --- a/src/Umbraco.Core/Models/PublishedContent/HttpContextVariationContextAccessor.cs +++ b/src/Umbraco.Core/Models/PublishedContent/HttpContextVariationContextAccessor.cs @@ -16,9 +16,9 @@ namespace Umbraco.Cms.Core.Models.PublishedContent public HttpContextVariationContextAccessor(IRequestCache requestCache) => _requestCache = requestCache; /// - public VariationContext VariationContext + public VariationContext? VariationContext { - get => (VariationContext) _requestCache.Get(ContextKey); + get => (VariationContext?) _requestCache.Get(ContextKey); set => _requestCache.Set(ContextKey, value); } } diff --git a/src/Umbraco.Core/Models/PublishedContent/HybridVariationContextAccessor.cs b/src/Umbraco.Core/Models/PublishedContent/HybridVariationContextAccessor.cs index 9c50b60ac1..d974041d3b 100644 --- a/src/Umbraco.Core/Models/PublishedContent/HybridVariationContextAccessor.cs +++ b/src/Umbraco.Core/Models/PublishedContent/HybridVariationContextAccessor.cs @@ -14,7 +14,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent /// /// Gets or sets the object. /// - public VariationContext VariationContext + public VariationContext? VariationContext { get => Value; set => Value = value; diff --git a/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs b/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs index 75caa212c5..411c4d55cf 100644 --- a/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs +++ b/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs @@ -29,12 +29,12 @@ namespace Umbraco.Cms.Core.Models.PublishedContent /// /// Gets the name of the content item for the current culture. /// - string Name { get; } + string? Name { get; } /// /// Gets the URL segment of the content item for the current culture. /// - string UrlSegment { get; } + string? UrlSegment { get; } /// /// Gets the sort order of the content item. @@ -109,7 +109,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent /// is the edited version) or false (document is published, and has not been edited, and /// what is returned is the published version). /// - bool IsDraft(string culture = null); + bool IsDraft(string? culture = null); /// /// Gets a value indicating whether the content is published. @@ -123,7 +123,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent /// It is therefore possible for both IsDraft and IsPublished to be true at the same /// time, meaning that the content is the draft version, and a published version exists. /// - bool IsPublished(string culture = null); + bool IsPublished(string? culture = null); #endregion diff --git a/src/Umbraco.Core/Models/PublishedContent/IPublishedContentType.cs b/src/Umbraco.Core/Models/PublishedContent/IPublishedContentType.cs index 866acc0c4d..ba060fa5d0 100644 --- a/src/Umbraco.Core/Models/PublishedContent/IPublishedContentType.cs +++ b/src/Umbraco.Core/Models/PublishedContent/IPublishedContentType.cs @@ -48,7 +48,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent /// /// Gets the content type properties. /// - IEnumerable PropertyTypes { get; } + IEnumerable? PropertyTypes { get; } /// /// Gets a property type index. @@ -59,11 +59,11 @@ namespace Umbraco.Cms.Core.Models.PublishedContent /// /// Gets a property type. /// - IPublishedPropertyType GetPropertyType(string alias); + IPublishedPropertyType? GetPropertyType(string alias); /// /// Gets a property type. /// - IPublishedPropertyType GetPropertyType(int index); + IPublishedPropertyType? GetPropertyType(int index); } } diff --git a/src/Umbraco.Core/Models/PublishedContent/IPublishedProperty.cs b/src/Umbraco.Core/Models/PublishedContent/IPublishedProperty.cs index 5d2eab7830..804d0972da 100644 --- a/src/Umbraco.Core/Models/PublishedContent/IPublishedProperty.cs +++ b/src/Umbraco.Core/Models/PublishedContent/IPublishedProperty.cs @@ -37,7 +37,7 @@ /// If you're using that value, you're probably wrong, unless you're doing some internal /// Umbraco stuff. /// - object GetSourceValue(string? culture = null, string? segment = null); + object? GetSourceValue(string? culture = null, string? segment = null); /// /// Gets the object value of the property. @@ -47,7 +47,7 @@ /// It can be null, or any type of CLR object. /// It has been fully prepared and processed by the appropriate converter. /// - object GetValue(string? culture = null, string? segment = null); + object? GetValue(string? culture = null, string? segment = null); /// /// Gets the XPath value of the property. @@ -57,6 +57,6 @@ /// It must be either null, or a string, or an XPathNavigator. /// It has been fully prepared and processed by the appropriate converter. /// - object GetXPathValue(string? culture = null, string? segment = null); + object? GetXPathValue(string? culture = null, string? segment = null); } } diff --git a/src/Umbraco.Core/Models/PublishedContent/IPublishedPropertyType.cs b/src/Umbraco.Core/Models/PublishedContent/IPublishedPropertyType.cs index 04d900e89f..f81acca36f 100644 --- a/src/Umbraco.Core/Models/PublishedContent/IPublishedPropertyType.cs +++ b/src/Umbraco.Core/Models/PublishedContent/IPublishedPropertyType.cs @@ -13,7 +13,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent /// /// Gets the published content type containing the property type. /// - IPublishedContentType ContentType { get; } + IPublishedContentType? ContentType { get; } /// /// Gets the data type. @@ -84,7 +84,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent /// /// The XPath value can be either a string or an XPathNavigator. /// - object ConvertInterToXPath(IPublishedElement owner, PropertyCacheLevel referenceCacheLevel, object inter, bool preview); + object? ConvertInterToXPath(IPublishedElement owner, PropertyCacheLevel referenceCacheLevel, object inter, bool preview); /// /// Gets the property model CLR type. @@ -93,7 +93,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent /// The model CLR type may be a type, or may contain types. /// For the actual CLR type, see . /// - Type ModelClrType { get; } + Type? ModelClrType { get; } /// /// Gets the property CLR type. @@ -103,6 +103,6 @@ namespace Umbraco.Cms.Core.Models.PublishedContent /// Mapping from may throw if some instances /// could not be mapped to actual CLR types. /// - Type ClrType { get; } + Type? ClrType { get; } } } diff --git a/src/Umbraco.Core/Models/PublishedContent/IPublishedValueFallback.cs b/src/Umbraco.Core/Models/PublishedContent/IPublishedValueFallback.cs index ba5790fca5..c1ecf1909a 100644 --- a/src/Umbraco.Core/Models/PublishedContent/IPublishedValueFallback.cs +++ b/src/Umbraco.Core/Models/PublishedContent/IPublishedValueFallback.cs @@ -25,7 +25,7 @@ /// so the variant context should be used to contextualize them (see our default implementation in /// the web project. /// - bool TryGetValue(IPublishedProperty property, string? culture, string? segment, Fallback fallback, object? defaultValue, out object value); + bool TryGetValue(IPublishedProperty property, string? culture, string? segment, Fallback fallback, object? defaultValue, out object? value); /// /// Tries to get a fallback value for a property. @@ -45,7 +45,7 @@ /// At property level, property.GetValue() does *not* implement fallback, and one has to /// get property.Value() or property.Value{T}() to trigger fallback. /// - bool TryGetValue(IPublishedProperty property, string? culture, string? segment, Fallback fallback, T? defaultValue, out T value); + bool TryGetValue(IPublishedProperty property, string? culture, string? segment, Fallback fallback, T? defaultValue, out T? value); /// /// Tries to get a fallback value for a published element property. @@ -63,7 +63,7 @@ /// segment, either returned no property at all, or a property with HasValue(culture, segment) being false. /// It can only fallback at element level (no recurse). /// - bool TryGetValue(IPublishedElement content, string alias, string? culture, string? segment, Fallback fallback, object? defaultValue, out object value); + bool TryGetValue(IPublishedElement content, string alias, string? culture, string? segment, Fallback fallback, object? defaultValue, out object? value); /// /// Tries to get a fallback value for a published element property. @@ -82,7 +82,7 @@ /// segment, either returned no property at all, or a property with HasValue(culture, segment) being false. /// It can only fallback at element level (no recurse). /// - bool TryGetValue(IPublishedElement content, string alias, string? culture, string? segment, Fallback fallback, T? defaultValue, out T value); + bool TryGetValue(IPublishedElement content, string alias, string? culture, string? segment, Fallback fallback, T? defaultValue, out T? value); /// /// Tries to get a fallback value for a published content property. @@ -104,7 +104,7 @@ /// parameter is used to return a property with no value. That can then be used to invoke a converter and get the /// converter's interpretation of "no value". /// - bool TryGetValue(IPublishedContent content, string alias, string? culture, string? segment, Fallback fallback, object? defaultValue, out object value, out IPublishedProperty noValueProperty); + bool TryGetValue(IPublishedContent content, string alias, string? culture, string? segment, Fallback fallback, object? defaultValue, out object? value, out IPublishedProperty? noValueProperty); /// /// Tries to get a fallback value for a published content property. @@ -127,6 +127,6 @@ /// parameter is used to return a property with no value. That can then be used to invoke a converter and get the /// converter's interpretation of "no value". /// - bool TryGetValue(IPublishedContent content, string alias, string? culture, string? segment, Fallback fallback, T defaultValue, out T value, out IPublishedProperty noValueProperty); + bool TryGetValue(IPublishedContent content, string alias, string? culture, string? segment, Fallback fallback, T defaultValue, out T? value, out IPublishedProperty? noValueProperty); } } diff --git a/src/Umbraco.Core/Models/PublishedContent/IVariationContextAccessor.cs b/src/Umbraco.Core/Models/PublishedContent/IVariationContextAccessor.cs index 39f256faf2..83c5f19c9e 100644 --- a/src/Umbraco.Core/Models/PublishedContent/IVariationContextAccessor.cs +++ b/src/Umbraco.Core/Models/PublishedContent/IVariationContextAccessor.cs @@ -8,6 +8,6 @@ /// /// Gets or sets the current . /// - VariationContext VariationContext { get; set; } + VariationContext? VariationContext { get; set; } } } diff --git a/src/Umbraco.Core/Models/PublishedContent/ModelType.cs b/src/Umbraco.Core/Models/PublishedContent/ModelType.cs index 921059ff22..2673a61876 100644 --- a/src/Umbraco.Core/Models/PublishedContent/ModelType.cs +++ b/src/Umbraco.Core/Models/PublishedContent/ModelType.cs @@ -89,10 +89,10 @@ namespace Umbraco.Cms.Core.Models.PublishedContent /// The type. /// The model types map. /// The actual CLR type name. - public static string MapToName(Type type, Dictionary map) + public static string? MapToName(Type type, Dictionary map) => MapToName(type, map, false); - private static string MapToName(Type type, Dictionary map, bool dictionaryIsInvariant) + private static string? MapToName(Type type, Dictionary map, bool dictionaryIsInvariant) { // it may be that senders forgot to send an invariant dictionary (garbage-in) if (!dictionaryIsInvariant) @@ -119,7 +119,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent throw new PanicException($"The type {type} has not generic type definition"); var args = type.GetGenericArguments().Select(x => MapToName(x, map, true)).ToArray(); - var defFullName = def.FullName.Substring(0, def.FullName.IndexOf('`')); + var defFullName = def.FullName?.Substring(0, def.FullName.IndexOf('`')); return defFullName + "<" + string.Join(", ", args) + ">"; } @@ -166,7 +166,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent => Array.Empty(); /// - protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) + protected override ConstructorInfo? GetConstructorImpl(BindingFlags bindingAttr, Binder? binder, CallingConventions callConvention, Type[] types, ParameterModifier[]? modifiers) => null; /// @@ -174,7 +174,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent => Array.Empty(); /// - public override Type GetInterface(string name, bool ignoreCase) + public override Type? GetInterface(string name, bool ignoreCase) => null; /// @@ -182,7 +182,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent => Array.Empty(); /// - public override EventInfo GetEvent(string name, BindingFlags bindingAttr) + public override EventInfo? GetEvent(string name, BindingFlags bindingAttr) => null; /// @@ -190,7 +190,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent => Array.Empty(); /// - public override Type GetNestedType(string name, BindingFlags bindingAttr) + public override Type? GetNestedType(string name, BindingFlags bindingAttr) => null; /// @@ -198,7 +198,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent => Array.Empty(); /// - protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) + protected override PropertyInfo? GetPropertyImpl(string name, BindingFlags bindingAttr, Binder? binder, Type? returnType, Type[]? types, ParameterModifier[]? modifiers) => null; /// @@ -206,7 +206,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent => Array.Empty(); /// - protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) + protected override MethodInfo? GetMethodImpl(string name, BindingFlags bindingAttr, Binder? binder, CallingConventions callConvention, Type[]? types, ParameterModifier[]? modifiers) => null; /// @@ -214,7 +214,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent => Array.Empty(); /// - public override FieldInfo GetField(string name, BindingFlags bindingAttr) + public override FieldInfo? GetField(string name, BindingFlags bindingAttr) => null; /// @@ -234,7 +234,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent => false; /// - public override Type GetElementType() + public override Type? GetElementType() => null; /// @@ -262,14 +262,14 @@ namespace Umbraco.Cms.Core.Models.PublishedContent => false; /// - public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters) + public override object InvokeMember(string name, BindingFlags invokeAttr, Binder? binder, object? target, object?[]? args, ParameterModifier[]? modifiers, CultureInfo? culture, string[]? namedParameters) => throw new NotSupportedException(); /// public override Type UnderlyingSystemType => this; /// - public override Type BaseType => null; + public override Type? BaseType => null; /// public override string Name { get; } @@ -319,43 +319,43 @@ namespace Umbraco.Cms.Core.Models.PublishedContent public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) => Array.Empty(); - protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) + protected override ConstructorInfo? GetConstructorImpl(BindingFlags bindingAttr, Binder? binder, CallingConventions callConvention, Type[] types, ParameterModifier[]? modifiers) => null; public override Type[] GetInterfaces() => Array.Empty(); - public override Type GetInterface(string name, bool ignoreCase) + public override Type? GetInterface(string name, bool ignoreCase) => null; public override EventInfo[] GetEvents(BindingFlags bindingAttr) => Array.Empty(); - public override EventInfo GetEvent(string name, BindingFlags bindingAttr) + public override EventInfo? GetEvent(string name, BindingFlags bindingAttr) => null; public override Type[] GetNestedTypes(BindingFlags bindingAttr) => Array.Empty(); - public override Type GetNestedType(string name, BindingFlags bindingAttr) + public override Type? GetNestedType(string name, BindingFlags bindingAttr) => null; public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) => Array.Empty(); - protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) + protected override PropertyInfo? GetPropertyImpl(string name, BindingFlags bindingAttr, Binder? binder, Type? returnType, Type[]? types, ParameterModifier[]? modifiers) => null; public override MethodInfo[] GetMethods(BindingFlags bindingAttr) => Array.Empty(); - protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) + protected override MethodInfo? GetMethodImpl(string name, BindingFlags bindingAttr, Binder? binder, CallingConventions callConvention, Type[]? types, ParameterModifier[]? modifiers) => null; public override FieldInfo[] GetFields(BindingFlags bindingAttr) => Array.Empty(); - public override FieldInfo GetField(string name, BindingFlags bindingAttr) + public override FieldInfo? GetField(string name, BindingFlags bindingAttr) => null; public override MemberInfo[] GetMembers(BindingFlags bindingAttr) @@ -390,13 +390,13 @@ namespace Umbraco.Cms.Core.Models.PublishedContent protected override bool IsCOMObjectImpl() => false; - public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters) + public override object InvokeMember(string name, BindingFlags invokeAttr, Binder? binder, object? target, object?[]? args, ParameterModifier[]? modifiers, CultureInfo? culture, string[]? namedParameters) { throw new NotSupportedException(); } public override Type UnderlyingSystemType => this; - public override Type BaseType => null; + public override Type? BaseType => null; public override string Name { get; } public override Guid GUID { get; } = Guid.NewGuid(); diff --git a/src/Umbraco.Core/Models/PublishedContent/NoopPublishedValueFallback.cs b/src/Umbraco.Core/Models/PublishedContent/NoopPublishedValueFallback.cs index 82a6b44565..a08a20658d 100644 --- a/src/Umbraco.Core/Models/PublishedContent/NoopPublishedValueFallback.cs +++ b/src/Umbraco.Core/Models/PublishedContent/NoopPublishedValueFallback.cs @@ -9,35 +9,35 @@ public class NoopPublishedValueFallback : IPublishedValueFallback { /// - public bool TryGetValue(IPublishedProperty property, string culture, string segment, Fallback fallback, object defaultValue, out object value) + public bool TryGetValue(IPublishedProperty property, string? culture, string? segment, Fallback fallback, object? defaultValue, out object? value) { value = default; return false; } /// - public bool TryGetValue(IPublishedProperty property, string culture, string segment, Fallback fallback, T defaultValue, out T value) + public bool TryGetValue(IPublishedProperty property, string? culture, string? segment, Fallback fallback, T? defaultValue, out T? value) { value = default; return false; } /// - public bool TryGetValue(IPublishedElement content, string alias, string culture, string segment, Fallback fallback, object defaultValue, out object value) + public bool TryGetValue(IPublishedElement content, string alias, string? culture, string? segment, Fallback fallback, object? defaultValue, out object? value) { value = default; return false; } /// - public bool TryGetValue(IPublishedElement content, string alias, string culture, string segment, Fallback fallback, T defaultValue, out T value) + public bool TryGetValue(IPublishedElement content, string alias, string? culture, string? segment, Fallback fallback, T? defaultValue, out T? value) { value = default; return false; } /// - public bool TryGetValue(IPublishedContent content, string alias, string culture, string segment, Fallback fallback, object defaultValue, out object value, out IPublishedProperty noValueProperty) + public bool TryGetValue(IPublishedContent content, string alias, string? culture, string? segment, Fallback fallback, object? defaultValue, out object? value, out IPublishedProperty? noValueProperty) { value = default; noValueProperty = default; @@ -45,7 +45,7 @@ } /// - public bool TryGetValue(IPublishedContent content, string alias, string culture, string segment, Fallback fallback, T defaultValue, out T value, out IPublishedProperty noValueProperty) + public bool TryGetValue(IPublishedContent content, string alias, string? culture, string? segment, Fallback fallback, T defaultValue, out T? value, out IPublishedProperty? noValueProperty) { value = default; noValueProperty = default; diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentBase.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentBase.cs index 7c57b8281f..c229941586 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentBase.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentBase.cs @@ -39,10 +39,10 @@ namespace Umbraco.Cms.Core.Models.PublishedContent public abstract int Id { get; } /// - public virtual string Name => this.Name(_variationContextAccessor); + public virtual string? Name => this.Name(_variationContextAccessor); /// - public virtual string UrlSegment => this.UrlSegment(_variationContextAccessor); + public virtual string? UrlSegment => this.UrlSegment(_variationContextAccessor); /// public abstract int SortOrder { get; } @@ -75,10 +75,10 @@ namespace Umbraco.Cms.Core.Models.PublishedContent public abstract PublishedItemType ItemType { get; } /// - public abstract bool IsDraft(string culture = null); + public abstract bool IsDraft(string? culture = null); /// - public abstract bool IsPublished(string culture = null); + public abstract bool IsPublished(string? culture = null); #endregion diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentExtensionsForModels.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentExtensionsForModels.cs index c258d4e50b..731d670184 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentExtensionsForModels.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentExtensionsForModels.cs @@ -13,7 +13,7 @@ namespace Umbraco.Extensions /// /// The internal published content. /// The strongly typed published content model. - public static IPublishedContent CreateModel(this IPublishedContent content, IPublishedModelFactory publishedModelFactory) + public static IPublishedContent? CreateModel(this IPublishedContent content, IPublishedModelFactory publishedModelFactory) { if (publishedModelFactory == null) throw new ArgumentNullException(nameof(publishedModelFactory)); if (content == null) diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentType.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentType.cs index c4d7b96feb..fbf29ac235 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentType.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentType.cs @@ -14,7 +14,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent [DebuggerDisplay("{Alias}")] public class PublishedContentType : IPublishedContentType { - private readonly IPublishedPropertyType[] _propertyTypes; + private readonly IPublishedPropertyType[]? _propertyTypes; // fast alias-to-index xref containing both the raw alias and its lowercase version private readonly Dictionary _indexes = new Dictionary(); @@ -102,11 +102,17 @@ namespace Umbraco.Cms.Core.Models.PublishedContent private void InitializeIndexes() { - for (var i = 0; i < _propertyTypes.Length; i++) + if (_propertyTypes is not null) { - var propertyType = _propertyTypes[i]; - _indexes[propertyType.Alias] = i; - _indexes[propertyType.Alias.ToLowerInvariant()] = i; + for (var i = 0; i < _propertyTypes.Length; i++) + { + IPublishedPropertyType propertyType = _propertyTypes[i]; + if (propertyType.Alias is not null) + { + _indexes[propertyType.Alias] = i; + _indexes[propertyType.Alias.ToLowerInvariant()] = i; + } + } } } @@ -115,7 +121,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent // same alias does not exist already. private void EnsureMemberProperties(List propertyTypes, IPublishedContentTypeFactory factory) { - var aliases = new HashSet(propertyTypes.Select(x => x.Alias), StringComparer.OrdinalIgnoreCase); + var aliases = new HashSet(propertyTypes.Select(x => x.Alias), StringComparer.OrdinalIgnoreCase); foreach (var (alias, dataTypeId) in BuiltinMemberProperties) { @@ -163,7 +169,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent #region Properties /// - public IEnumerable PropertyTypes => _propertyTypes; + public IEnumerable? PropertyTypes => _propertyTypes; /// public int GetPropertyIndex(string alias) @@ -176,7 +182,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent // virtual for unit tests // TODO: explain why /// - public virtual IPublishedPropertyType GetPropertyType(string alias) + public virtual IPublishedPropertyType? GetPropertyType(string alias) { var index = GetPropertyIndex(alias); return GetPropertyType(index); @@ -185,9 +191,9 @@ namespace Umbraco.Cms.Core.Models.PublishedContent // virtual for unit tests // TODO: explain why /// - public virtual IPublishedPropertyType GetPropertyType(int index) + public virtual IPublishedPropertyType? GetPropertyType(int index) { - return index >= 0 && index < _propertyTypes.Length ? _propertyTypes[index] : null; + return index >= 0 && _propertyTypes is not null && index < _propertyTypes.Length ? _propertyTypes[index] : null; } /// diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeConverter.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeConverter.cs index 9c57fe29a9..23adf358ca 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeConverter.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeConverter.cs @@ -9,13 +9,13 @@ namespace Umbraco.Cms.Core.Models.PublishedContent { private static readonly Type[] ConvertingTypes = { typeof(int) }; - public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType) { return ConvertingTypes.Any(x => x.IsAssignableFrom(destinationType)) - || CanConvertFrom(context, destinationType); + || (destinationType is not null && CanConvertFrom(context, destinationType)); } - public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType) { if (!(value is IPublishedContent publishedContent)) return null; diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeFactory.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeFactory.cs index d93049abeb..31a05123b1 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeFactory.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeFactory.cs @@ -15,7 +15,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent private readonly PropertyValueConverterCollection _propertyValueConverters; private readonly IDataTypeService _dataTypeService; private readonly object _publishedDataTypesLocker = new object(); - private Dictionary _publishedDataTypes; + private Dictionary? _publishedDataTypes; public PublishedContentTypeFactory(IPublishedModelFactory publishedModelFactory, PropertyValueConverterCollection propertyValueConverters, IDataTypeService dataTypeService) { @@ -119,6 +119,6 @@ namespace Umbraco.Cms.Core.Models.PublishedContent } private PublishedDataType CreatePublishedDataType(IDataType dataType) - => new PublishedDataType(dataType.Id, dataType.EditorAlias, dataType is DataType d ? d.GetLazyConfiguration() : new Lazy(() => dataType.Configuration)); + => new PublishedDataType(dataType.Id, dataType.EditorAlias, dataType is DataType d ? d.GetLazyConfiguration() : new Lazy(() => dataType.Configuration)); } } diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs index 92fb4a4c28..abd933ae01 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs @@ -63,10 +63,10 @@ namespace Umbraco.Cms.Core.Models.PublishedContent public virtual int Id => _content.Id; /// - public virtual string Name => _content.Name; + public virtual string? Name => _content.Name; /// - public virtual string UrlSegment => _content.UrlSegment; + public virtual string? UrlSegment => _content.UrlSegment; /// public virtual int SortOrder => _content.SortOrder; @@ -99,10 +99,10 @@ namespace Umbraco.Cms.Core.Models.PublishedContent public virtual PublishedItemType ItemType => _content.ItemType; /// - public virtual bool IsDraft(string culture = null) => _content.IsDraft(culture); + public virtual bool IsDraft(string? culture = null) => _content.IsDraft(culture); /// - public virtual bool IsPublished(string culture = null) => _content.IsPublished(culture); + public virtual bool IsPublished(string? culture = null) => _content.IsPublished(culture); #endregion diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedDataType.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedDataType.cs index 725616f708..de590c2531 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedDataType.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedDataType.cs @@ -14,12 +14,12 @@ namespace Umbraco.Cms.Core.Models.PublishedContent [DebuggerDisplay("{EditorAlias}")] public class PublishedDataType { - private readonly Lazy _lazyConfiguration; + private readonly Lazy _lazyConfiguration; /// /// Initializes a new instance of the class. /// - public PublishedDataType(int id, string editorAlias, Lazy lazyConfiguration) + public PublishedDataType(int id, string editorAlias, Lazy lazyConfiguration) { _lazyConfiguration = lazyConfiguration; @@ -40,14 +40,14 @@ namespace Umbraco.Cms.Core.Models.PublishedContent /// /// Gets the data type configuration. /// - public object Configuration => _lazyConfiguration.Value; + public object? Configuration => _lazyConfiguration?.Value; /// /// Gets the configuration object. /// /// The expected type of the configuration object. /// When the datatype configuration is not of the expected type. - public T ConfigurationAs() + public T? ConfigurationAs() where T : class { switch (Configuration) diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedModelFactory.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedModelFactory.cs index 23a060a3fd..94aae97385 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedModelFactory.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedModelFactory.cs @@ -10,19 +10,19 @@ namespace Umbraco.Cms.Core.Models.PublishedContent /// public class PublishedModelFactory : IPublishedModelFactory { - private readonly Dictionary _modelInfos; + private readonly Dictionary? _modelInfos; private readonly Dictionary _modelTypeMap; private readonly IPublishedValueFallback _publishedValueFallback; private class ModelInfo { - public Type ParameterType { get; set; } + public Type? ParameterType { get; set; } - public Func Ctor { get; set; } + public Func? Ctor { get; set; } - public Type ModelType { get; set; } + public Type? ModelType { get; set; } - public Func ListCtor { get; set; } + public Func? ListCtor { get; set; } } /// @@ -50,8 +50,8 @@ namespace Umbraco.Cms.Core.Models.PublishedContent // IPublishedElement - but it can be IPublishedContent - so we cannot get one precise ctor, // we have to iterate over all ctors and try to find the right one - ConstructorInfo constructor = null; - Type parameterType = null; + ConstructorInfo? constructor = null; + Type? parameterType = null; foreach (var ctor in type.GetConstructors()) { @@ -72,7 +72,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent var typeName = attribute == null ? type.Name : attribute.ContentTypeAlias; if (modelInfos.TryGetValue(typeName, out var modelInfo)) - throw new InvalidOperationException($"Both types '{type.AssemblyQualifiedName}' and '{modelInfo.ModelType.AssemblyQualifiedName}' want to be a model type for content type with alias \"{typeName}\"."); + throw new InvalidOperationException($"Both types '{type.AssemblyQualifiedName}' and '{modelInfo.ModelType?.AssemblyQualifiedName}' want to be a model type for content type with alias \"{typeName}\"."); // have to use an unsafe ctor because we don't know the types, really var modelCtor = ReflectionUtilities.EmitConstructorUnsafe>(constructor); @@ -92,15 +92,15 @@ namespace Umbraco.Cms.Core.Models.PublishedContent if (_modelInfos == null) return element; - if (!_modelInfos.TryGetValue(element.ContentType.Alias, out var modelInfo)) + if (element.ContentType.Alias is null || !_modelInfos.TryGetValue(element.ContentType.Alias, out var modelInfo)) return element; // ReSharper disable once UseMethodIsInstanceOfType - if (modelInfo.ParameterType.IsAssignableFrom(element.GetType()) == false) + if (modelInfo.ParameterType?.IsAssignableFrom(element.GetType()) == false) throw new InvalidOperationException($"Model {modelInfo.ModelType} expects argument of type {modelInfo.ParameterType.FullName}, but got {element.GetType().FullName}."); // can cast, because we checked when creating the ctor - return (IPublishedElement)modelInfo.Ctor(element, _publishedValueFallback); + return (IPublishedElement)modelInfo.Ctor!(element, _publishedValueFallback); } /// @@ -110,7 +110,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent if (_modelInfos == null) return new List(); - if (!_modelInfos.TryGetValue(alias, out var modelInfo)) + if (!_modelInfos.TryGetValue(alias, out var modelInfo) || modelInfo.ModelType is null) return new List(); var ctor = modelInfo.ListCtor; diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyBase.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyBase.cs index d32943357e..6cdbd85c74 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyBase.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyBase.cs @@ -55,15 +55,15 @@ namespace Umbraco.Cms.Core.Models.PublishedContent public string Alias => PropertyType.Alias; /// - public abstract bool HasValue(string culture = null, string? segment = null); + public abstract bool HasValue(string? culture = null, string? segment = null); /// - public abstract object GetSourceValue(string culture = null, string? segment = null); + public abstract object? GetSourceValue(string? culture = null, string? segment = null); /// - public abstract object GetValue(string culture = null, string? segment = null); + public abstract object? GetValue(string? culture = null, string? segment = null); /// - public abstract object GetXPathValue(string culture = null, string? segment = null); + public abstract object? GetXPathValue(string? culture = null, string? segment = null); } } diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs index ee55917c4c..c8b5773106 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs @@ -18,11 +18,11 @@ namespace Umbraco.Cms.Core.Models.PublishedContent private readonly PropertyValueConverterCollection _propertyValueConverters; private readonly object _locker = new object(); private volatile bool _initialized; - private IPropertyValueConverter _converter; + private IPropertyValueConverter? _converter; private PropertyCacheLevel _cacheLevel; - private Type _modelClrType; - private Type _clrType; + private Type? _modelClrType; + private Type? _clrType; #region Constructors @@ -76,7 +76,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent #region Property type /// - public IPublishedContentType ContentType { get; internal set; } // internally set by PublishedContentType constructor + public IPublishedContentType? ContentType { get; internal set; } // internally set by PublishedContentType constructor /// public PublishedDataType DataType { get; } @@ -145,7 +145,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent throw new InvalidOperationException(string.Format("Type '{2}' cannot be an IPropertyValueConverter" + " for property '{1}' of content type '{0}' because type '{3}' has already been detected as a converter" + " for that property, and only one converter can exist for a property.", - ContentType.Alias, Alias, + ContentType?.Alias, Alias, converter.GetType().FullName, _converter.GetType().FullName)); } } @@ -168,7 +168,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent throw new InvalidOperationException(string.Format("Type '{2}' cannot be an IPropertyValueConverter" + " for property '{1}' of content type '{0}' because type '{3}' has already been detected as a converter" + " for that property, and only one converter can exist for a property.", - ContentType.Alias, Alias, + ContentType?.Alias, Alias, converter.GetType().FullName, _converter.GetType().FullName)); } } @@ -224,7 +224,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent } /// - public object ConvertInterToXPath(IPublishedElement owner, PropertyCacheLevel referenceCacheLevel, object inter, bool preview) + public object? ConvertInterToXPath(IPublishedElement owner, PropertyCacheLevel referenceCacheLevel, object inter, bool preview) { if (!_initialized) Initialize(); @@ -236,11 +236,11 @@ namespace Umbraco.Cms.Core.Models.PublishedContent if (inter == null) return null; if (inter is XElement xElement) return xElement.CreateNavigator(); - return inter.ToString().Trim(); + return inter.ToString()?.Trim(); } /// - public Type ModelClrType + public Type? ModelClrType { get { @@ -250,12 +250,12 @@ namespace Umbraco.Cms.Core.Models.PublishedContent } /// - public Type ClrType + public Type? ClrType { get { if (!_initialized) Initialize(); - return _clrType ?? (_clrType = _publishedModelFactory.MapModelType(_modelClrType)); + return _clrType ?? (_modelClrType is not null ? _clrType = _publishedModelFactory.MapModelType(_modelClrType) : null); } } diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedValueFallback.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedValueFallback.cs index 2c4ecfdb67..811d230ef9 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedValueFallback.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedValueFallback.cs @@ -23,13 +23,13 @@ namespace Umbraco.Cms.Core.Models.PublishedContent } /// - public bool TryGetValue(IPublishedProperty property, string culture, string segment, Fallback fallback, object defaultValue, out object value) + public bool TryGetValue(IPublishedProperty property, string? culture, string? segment, Fallback fallback, object? defaultValue, out object? value) { return TryGetValue(property, culture, segment, fallback, defaultValue, out value); } /// - public bool TryGetValue(IPublishedProperty property, string culture, string segment, Fallback fallback, T defaultValue, out T value) + public bool TryGetValue(IPublishedProperty property, string? culture, string? segment, Fallback fallback, T? defaultValue, out T? value) { _variationContextAccessor.ContextualizeVariation(property.PropertyType.Variations, ref culture, ref segment); @@ -56,13 +56,13 @@ namespace Umbraco.Cms.Core.Models.PublishedContent } /// - public bool TryGetValue(IPublishedElement content, string alias, string culture, string segment, Fallback fallback, object defaultValue, out object value) + public bool TryGetValue(IPublishedElement content, string alias, string? culture, string? segment, Fallback fallback, object? defaultValue, out object? value) { return TryGetValue(content, alias, culture, segment, fallback, defaultValue, out value); } /// - public bool TryGetValue(IPublishedElement content, string alias, string culture, string segment, Fallback fallback, T defaultValue, out T value) + public bool TryGetValue(IPublishedElement content, string alias, string? culture, string? segment, Fallback fallback, T? defaultValue, out T? value) { var propertyType = content.ContentType.GetPropertyType(alias); if (propertyType == null) @@ -96,13 +96,13 @@ namespace Umbraco.Cms.Core.Models.PublishedContent } /// - public bool TryGetValue(IPublishedContent content, string alias, string culture, string segment, Fallback fallback, object defaultValue, out object value, out IPublishedProperty noValueProperty) + public bool TryGetValue(IPublishedContent content, string alias, string? culture, string? segment, Fallback fallback, object? defaultValue, out object? value, out IPublishedProperty? noValueProperty) { return TryGetValue(content, alias, culture, segment, fallback, defaultValue, out value, out noValueProperty); } /// - public virtual bool TryGetValue(IPublishedContent content, string alias, string culture, string segment, Fallback fallback, T defaultValue, out T value, out IPublishedProperty noValueProperty) + public virtual bool TryGetValue(IPublishedContent content, string alias, string? culture, string? segment, Fallback fallback, T? defaultValue, out T? value, out IPublishedProperty? noValueProperty) { noValueProperty = default; @@ -153,16 +153,16 @@ namespace Umbraco.Cms.Core.Models.PublishedContent // tries to get a value, recursing the tree // because we recurse, content may not even have the a property with the specified alias (but only some ancestor) // in case no value was found, noValueProperty contains the first property that was found (which does not have a value) - private bool TryGetValueWithAncestorsFallback(IPublishedContent content, string alias, string culture, string segment, out T value, ref IPublishedProperty noValueProperty) + private bool TryGetValueWithAncestorsFallback(IPublishedContent? content, string alias, string? culture, string? segment, out T? value, ref IPublishedProperty? noValueProperty) { - IPublishedProperty property; // if we are here, content's property has no value + IPublishedProperty? property; // if we are here, content's property has no value do { - content = content.Parent; + content = content?.Parent; var propertyType = content?.ContentType.GetPropertyType(alias); - if (propertyType != null) + if (propertyType != null && content is not null) { culture = null; segment = null; @@ -189,7 +189,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent } // tries to get a value, falling back onto other languages - private bool TryGetValueWithLanguageFallback(IPublishedProperty property, string culture, string segment, out T value) + private bool TryGetValueWithLanguageFallback(IPublishedProperty property, string? culture, string? segment, out T? value) { value = default; @@ -197,7 +197,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent var visited = new HashSet(); - var language = _localizationService.GetLanguageByIsoCode(culture); + var language = culture is not null ? _localizationService.GetLanguageByIsoCode(culture) : null; if (language == null) return false; while (true) @@ -223,7 +223,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent } // tries to get a value, falling back onto other languages - private bool TryGetValueWithLanguageFallback(IPublishedElement content, string alias, string culture, string segment, out T value) + private bool TryGetValueWithLanguageFallback(IPublishedElement content, string alias, string? culture, string? segment, out T? value) { value = default; @@ -231,7 +231,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent var visited = new HashSet(); - var language = _localizationService.GetLanguageByIsoCode(culture); + var language = culture is not null ? _localizationService.GetLanguageByIsoCode(culture) : null; if (language == null) return false; while (true) @@ -257,7 +257,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent } // tries to get a value, falling back onto other languages - private bool TryGetValueWithLanguageFallback(IPublishedContent content, string alias, string culture, string segment, out T value) + private bool TryGetValueWithLanguageFallback(IPublishedContent content, string alias, string? culture, string? segment, out T? value) { value = default; @@ -268,7 +268,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent // TODO: _localizationService.GetXxx() is expensive, it deep clones objects // we want _localizationService.GetReadOnlyXxx() returning IReadOnlyLanguage which cannot be saved back = no need to clone - var language = _localizationService.GetLanguageByIsoCode(culture); + var language = culture is not null ? _localizationService.GetLanguageByIsoCode(culture) : null; if (language == null) return false; while (true) diff --git a/src/Umbraco.Core/Models/PublishedContent/RawValueProperty.cs b/src/Umbraco.Core/Models/PublishedContent/RawValueProperty.cs index 730f107fa6..9e52adc07f 100644 --- a/src/Umbraco.Core/Models/PublishedContent/RawValueProperty.cs +++ b/src/Umbraco.Core/Models/PublishedContent/RawValueProperty.cs @@ -18,24 +18,24 @@ namespace Umbraco.Cms.Core.Models.PublishedContent { private readonly object _sourceValue; //the value in the db private readonly Lazy _objectValue; - private readonly Lazy _xpathValue; + private readonly Lazy _xpathValue; // RawValueProperty does not (yet?) support variants, // only manages the current "default" value - public override object GetSourceValue(string culture = null, string? segment = null) + public override object? GetSourceValue(string? culture = null, string? segment = null) => string.IsNullOrEmpty(culture) & string.IsNullOrEmpty(segment) ? _sourceValue : null; - public override bool HasValue(string culture = null, string? segment = null) + public override bool HasValue(string? culture = null, string? segment = null) { var sourceValue = GetSourceValue(culture, segment); return sourceValue is string s ? !string.IsNullOrWhiteSpace(s) : sourceValue != null; } - public override object GetValue(string culture = null, string? segment = null) + public override object? GetValue(string? culture = null, string? segment = null) => string.IsNullOrEmpty(culture) & string.IsNullOrEmpty(segment) ? _objectValue.Value : null; - public override object GetXPathValue(string culture = null, string? segment = null) + public override object? GetXPathValue(string? culture = null, string? segment = null) => string.IsNullOrEmpty(culture) & string.IsNullOrEmpty(segment) ? _xpathValue.Value : null; public RawValueProperty(IPublishedPropertyType propertyType, IPublishedElement content, object sourceValue, bool isPreviewing = false) @@ -48,7 +48,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent var interValue = new Lazy(() => PropertyType.ConvertSourceToInter(content, _sourceValue, isPreviewing)); _objectValue = new Lazy(() => PropertyType.ConvertInterToObject(content, PropertyCacheLevel.Unknown, interValue.Value, isPreviewing)); - _xpathValue = new Lazy(() => PropertyType.ConvertInterToXPath(content, PropertyCacheLevel.Unknown, interValue.Value, isPreviewing)); + _xpathValue = new Lazy(() => PropertyType.ConvertInterToXPath(content, PropertyCacheLevel.Unknown, interValue.Value, isPreviewing)); } } } diff --git a/src/Umbraco.Core/Models/PublishedContent/ThreadCultureVariationContextAccessor.cs b/src/Umbraco.Core/Models/PublishedContent/ThreadCultureVariationContextAccessor.cs index a3c4cbfb70..a9d06e521f 100644 --- a/src/Umbraco.Core/Models/PublishedContent/ThreadCultureVariationContextAccessor.cs +++ b/src/Umbraco.Core/Models/PublishedContent/ThreadCultureVariationContextAccessor.cs @@ -14,7 +14,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent { private readonly ConcurrentDictionary _contexts = new ConcurrentDictionary(); - public VariationContext VariationContext + public VariationContext? VariationContext { get => _contexts.GetOrAdd(Thread.CurrentThread.CurrentUICulture.Name, culture => new VariationContext(culture)); set => throw new NotSupportedException(); diff --git a/src/Umbraco.Core/Models/PublishedContent/VariationContext.cs b/src/Umbraco.Core/Models/PublishedContent/VariationContext.cs index ce50180616..9b8ae30245 100644 --- a/src/Umbraco.Core/Models/PublishedContent/VariationContext.cs +++ b/src/Umbraco.Core/Models/PublishedContent/VariationContext.cs @@ -8,7 +8,7 @@ /// /// Initializes a new instance of the class. /// - public VariationContext(string culture = null, string? segment = null) + public VariationContext(string? culture = null, string? segment = null) { Culture = culture ?? ""; // cannot be null, default to invariant Segment = segment ?? ""; // cannot be null, default to neutral diff --git a/src/Umbraco.Core/Models/PublishedContent/VariationContextAccessorExtensions.cs b/src/Umbraco.Core/Models/PublishedContent/VariationContextAccessorExtensions.cs index 16ccd81000..4a986597bd 100644 --- a/src/Umbraco.Core/Models/PublishedContent/VariationContextAccessorExtensions.cs +++ b/src/Umbraco.Core/Models/PublishedContent/VariationContextAccessorExtensions.cs @@ -8,13 +8,13 @@ namespace Umbraco.Extensions { public static class VariationContextAccessorExtensions { - public static void ContextualizeVariation(this IVariationContextAccessor variationContextAccessor, ContentVariation variations, ref string culture, ref string segment) + public static void ContextualizeVariation(this IVariationContextAccessor variationContextAccessor, ContentVariation variations, ref string? culture, ref string? segment) => variationContextAccessor.ContextualizeVariation(variations, null, ref culture, ref segment); - public static void ContextualizeVariation(this IVariationContextAccessor variationContextAccessor, ContentVariation variations, int contentId, ref string culture, ref string segment) + public static void ContextualizeVariation(this IVariationContextAccessor variationContextAccessor, ContentVariation variations, int contentId, ref string? culture, ref string? segment) => variationContextAccessor.ContextualizeVariation(variations, (int?)contentId, ref culture, ref segment); - private static void ContextualizeVariation(this IVariationContextAccessor variationContextAccessor, ContentVariation variations, int? contentId, ref string culture, ref string segment) + private static void ContextualizeVariation(this IVariationContextAccessor variationContextAccessor, ContentVariation variations, int? contentId, ref string? culture, ref string? segment) { if (culture != null && segment != null) return; diff --git a/src/Umbraco.Core/Models/Range.cs b/src/Umbraco.Core/Models/Range.cs index 7aa4bf5ed8..9c5da2087e 100644 --- a/src/Umbraco.Core/Models/Range.cs +++ b/src/Umbraco.Core/Models/Range.cs @@ -17,7 +17,7 @@ namespace Umbraco.Cms.Core.Models /// /// The minimum value. /// - public T Minimum { get; set; } + public T? Minimum { get; set; } /// /// Gets or sets the maximum value. @@ -25,7 +25,7 @@ namespace Umbraco.Cms.Core.Models /// /// The maximum value. /// - public T Maximum { get; set; } + public T? Maximum { get; set; } /// /// Returns a that represents this instance. @@ -44,7 +44,7 @@ namespace Umbraco.Cms.Core.Models /// /// A that represents this instance. /// - public string ToString(string format, string formatRange, IFormatProvider provider = null) => this.ToString(this.Minimum.CompareTo(this.Maximum) == 0 ? format : formatRange, provider); + public string ToString(string format, string formatRange, IFormatProvider? provider = null) => this.ToString(this.Minimum?.CompareTo(this.Maximum) == 0 ? format : formatRange, provider); /// /// Returns a that represents this instance. @@ -54,7 +54,7 @@ namespace Umbraco.Cms.Core.Models /// /// A that represents this instance. /// - public string ToString(string format, IFormatProvider provider = null) => string.Format(provider, format, this.Minimum, this.Maximum); + public string ToString(string format, IFormatProvider? provider = null) => string.Format(provider, format, this.Minimum, this.Maximum); /// /// Determines whether this range is valid (the minimum value is lower than or equal to the maximum value). @@ -62,7 +62,7 @@ namespace Umbraco.Cms.Core.Models /// /// true if this range is valid; otherwise, false. /// - public bool IsValid() => this.Minimum.CompareTo(this.Maximum) <= 0; + public bool IsValid() => this.Minimum?.CompareTo(this.Maximum) <= 0; /// /// Determines whether this range contains the specified value. @@ -71,7 +71,7 @@ namespace Umbraco.Cms.Core.Models /// /// true if this range contains the specified value; otherwise, false. /// - public bool ContainsValue(T value) => this.Minimum.CompareTo(value) <= 0 && value.CompareTo(this.Maximum) <= 0; + public bool ContainsValue(T? value) => this.Minimum?.CompareTo(value) <= 0 && value?.CompareTo(this.Maximum) <= 0; /// /// Determines whether this range is inside the specified range. @@ -98,7 +98,7 @@ namespace Umbraco.Cms.Core.Models /// /// true if the specified is equal to this instance; otherwise, false. /// - public override bool Equals(object obj) => obj is Range other && this.Equals(other); + public override bool Equals(object? obj) => obj is Range other && this.Equals(other); /// /// Indicates whether the current object is equal to another object of the same type. @@ -107,7 +107,7 @@ namespace Umbraco.Cms.Core.Models /// /// if the current object is equal to the parameter; otherwise, . /// - public bool Equals(Range other) => other != null && this.Equals(other.Minimum, other.Maximum); + public bool Equals(Range? other) => other != null && this.Equals(other.Minimum, other.Maximum); /// /// Determines whether the specified and values are equal to this instance values. @@ -117,7 +117,7 @@ namespace Umbraco.Cms.Core.Models /// /// true if the specified and values are equal to this instance values; otherwise, false. /// - public bool Equals(T minimum, T maximum) => this.Minimum.CompareTo(minimum) == 0 && this.Maximum.CompareTo(maximum) == 0; + public bool Equals(T? minimum, T? maximum) => this.Minimum?.CompareTo(minimum) == 0 && this.Maximum?.CompareTo(maximum) == 0; /// /// Returns a hash code for this instance. diff --git a/src/Umbraco.Core/Models/ReadOnlyContentBaseAdapter.cs b/src/Umbraco.Core/Models/ReadOnlyContentBaseAdapter.cs index 77d285596a..cbb1e51a3e 100644 --- a/src/Umbraco.Core/Models/ReadOnlyContentBaseAdapter.cs +++ b/src/Umbraco.Core/Models/ReadOnlyContentBaseAdapter.cs @@ -21,7 +21,7 @@ namespace Umbraco.Cms.Core.Models public DateTime UpdateDate => _content.UpdateDate; - public string Name => _content.Name; + public string? Name => _content.Name; public int CreatorId => _content.CreatorId; @@ -29,7 +29,7 @@ namespace Umbraco.Cms.Core.Models public int Level => _content.Level; - public string Path => _content.Path; + public string? Path => _content.Path; public int SortOrder => _content.SortOrder; diff --git a/src/Umbraco.Core/Models/RedirectUrl.cs b/src/Umbraco.Core/Models/RedirectUrl.cs index 2997ae0ffd..ca3374c7a9 100644 --- a/src/Umbraco.Core/Models/RedirectUrl.cs +++ b/src/Umbraco.Core/Models/RedirectUrl.cs @@ -22,8 +22,8 @@ namespace Umbraco.Cms.Core.Models private int _contentId; private Guid _contentKey; private DateTime _createDateUtc; - private string _culture; - private string _url; + private string? _culture; + private string? _url; /// public int ContentId @@ -47,14 +47,14 @@ namespace Umbraco.Cms.Core.Models } /// - public string Culture + public string? Culture { get => _culture; set => SetPropertyValueAndDetectChanges(value, ref _culture, nameof(Culture)); } /// - public string Url + public string? Url { get => _url; set => SetPropertyValueAndDetectChanges(value, ref _url, nameof(Url)); diff --git a/src/Umbraco.Core/Models/Relation.cs b/src/Umbraco.Core/Models/Relation.cs index 26656593fd..54227db910 100644 --- a/src/Umbraco.Core/Models/Relation.cs +++ b/src/Umbraco.Core/Models/Relation.cs @@ -15,7 +15,7 @@ namespace Umbraco.Cms.Core.Models private int _parentId; private int _childId; private IRelationType _relationType; - private string _comment; + private string? _comment; /// /// Constructor for constructing the entity to be created @@ -81,14 +81,14 @@ namespace Umbraco.Cms.Core.Models public IRelationType RelationType { get => _relationType; - set => SetPropertyValueAndDetectChanges(value, ref _relationType, nameof(RelationType)); + set => SetPropertyValueAndDetectChanges(value, ref _relationType!, nameof(RelationType)); } /// /// Gets or sets a comment for the Relation /// [DataMember] - public string Comment + public string? Comment { get => _comment; set => SetPropertyValueAndDetectChanges(value, ref _comment, nameof(Comment)); diff --git a/src/Umbraco.Core/Models/RelationType.cs b/src/Umbraco.Core/Models/RelationType.cs index 2def0eb636..87c2084af7 100644 --- a/src/Umbraco.Core/Models/RelationType.cs +++ b/src/Umbraco.Core/Models/RelationType.cs @@ -43,7 +43,7 @@ namespace Umbraco.Cms.Core.Models public string Name { get => _name; - set => SetPropertyValueAndDetectChanges(value, ref _name, nameof(Name)); + set => SetPropertyValueAndDetectChanges(value, ref _name!, nameof(Name)); } /// @@ -53,7 +53,7 @@ namespace Umbraco.Cms.Core.Models public string Alias { get => _alias; - set => SetPropertyValueAndDetectChanges(value, ref _alias, nameof(Alias)); + set => SetPropertyValueAndDetectChanges(value, ref _alias!, nameof(Alias)); } /// diff --git a/src/Umbraco.Core/Models/Script.cs b/src/Umbraco.Core/Models/Script.cs index 3841be5598..9f1bad9e99 100644 --- a/src/Umbraco.Core/Models/Script.cs +++ b/src/Umbraco.Core/Models/Script.cs @@ -11,10 +11,10 @@ namespace Umbraco.Cms.Core.Models public class Script : File, IScript { public Script(string path) - : this(path, (Func) null) + : this(path, (Func?) null) { } - public Script(string path, Func getFileContent) + public Script(string path, Func? getFileContent) : base(path, getFileContent) { } diff --git a/src/Umbraco.Core/Models/ServerRegistration.cs b/src/Umbraco.Core/Models/ServerRegistration.cs index dae691812b..aa46bfbcf9 100644 --- a/src/Umbraco.Core/Models/ServerRegistration.cs +++ b/src/Umbraco.Core/Models/ServerRegistration.cs @@ -10,8 +10,8 @@ namespace Umbraco.Cms.Core.Models /// public class ServerRegistration : EntityBase, IServerRegistration { - private string _serverAddress; - private string _serverIdentity; + private string? _serverAddress; + private string? _serverIdentity; private bool _isActive; private bool _isSchedulingPublisher; @@ -61,7 +61,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets or sets the server URL. /// - public string ServerAddress + public string? ServerAddress { get => _serverAddress; set => SetPropertyValueAndDetectChanges(value, ref _serverAddress, nameof(ServerAddress)); @@ -70,7 +70,7 @@ namespace Umbraco.Cms.Core.Models /// /// Gets or sets the server unique identity. /// - public string ServerIdentity + public string? ServerIdentity { get => _serverIdentity; set => SetPropertyValueAndDetectChanges(value, ref _serverIdentity, nameof(ServerIdentity)); diff --git a/src/Umbraco.Core/Models/SimpleContentType.cs b/src/Umbraco.Core/Models/SimpleContentType.cs index 56ea073b91..31e061362c 100644 --- a/src/Umbraco.Core/Models/SimpleContentType.cs +++ b/src/Umbraco.Core/Models/SimpleContentType.cs @@ -53,21 +53,21 @@ namespace Umbraco.Cms.Core.Models public Guid Key { get; } /// - public ITemplate DefaultTemplate { get; } + public ITemplate? DefaultTemplate { get; } public ContentVariation Variations { get; } - public string Icon { get; } + public string? Icon { get; } public bool IsContainer { get; } - public string Name { get; } + public string? Name { get; } public bool AllowedAsRoot { get; } public bool IsElement { get; } - public bool SupportsPropertyVariation(string culture, string segment, bool wildcards = false) + public bool SupportsPropertyVariation(string? culture, string segment, bool wildcards = false) { // non-exact validation: can accept a 'null' culture if the property type varies // by culture, and likewise for segment @@ -80,7 +80,7 @@ namespace Umbraco.Cms.Core.Models return string.Equals(Alias, other.Alias) && 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/Models/Stylesheet.cs b/src/Umbraco.Core/Models/Stylesheet.cs index 6d796f66d7..1dc386f510 100644 --- a/src/Umbraco.Core/Models/Stylesheet.cs +++ b/src/Umbraco.Core/Models/Stylesheet.cs @@ -20,13 +20,13 @@ namespace Umbraco.Cms.Core.Models : this(path, null) { } - public Stylesheet(string path, Func getFileContent) + public Stylesheet(string path, Func? getFileContent) : base(string.IsNullOrEmpty(path) ? path : path.EnsureEndsWith(".css"), getFileContent) { InitializeProperties(); } - private Lazy> _properties; + private Lazy>? _properties; private void InitializeProperties() { @@ -85,17 +85,20 @@ namespace Umbraco.Cms.Core.Models /// /// /// - void Property_PropertyChanged(object sender, PropertyChangedEventArgs e) + void Property_PropertyChanged(object? sender, PropertyChangedEventArgs e) { - var prop = (StylesheetProperty) sender; + var prop = (StylesheetProperty?) sender; - //Ensure we are setting base.Content here so that the properties don't get reset and thus any event handlers would get reset too - base.Content = StylesheetHelper.ReplaceRule(Content, prop.Name, new StylesheetRule + if (prop is not null) { - Name = prop.Name, - Selector = prop.Alias, - Styles = prop.Value - }); + //Ensure we are setting base.Content here so that the properties don't get reset and thus any event handlers would get reset too + base.Content = StylesheetHelper.ReplaceRule(Content, prop.Name, new StylesheetRule + { + Name = prop.Name, + Selector = prop.Alias, + Styles = prop.Value + }); + } } /// @@ -121,9 +124,9 @@ namespace Umbraco.Cms.Core.Models /// /** umb_name: MyPropertyName */ p { font-size: 1em; } /// [IgnoreDataMember] - public IEnumerable Properties + public IEnumerable? Properties { - get { return _properties.Value; } + get { return _properties?.Value; } } /// @@ -132,7 +135,7 @@ namespace Umbraco.Cms.Core.Models /// public void AddProperty(IStylesheetProperty property) { - if (Properties.Any(x => x.Name.InvariantEquals(property.Name))) + if (Properties is not null && Properties.Any(x => x.Name.InvariantEquals(property.Name))) { throw new DuplicateNameException("The property with the name " + property.Name + " already exists in the collection"); } @@ -155,7 +158,7 @@ namespace Umbraco.Cms.Core.Models /// public void RemoveProperty(string name) { - if (Properties.Any(x => x.Name.InvariantEquals(name))) + if (Properties is not null && Properties.Any(x => x.Name.InvariantEquals(name))) { Content = StylesheetHelper.ReplaceRule(Content, name, null); } diff --git a/src/Umbraco.Core/Models/StylesheetProperty.cs b/src/Umbraco.Core/Models/StylesheetProperty.cs index 9a4ac93963..af6f347a63 100644 --- a/src/Umbraco.Core/Models/StylesheetProperty.cs +++ b/src/Umbraco.Core/Models/StylesheetProperty.cs @@ -35,7 +35,7 @@ namespace Umbraco.Cms.Core.Models public string Alias { get => _alias; - set => SetPropertyValueAndDetectChanges(value, ref _alias, nameof(Alias)); + set => SetPropertyValueAndDetectChanges(value, ref _alias!, nameof(Alias)); } /// @@ -44,7 +44,7 @@ namespace Umbraco.Cms.Core.Models public string Value { get => _value; - set => SetPropertyValueAndDetectChanges(value, ref _value, nameof(Value)); + set => SetPropertyValueAndDetectChanges(value, ref _value!, nameof(Value)); } } diff --git a/src/Umbraco.Core/Models/Tag.cs b/src/Umbraco.Core/Models/Tag.cs index 3d47b696d5..3c1e5eb13f 100644 --- a/src/Umbraco.Core/Models/Tag.cs +++ b/src/Umbraco.Core/Models/Tag.cs @@ -11,8 +11,8 @@ namespace Umbraco.Cms.Core.Models [DataContract(IsReference = true)] public class Tag : EntityBase, ITag { - private string _group; - private string _text; + private string? _group; + private string? _text; private int? _languageId; /// @@ -33,14 +33,14 @@ namespace Umbraco.Cms.Core.Models } /// - public string Group + public string? Group { get => _group; set => SetPropertyValueAndDetectChanges(value, ref _group, nameof(Group)); } /// - public string Text + public string? Text { get => _text; set => SetPropertyValueAndDetectChanges(value, ref _text, nameof(Text)); diff --git a/src/Umbraco.Core/Models/TagModel.cs b/src/Umbraco.Core/Models/TagModel.cs index 04b02cdbb8..6a0430a492 100644 --- a/src/Umbraco.Core/Models/TagModel.cs +++ b/src/Umbraco.Core/Models/TagModel.cs @@ -9,10 +9,10 @@ namespace Umbraco.Cms.Core.Models public int Id { get; set; } [DataMember(Name = "text", IsRequired = true)] - public string Text { get; set; } + public string? Text { get; set; } [DataMember(Name = "group")] - public string Group { get; set; } + public string? Group { get; set; } [DataMember(Name = "nodeCount")] public int NodeCount { get; set; } diff --git a/src/Umbraco.Core/Models/Template.cs b/src/Umbraco.Core/Models/Template.cs index bd90060ce7..d2029fa801 100644 --- a/src/Umbraco.Core/Models/Template.cs +++ b/src/Umbraco.Core/Models/Template.cs @@ -14,15 +14,15 @@ namespace Umbraco.Cms.Core.Models { private string _alias; private readonly IShortStringHelper _shortStringHelper; - private string _name; - private string _masterTemplateAlias; - private Lazy _masterTemplateId; + private string? _name; + private string? _masterTemplateAlias; + private Lazy? _masterTemplateId; - public Template(IShortStringHelper shortStringHelper, string name, string alias) + public Template(IShortStringHelper shortStringHelper, string? name, string alias) : this(shortStringHelper, name, alias, null) { } - public Template(IShortStringHelper shortStringHelper, string name, string alias, Func getFileContent) + public Template(IShortStringHelper shortStringHelper, string? name, string alias, Func? getFileContent) : base(string.Empty, getFileContent) { _shortStringHelper = shortStringHelper; @@ -32,20 +32,20 @@ namespace Umbraco.Cms.Core.Models } [DataMember] - public Lazy MasterTemplateId + public Lazy? MasterTemplateId { get => _masterTemplateId; set => SetPropertyValueAndDetectChanges(value, ref _masterTemplateId, nameof(MasterTemplateId)); } - public string MasterTemplateAlias + public string? MasterTemplateAlias { get => _masterTemplateAlias; set => SetPropertyValueAndDetectChanges(value, ref _masterTemplateAlias, nameof(MasterTemplateAlias)); } [DataMember] - public new string Name + public new string? Name { get => _name; set => SetPropertyValueAndDetectChanges(value, ref _name, nameof(Name)); @@ -55,7 +55,7 @@ namespace Umbraco.Cms.Core.Models public new string Alias { get => _alias; - set => SetPropertyValueAndDetectChanges(value.ToCleanString(_shortStringHelper, CleanStringType.UnderscoreAlias), ref _alias, nameof(Alias)); + set => SetPropertyValueAndDetectChanges(value.ToCleanString(_shortStringHelper, CleanStringType.UnderscoreAlias), ref _alias!, nameof(Alias)); } /// diff --git a/src/Umbraco.Core/Models/TemplateNode.cs b/src/Umbraco.Core/Models/TemplateNode.cs index cef3d4ea79..339f4efee3 100644 --- a/src/Umbraco.Core/Models/TemplateNode.cs +++ b/src/Umbraco.Core/Models/TemplateNode.cs @@ -29,6 +29,6 @@ namespace Umbraco.Cms.Core.Models /// /// Will be null if there is no parent /// - public TemplateNode Parent { get; set; } + public TemplateNode? Parent { get; set; } } } diff --git a/src/Umbraco.Core/Models/TemplateOnDisk.cs b/src/Umbraco.Core/Models/TemplateOnDisk.cs index 4ea450162c..61c10ba456 100644 --- a/src/Umbraco.Core/Models/TemplateOnDisk.cs +++ b/src/Umbraco.Core/Models/TemplateOnDisk.cs @@ -36,7 +36,7 @@ namespace Umbraco.Cms.Core.Models /// Setting the content means it is not "on disk" anymore, and the /// template becomes (and behaves like) a normal template. /// - public override string Content + public override string? Content { get { diff --git a/src/Umbraco.Core/Models/TemplateQuery/QueryCondition.cs b/src/Umbraco.Core/Models/TemplateQuery/QueryCondition.cs index c80c8c764c..b6305f16a8 100644 --- a/src/Umbraco.Core/Models/TemplateQuery/QueryCondition.cs +++ b/src/Umbraco.Core/Models/TemplateQuery/QueryCondition.cs @@ -2,8 +2,8 @@ { public class QueryCondition { - public PropertyModel Property { get; set; } - public OperatorTerm Term { get; set; } - public string ConstraintValue { get; set; } + public PropertyModel Property { get; set; } = new PropertyModel(); + public OperatorTerm Term { get; set; } = new OperatorTerm(); + public string ConstraintValue { get; set; } = string.Empty; } } diff --git a/src/Umbraco.Core/Models/TemplateQuery/QueryConditionExtensions.cs b/src/Umbraco.Core/Models/TemplateQuery/QueryConditionExtensions.cs index 2d000d4b2f..4edda6ad5d 100644 --- a/src/Umbraco.Core/Models/TemplateQuery/QueryConditionExtensions.cs +++ b/src/Umbraco.Core/Models/TemplateQuery/QueryConditionExtensions.cs @@ -8,7 +8,7 @@ namespace Umbraco.Extensions public static class QueryConditionExtensions { private static Lazy StringContainsMethodInfo => - new Lazy(() => typeof(string).GetMethod("Contains", new[] {typeof(string)})); + new Lazy(() => typeof(string).GetMethod("Contains", new[] {typeof(string)})!); public static Expression> BuildCondition(this QueryCondition condition, string parameterAlias) { diff --git a/src/Umbraco.Core/Models/Trees/ActionMenuItem.cs b/src/Umbraco.Core/Models/Trees/ActionMenuItem.cs index 2f05541c19..c89fb402d0 100644 --- a/src/Umbraco.Core/Models/Trees/ActionMenuItem.cs +++ b/src/Umbraco.Core/Models/Trees/ActionMenuItem.cs @@ -25,7 +25,7 @@ namespace Umbraco.Cms.Core.Models.Trees /// /// The angular service method name to call for this menu item /// - public virtual string AngularServiceMethodName { get; } = null; + public virtual string? AngularServiceMethodName { get; } = null; protected ActionMenuItem(string alias, string name) : base(alias, name) { diff --git a/src/Umbraco.Core/Models/Trees/MenuItem.cs b/src/Umbraco.Core/Models/Trees/MenuItem.cs index 8407530548..e56a2440a8 100644 --- a/src/Umbraco.Core/Models/Trees/MenuItem.cs +++ b/src/Umbraco.Core/Models/Trees/MenuItem.cs @@ -55,7 +55,7 @@ namespace Umbraco.Cms.Core.Models.Trees #region Properties [IgnoreDataMember] - public IAction Action { get; set; } + public IAction? Action { get; set; } /// /// A dictionary to support any additional meta data that should be rendered for the node which is @@ -70,14 +70,14 @@ namespace Umbraco.Cms.Core.Models.Trees [DataMember(Name = "name", IsRequired = true)] [Required] - public string Name { get; set; } + public string? Name { get; set; } [DataMember(Name = "alias", IsRequired = true)] [Required] - public string Alias { get; set; } + public string? Alias { get; set; } [DataMember(Name = "textDescription")] - public string TextDescription { get; set; } + public string? TextDescription { get; set; } /// /// Ensures a menu separator will exist before this menu item diff --git a/src/Umbraco.Core/Models/UserExtensions.cs b/src/Umbraco.Core/Models/UserExtensions.cs index aab9a5d8a7..b28033ed5c 100644 --- a/src/Umbraco.Core/Models/UserExtensions.cs +++ b/src/Umbraco.Core/Models/UserExtensions.cs @@ -38,7 +38,7 @@ namespace Umbraco.Cms.Core.Models if (user.Avatar.IsNullOrWhiteSpace()) { - var gravatarHash = user.Email.GenerateHash(); + var gravatarHash = user.Email?.GenerateHash(); var gravatarUrl = "https://www.gravatar.com/avatar/" + gravatarHash + "?d=404"; //try Gravatar @@ -147,13 +147,13 @@ namespace Umbraco.Cms.Core.Models /// /// Calculate start nodes, combining groups' and user's, and excluding what's in the bin /// - public static int[] CalculateContentStartNodeIds(this IUser user, IEntityService entityService, AppCaches appCaches) + public static int[]? CalculateContentStartNodeIds(this IUser user, IEntityService entityService, AppCaches appCaches) { var cacheKey = CacheKeys.UserAllContentStartNodesPrefix + user.Id; var runtimeCache = appCaches.IsolatedCaches.GetOrCreate(); var result = runtimeCache.GetCacheItem(cacheKey, () => { - var gsn = user.Groups.Where(x => x.StartContentId.HasValue).Select(x => x.StartContentId.Value).Distinct().ToArray(); + var gsn = user.Groups.Select(x => x.StartContentId).Distinct().ToArray(); var usn = user.StartContentIds; var vals = CombineStartNodes(UmbracoObjectTypes.Document, gsn, usn, entityService); return vals; @@ -169,7 +169,7 @@ namespace Umbraco.Cms.Core.Models /// /// /// - public static int[] CalculateMediaStartNodeIds(this IUser user, IEntityService entityService, AppCaches appCaches) + public static int[]? CalculateMediaStartNodeIds(this IUser user, IEntityService entityService, AppCaches appCaches) { var cacheKey = CacheKeys.UserAllMediaStartNodesPrefix + user.Id; var runtimeCache = appCaches.IsolatedCaches.GetOrCreate(); @@ -184,7 +184,7 @@ namespace Umbraco.Cms.Core.Models return result; } - public static string[] GetMediaStartNodePaths(this IUser user, IEntityService entityService, AppCaches appCaches) + public static string[]? GetMediaStartNodePaths(this IUser user, IEntityService entityService, AppCaches appCaches) { var cacheKey = CacheKeys.UserMediaStartNodePathsPrefix + user.Id; var runtimeCache = appCaches.IsolatedCaches.GetOrCreate(); @@ -198,7 +198,7 @@ namespace Umbraco.Cms.Core.Models return result; } - public static string[] GetContentStartNodePaths(this IUser user, IEntityService entityService, AppCaches appCaches) + public static string[]? GetContentStartNodePaths(this IUser user, IEntityService entityService, AppCaches appCaches) { var cacheKey = CacheKeys.UserContentStartNodePathsPrefix + user.Id; var runtimeCache = appCaches.IsolatedCaches.GetOrCreate(); diff --git a/src/Umbraco.Core/Models/UserTourStatus.cs b/src/Umbraco.Core/Models/UserTourStatus.cs index 6fe7b024d0..cc3b43dd0f 100644 --- a/src/Umbraco.Core/Models/UserTourStatus.cs +++ b/src/Umbraco.Core/Models/UserTourStatus.cs @@ -27,14 +27,14 @@ namespace Umbraco.Cms.Core.Models [DataMember(Name = "disabled")] public bool Disabled { get; set; } - public bool Equals(UserTourStatus other) + public bool Equals(UserTourStatus? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return string.Equals(Alias, other.Alias); } - 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/Net/ISessionIdResolver.cs b/src/Umbraco.Core/Net/ISessionIdResolver.cs index 580c04c8e2..f5d6b4de29 100644 --- a/src/Umbraco.Core/Net/ISessionIdResolver.cs +++ b/src/Umbraco.Core/Net/ISessionIdResolver.cs @@ -2,6 +2,6 @@ namespace Umbraco.Cms.Core.Net { public interface ISessionIdResolver { - string SessionId { get; } + string? SessionId { get; } } } diff --git a/src/Umbraco.Core/Net/NullSessionIdResolver.cs b/src/Umbraco.Core/Net/NullSessionIdResolver.cs index c7bd462aba..207a9c6048 100644 --- a/src/Umbraco.Core/Net/NullSessionIdResolver.cs +++ b/src/Umbraco.Core/Net/NullSessionIdResolver.cs @@ -2,6 +2,6 @@ { public class NullSessionIdResolver : ISessionIdResolver { - public string SessionId => null; + public string? SessionId => null; } } diff --git a/src/Umbraco.Core/Notifications/ContentNotificationExtensions.cs b/src/Umbraco.Core/Notifications/ContentNotificationExtensions.cs index 1b9464dcb4..c009b1cb62 100644 --- a/src/Umbraco.Core/Notifications/ContentNotificationExtensions.cs +++ b/src/Umbraco.Core/Notifications/ContentNotificationExtensions.cs @@ -11,7 +11,7 @@ namespace Umbraco.Cms.Core.Notifications /// Determines whether a culture is being saved, during a Saving notification /// public static bool IsSavingCulture(this SavingNotification notification, T content, string culture) where T : IContentBase - => content.CultureInfos.TryGetValue(culture, out ContentCultureInfos cultureInfo) && cultureInfo.IsDirty(); + => (content.CultureInfos?.TryGetValue(culture, out ContentCultureInfos cultureInfo) ?? false) && cultureInfo.IsDirty(); /// /// Determines whether a culture has been saved, during a Saved notification @@ -59,7 +59,7 @@ namespace Umbraco.Cms.Core.Notifications => content.IsPropertyDirty(ContentBase.ChangeTrackingPrefix.UnpublishedCulture + culture); public static bool IsPublishingCulture(IContent content, string culture) - => content.PublishCultureInfos.TryGetValue(culture, out ContentCultureInfos cultureInfo) && cultureInfo.IsDirty(); + => (content.PublishCultureInfos?.TryGetValue(culture, out ContentCultureInfos cultureInfo) ?? false) && cultureInfo.IsDirty(); public static bool HasUnpublishedCulture(IContent content, string culture) => content.WasPropertyDirty(ContentBase.ChangeTrackingPrefix.UnpublishedCulture + culture); diff --git a/src/Umbraco.Core/Notifications/StatefulNotification.cs b/src/Umbraco.Core/Notifications/StatefulNotification.cs index cf01b86e58..940e8ac45f 100644 --- a/src/Umbraco.Core/Notifications/StatefulNotification.cs +++ b/src/Umbraco.Core/Notifications/StatefulNotification.cs @@ -6,7 +6,7 @@ namespace Umbraco.Cms.Core.Notifications { public abstract class StatefulNotification : IStatefulNotification { - private IDictionary _state; + private IDictionary? _state; /// /// This can be used by event subscribers to store state in the notification so they easily deal with custom state data between diff --git a/src/Umbraco.Core/Notifications/TemplateSavedNotification.cs b/src/Umbraco.Core/Notifications/TemplateSavedNotification.cs index 7cfbd8a7bb..ae07680f34 100644 --- a/src/Umbraco.Core/Notifications/TemplateSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/TemplateSavedNotification.cs @@ -36,14 +36,21 @@ namespace Umbraco.Cms.Core.Notifications set => State[s_templateForContentTypeKey] = value; } - public string ContentTypeAlias + public string? ContentTypeAlias { get { State.TryGetValue(s_contentTypeAliasKey, out var result); return result as string; } - set => State[s_contentTypeAliasKey] = value; + + set + { + if (value is not null) + { + State[s_contentTypeAliasKey] = value; + } + } } } } diff --git a/src/Umbraco.Core/Notifications/TemplateSavingNotification.cs b/src/Umbraco.Core/Notifications/TemplateSavingNotification.cs index 95023441d7..b06a3f581a 100644 --- a/src/Umbraco.Core/Notifications/TemplateSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/TemplateSavingNotification.cs @@ -51,14 +51,21 @@ namespace Umbraco.Cms.Core.Notifications set => State[s_templateForContentTypeKey] = value; } - public string ContentTypeAlias + public string? ContentTypeAlias { get { State.TryGetValue(s_contentTypeAliasKey, out var result); return result as string; } - set => State[s_contentTypeAliasKey] = value; + + set + { + if (value is not null) + { + State[s_contentTypeAliasKey] = value; + } + } } } } diff --git a/src/Umbraco.Core/Notifications/UserLogoutSuccessNotification.cs b/src/Umbraco.Core/Notifications/UserLogoutSuccessNotification.cs index cc6a2f819b..e8d4693852 100644 --- a/src/Umbraco.Core/Notifications/UserLogoutSuccessNotification.cs +++ b/src/Umbraco.Core/Notifications/UserLogoutSuccessNotification.cs @@ -6,6 +6,6 @@ namespace Umbraco.Cms.Core.Notifications { } - public string SignOutRedirectUrl { get; set; } + public string? SignOutRedirectUrl { get; set; } } } diff --git a/src/Umbraco.Core/Packaging/ConflictingPackageData.cs b/src/Umbraco.Core/Packaging/ConflictingPackageData.cs index 0d71b9f70e..4824917d7c 100644 --- a/src/Umbraco.Core/Packaging/ConflictingPackageData.cs +++ b/src/Umbraco.Core/Packaging/ConflictingPackageData.cs @@ -18,9 +18,9 @@ namespace Umbraco.Cms.Core.Packaging _macroService = macroService ?? throw new ArgumentNullException(nameof(macroService)); } - public IEnumerable FindConflictingStylesheets(IEnumerable stylesheetNodes) + public IEnumerable? FindConflictingStylesheets(IEnumerable? stylesheetNodes) { - return stylesheetNodes + return stylesheetNodes? .Select(n => { var xElement = n.Element("Name") ?? n.Element("name"); @@ -32,9 +32,9 @@ namespace Umbraco.Cms.Core.Packaging .Where(v => v != null); } - public IEnumerable FindConflictingTemplates(IEnumerable templateNodes) + public IEnumerable? FindConflictingTemplates(IEnumerable? templateNodes) { - return templateNodes + return templateNodes? .Select(n => { var xElement = n.Element("Alias") ?? n.Element("alias"); @@ -46,9 +46,9 @@ namespace Umbraco.Cms.Core.Packaging .Where(v => v != null); } - public IEnumerable FindConflictingMacros(IEnumerable macroNodes) + public IEnumerable? FindConflictingMacros(IEnumerable? macroNodes) { - return macroNodes + return macroNodes? .Select(n => { var xElement = n.Element("alias") ?? n.Element("Alias"); diff --git a/src/Umbraco.Core/Packaging/IPackageDefinitionRepository.cs b/src/Umbraco.Core/Packaging/IPackageDefinitionRepository.cs index c074a45ae1..fe015006a8 100644 --- a/src/Umbraco.Core/Packaging/IPackageDefinitionRepository.cs +++ b/src/Umbraco.Core/Packaging/IPackageDefinitionRepository.cs @@ -7,8 +7,8 @@ namespace Umbraco.Cms.Core.Packaging /// public interface IPackageDefinitionRepository { - IEnumerable GetAll(); - PackageDefinition GetById(int id); + IEnumerable GetAll(); + PackageDefinition? GetById(int id); void Delete(int id); /// diff --git a/src/Umbraco.Core/Packaging/InstallationSummary.cs b/src/Umbraco.Core/Packaging/InstallationSummary.cs index 42ac9f7ef0..618853731d 100644 --- a/src/Umbraco.Core/Packaging/InstallationSummary.cs +++ b/src/Umbraco.Core/Packaging/InstallationSummary.cs @@ -38,7 +38,7 @@ namespace Umbraco.Cms.Core.Packaging { var sb = new StringBuilder(); - void WriteConflicts(IEnumerable source, Func selector, string message, bool appendLine = true) + void WriteConflicts(IEnumerable? source, Func selector, string message, bool appendLine = true) { var result = source?.Select(selector).ToList(); if (result?.Count > 0) diff --git a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs index 7cca061401..df5375ad92 100644 --- a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs +++ b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs @@ -16,7 +16,7 @@ namespace Umbraco.Cms.Core.Packaging private static readonly IList s_emptyGuidUdiList = new List(); - public PackageDefinition ToPackageDefinition(XElement xml) + public PackageDefinition? ToPackageDefinition(XElement xml) { if (xml == null) { diff --git a/src/Umbraco.Core/Packaging/PackageMigrationResource.cs b/src/Umbraco.Core/Packaging/PackageMigrationResource.cs index b9c0e99552..b972a2cf08 100644 --- a/src/Umbraco.Core/Packaging/PackageMigrationResource.cs +++ b/src/Umbraco.Core/Packaging/PackageMigrationResource.cs @@ -12,19 +12,19 @@ namespace Umbraco.Cms.Core.Packaging { public static class PackageMigrationResource { - private static Stream GetEmbeddedPackageZipStream(Type planType) + private static Stream? GetEmbeddedPackageZipStream(Type planType) { // lookup the embedded resource by convention Assembly currentAssembly = planType.Assembly; var fileName = $"{planType.Namespace}.package.zip"; - Stream stream = currentAssembly.GetManifestResourceStream(fileName); + Stream? stream = currentAssembly.GetManifestResourceStream(fileName); return stream; } - public static XDocument GetEmbeddedPackageDataManifest(Type planType, out ZipArchive zipArchive) + public static XDocument? GetEmbeddedPackageDataManifest(Type planType, out ZipArchive? zipArchive) { - XDocument packageXml; + XDocument? packageXml; var zipStream = GetEmbeddedPackageZipStream(planType); if (zipStream is not null) { @@ -37,17 +37,17 @@ namespace Umbraco.Cms.Core.Packaging return packageXml; } - public static XDocument GetEmbeddedPackageDataManifest(Type planType) + public static XDocument? GetEmbeddedPackageDataManifest(Type planType) { return GetEmbeddedPackageDataManifest(planType, out _); } - private static XDocument GetEmbeddedPackageXmlDoc(Type planType) + private static XDocument? GetEmbeddedPackageXmlDoc(Type planType) { // lookup the embedded resource by convention Assembly currentAssembly = planType.Assembly; var fileName = $"{planType.Namespace}.package.xml"; - Stream stream = currentAssembly.GetManifestResourceStream(fileName); + Stream? stream = currentAssembly.GetManifestResourceStream(fileName); if (stream == null) { return null; @@ -67,7 +67,7 @@ namespace Umbraco.Cms.Core.Packaging // But it is still very fast ~303ms for a 100MB file. This will only be an issue if there are // several very large package.zips. - using Stream stream = GetEmbeddedPackageZipStream(planType); + using Stream? stream = GetEmbeddedPackageZipStream(planType); if (stream is not null) { @@ -84,7 +84,7 @@ namespace Umbraco.Cms.Core.Packaging throw new IOException("Missing embedded files for planType: " + planType); } - public static bool TryGetEmbeddedPackageDataManifest(Type planType, out XDocument packageXml, out ZipArchive zipArchive) + public static bool TryGetEmbeddedPackageDataManifest(Type planType, out XDocument? packageXml, out ZipArchive? zipArchive) { var zipStream = GetEmbeddedPackageZipStream(planType); if (zipStream is not null) @@ -106,7 +106,7 @@ namespace Umbraco.Cms.Core.Packaging } var zip = new ZipArchive(packageZipStream, ZipArchiveMode.Read); - ZipArchiveEntry packageXmlEntry = zip.GetEntry("package.xml"); + ZipArchiveEntry? packageXmlEntry = zip.GetEntry("package.xml"); if (packageXmlEntry == null) { throw new InvalidOperationException("Zip package does not contain the required package.xml file"); diff --git a/src/Umbraco.Core/Packaging/PackagesRepository.cs b/src/Umbraco.Core/Packaging/PackagesRepository.cs index 2b169f3603..ca862c23de 100644 --- a/src/Umbraco.Core/Packaging/PackagesRepository.cs +++ b/src/Umbraco.Core/Packaging/PackagesRepository.cs @@ -74,9 +74,9 @@ namespace Umbraco.Cms.Core.Packaging MediaFileManager mediaFileManager, FileSystems fileSystems, string packageRepositoryFileName, - string tempFolderPath = null, - string packagesFolderPath = null, - string mediaFolderPath = null) + string? tempFolderPath = null, + string? packagesFolderPath = null, + string? mediaFolderPath = null) { if (string.IsNullOrWhiteSpace(packageRepositoryFileName)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(packageRepositoryFileName)); @@ -103,7 +103,7 @@ namespace Umbraco.Cms.Core.Packaging private string CreatedPackagesFile => _packagesFolderPath.EnsureEndsWith('/') + _packageRepositoryFileName; - public IEnumerable GetAll() + public IEnumerable GetAll() { var packagesXml = EnsureStorage(out _); if (packagesXml?.Root == null) @@ -113,7 +113,7 @@ namespace Umbraco.Cms.Core.Packaging yield return _parser.ToPackageDefinition(packageXml); } - public PackageDefinition GetById(int id) + public PackageDefinition? GetById(int id) { var packagesXml = EnsureStorage(out var packageFile); var packageXml = packagesXml?.Root?.Elements("package").FirstOrDefault(x => x.AttributeValue("id") == id); @@ -129,7 +129,7 @@ namespace Umbraco.Cms.Core.Packaging packageXml.Remove(); - packagesXml.Save(packagesFile); + packagesXml?.Save(packagesFile); } public bool SavePackage(PackageDefinition definition) @@ -403,7 +403,7 @@ namespace Umbraco.Cms.Core.Packaging continue; } - XElement macroXml = GetMacroXml(outInt, out IMacro macro); + XElement? macroXml = GetMacroXml(outInt, out IMacro macro); if (macroXml == null) { continue; @@ -416,8 +416,8 @@ namespace Umbraco.Cms.Core.Packaging root.Add(macros); // Get the partial views for macros and package those (exclude views outside of the default directory, e.g. App_Plugins\*\Views) - IEnumerable views = packagedMacros.Where(x => x.MacroSource.StartsWith(Constants.SystemDirectories.MacroPartials)) - .Select(x => x.MacroSource.Substring(Constants.SystemDirectories.MacroPartials.Length).Replace('/', '\\')); + IEnumerable views = packagedMacros.Where(x => x.MacroSource is not null).Where(x => x.MacroSource!.StartsWith(Constants.SystemDirectories.MacroPartials)) + .Select(x => x.MacroSource!.Substring(Constants.SystemDirectories.MacroPartials.Length).Replace('/', '\\')); PackageStaticFiles(views, root, "MacroPartialViews", "View", _fileSystems.MacroPartialsFileSystem); } @@ -431,8 +431,8 @@ namespace Umbraco.Cms.Core.Packaging continue; } - XElement xml = GetStylesheetXml(stylesheet, true); - if (xml != null) + XElement? xml = GetStylesheetXml(stylesheet, true); + if (xml is not null) { stylesheetsXml.Add(xml); } @@ -445,7 +445,7 @@ namespace Umbraco.Cms.Core.Packaging XContainer root, string containerName, string elementName, - IFileSystem fileSystem) + IFileSystem? fileSystem) { var scriptsXml = new XElement(containerName); foreach (var file in filePaths) @@ -455,20 +455,25 @@ namespace Umbraco.Cms.Core.Packaging continue; } - if (!fileSystem.FileExists(file)) + if (!fileSystem?.FileExists(file) ?? false) { throw new InvalidOperationException("No file found with path " + file); } - using (Stream stream = fileSystem.OpenFile(file)) - using (var reader = new StreamReader(stream)) + using (Stream? stream = fileSystem?.OpenFile(file)) { - var fileContents = reader.ReadToEnd(); - scriptsXml.Add( - new XElement( - elementName, - new XAttribute("path", file), - new XCData(fileContents))); + if (stream is not null) + { + using (var reader = new StreamReader(stream)) + { + var fileContents = reader.ReadToEnd(); + scriptsXml.Add( + new XElement( + elementName, + new XAttribute("path", file), + new XCData(fileContents))); + } + } } } root.Add(scriptsXml); @@ -622,8 +627,8 @@ namespace Umbraco.Cms.Core.Packaging // get the media file path and store that separately in the XML. // the media file path is different from the URL and is specifically // extracted using the property editor for this media file and the current media file system. - Stream mediaStream = _mediaFileManager.GetFile(media, out var mediaFilePath); - if (mediaStream != null) + Stream? mediaStream = _mediaFileManager.GetFile(media, out var mediaFilePath); + if (mediaStream != null && mediaFilePath is not null) { xmlMedia.Add(new XAttribute("mediaFilePath", mediaFilePath)); @@ -653,7 +658,7 @@ namespace Umbraco.Cms.Core.Packaging // TODO: Delete this /// - private XElement GetMacroXml(int macroId, out IMacro macro) + private XElement? GetMacroXml(int macroId, out IMacro macro) { macro = _macroService.GetById(macroId); if (macro == null) @@ -668,7 +673,7 @@ namespace Umbraco.Cms.Core.Packaging /// The path of the stylesheet. /// if set to true [include properties]. /// - private XElement GetStylesheetXml(string path, bool includeProperties) + private XElement? GetStylesheetXml(string path, bool includeProperties) { if (string.IsNullOrWhiteSpace(path)) { diff --git a/src/Umbraco.Core/Persistence/Repositories/ITagRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ITagRepository.cs index 5e68f68f75..d9794ed1bd 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ITagRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ITagRepository.cs @@ -63,32 +63,32 @@ namespace Umbraco.Cms.Core.Persistence.Repositories /// /// Gets all entities of a type, tagged with the specified tag. /// - IEnumerable GetTaggedEntitiesByTag(TaggableObjectTypes objectType, string tag, string group = null, string? culture = null); + IEnumerable GetTaggedEntitiesByTag(TaggableObjectTypes objectType, string tag, string? group = null, string? culture = null); /// /// Gets all tags for an entity type. /// - IEnumerable GetTagsForEntityType(TaggableObjectTypes objectType, string group = null, string? culture = null); + IEnumerable GetTagsForEntityType(TaggableObjectTypes objectType, string? group = null, string? culture = null); /// /// Gets all tags attached to an entity. /// - IEnumerable GetTagsForEntity(int contentId, string group = null, string? culture = null); + IEnumerable GetTagsForEntity(int contentId, string? group = null, string? culture = null); /// /// Gets all tags attached to an entity. /// - IEnumerable GetTagsForEntity(Guid contentId, string group = null, string? culture = null); + IEnumerable GetTagsForEntity(Guid contentId, string? group = null, string? culture = null); /// /// Gets all tags attached to an entity via a property. /// - IEnumerable GetTagsForProperty(int contentId, string propertyTypeAlias, string group = null, string? culture = null); + IEnumerable GetTagsForProperty(int contentId, string propertyTypeAlias, string? group = null, string? culture = null); /// /// Gets all tags attached to an entity via a property. /// - IEnumerable GetTagsForProperty(Guid contentId, string propertyTypeAlias, string group = null, string? culture = null); + IEnumerable GetTagsForProperty(Guid contentId, string propertyTypeAlias, string? group = null, string? culture = null); #endregion } diff --git a/src/Umbraco.Core/Persistence/Repositories/IUserRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IUserRepository.cs index 799cb01963..2d77efa5ee 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IUserRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IUserRepository.cs @@ -70,8 +70,8 @@ namespace Umbraco.Cms.Core.Persistence.Repositories /// IEnumerable GetPagedResultsByQuery(IQuery query, long pageIndex, int pageSize, out long totalRecords, Expression> orderBy, Direction orderDirection = Direction.Ascending, - string[] includeUserGroups = null, string[] excludeUserGroups = null, UserState[] userState = null, - IQuery filter = null); + string[]? includeUserGroups = null, string[]? excludeUserGroups = null, UserState[]? userState = null, + IQuery? filter = null); /// /// Returns a user by username diff --git a/src/Umbraco.Core/Persistence/Repositories/RepositoryCacheKeys.cs b/src/Umbraco.Core/Persistence/Repositories/RepositoryCacheKeys.cs index 7e89c7c125..db0ebd7be5 100644 --- a/src/Umbraco.Core/Persistence/Repositories/RepositoryCacheKeys.cs +++ b/src/Umbraco.Core/Persistence/Repositories/RepositoryCacheKeys.cs @@ -30,7 +30,7 @@ namespace Umbraco.Cms.Core.Persistence.Repositories } else { - return GetKey() + id?.ToString().ToUpperInvariant(); + return GetKey() + id?.ToString()?.ToUpperInvariant(); } } } diff --git a/src/Umbraco.Core/Persistence/SqlExtensionsStatics.cs b/src/Umbraco.Core/Persistence/SqlExtensionsStatics.cs index 71df9a362e..ef20e93282 100644 --- a/src/Umbraco.Core/Persistence/SqlExtensionsStatics.cs +++ b/src/Umbraco.Core/Persistence/SqlExtensionsStatics.cs @@ -23,7 +23,7 @@ namespace Umbraco.Cms.Core.Persistence /// /// The name of the field. /// A function producing Sql text. - public static T SqlText(string field, Func expr) => default; + public static T? SqlText(string field, Func expr) => default; /// /// Produces Sql text. @@ -31,7 +31,7 @@ namespace Umbraco.Cms.Core.Persistence /// The name of the first field. /// The name of the second field. /// A function producing Sql text. - public static T SqlText(string field1, string field2, Func expr) => default; + public static T? SqlText(string field1, string field2, Func expr) => default; /// /// Produces Sql text. @@ -40,6 +40,6 @@ namespace Umbraco.Cms.Core.Persistence /// The name of the second field. /// The name of the third field. /// A function producing Sql text. - public static T SqlText(string field1, string field2, string field3, Func expr) => default; + public static T? SqlText(string field1, string field2, string field3, Func expr) => default; } } diff --git a/src/Umbraco.Core/PropertyEditors/IConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/IConfigurationEditor.cs index 4144c7c0a8..b1acfc3e44 100644 --- a/src/Umbraco.Core/PropertyEditors/IConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/IConfigurationEditor.cs @@ -52,7 +52,7 @@ namespace Umbraco.Cms.Core.PropertyEditors /// /// Converting the configuration object to the serialized database value is /// achieved by simply serializing the configuration. See . - object FromDatabase(string configurationJson, IConfigurationEditorJsonSerializer configurationEditorJsonSerializer); + object FromDatabase(string? configurationJson, IConfigurationEditorJsonSerializer configurationEditorJsonSerializer); /// /// Converts the values posted by the configuration editor into the actual configuration object. @@ -65,12 +65,12 @@ namespace Umbraco.Cms.Core.PropertyEditors /// Converts the configuration object to values for the configuration editor. /// /// The configuration. - IDictionary ToConfigurationEditor(object configuration); + IDictionary ToConfigurationEditor(object? configuration); /// /// Converts the configuration object to values for the value editor. /// /// The configuration. - IDictionary ToValueEditor(object configuration); + IDictionary ToValueEditor(object? configuration); } } diff --git a/src/Umbraco.Core/PropertyEditors/IDataEditor.cs b/src/Umbraco.Core/PropertyEditors/IDataEditor.cs index e632172990..403bf4ffeb 100644 --- a/src/Umbraco.Core/PropertyEditors/IDataEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/IDataEditor.cs @@ -52,7 +52,7 @@ namespace Umbraco.Cms.Core.PropertyEditors /// /// Gets a configured value editor. /// - IDataValueEditor GetValueEditor(object configuration); + IDataValueEditor GetValueEditor(object? configuration); /// /// Gets the configuration for the value editor. diff --git a/src/Umbraco.Core/Routing/IPublishedUrlProvider.cs b/src/Umbraco.Core/Routing/IPublishedUrlProvider.cs index 78d8f4024a..861fd63028 100644 --- a/src/Umbraco.Core/Routing/IPublishedUrlProvider.cs +++ b/src/Umbraco.Core/Routing/IPublishedUrlProvider.cs @@ -47,7 +47,7 @@ namespace Umbraco.Cms.Core.Routing /// string GetUrl(IPublishedContent content, UrlMode mode = UrlMode.Default, string? culture = null, Uri current = null); - string GetUrlFromRoute(int id, string route, string culture); + string GetUrlFromRoute(int id, string? route, string? culture); /// /// Gets the other urls of a published content. diff --git a/src/Umbraco.Core/Runtime/IMainDom.cs b/src/Umbraco.Core/Runtime/IMainDom.cs index f08b9f3436..65c64857b3 100644 --- a/src/Umbraco.Core/Runtime/IMainDom.cs +++ b/src/Umbraco.Core/Runtime/IMainDom.cs @@ -34,6 +34,6 @@ namespace Umbraco.Cms.Core.Runtime /// A value indicating whether it was possible to register. /// If registering is successful, then the action /// is guaranteed to execute before the AppDomain releases the main domain status. - bool Register(Action install = null, Action release = null, int weight = 100); + bool Register(Action? install = null, Action? release = null, int weight = 100); } } diff --git a/src/Umbraco.Core/Scoping/IScopeContext.cs b/src/Umbraco.Core/Scoping/IScopeContext.cs index aef8757e9e..1814486c0e 100644 --- a/src/Umbraco.Core/Scoping/IScopeContext.cs +++ b/src/Umbraco.Core/Scoping/IScopeContext.cs @@ -37,7 +37,7 @@ namespace Umbraco.Cms.Core.Scoping /// and action with the same key but only the first one is used, the others are ignored. /// The action boolean parameter indicates whether the scope completed or not. /// - T Enlist(string key, Func creator, Action action = null, int priority = 100); + T Enlist(string key, Func creator, Action? action = null, int priority = 100); /// /// Gets an enlisted object. diff --git a/src/Umbraco.Core/Security/ContentPermissions.cs b/src/Umbraco.Core/Security/ContentPermissions.cs index 206422b6e1..273fb40377 100644 --- a/src/Umbraco.Core/Security/ContentPermissions.cs +++ b/src/Umbraco.Core/Security/ContentPermissions.cs @@ -197,7 +197,7 @@ namespace Umbraco.Cms.Core.Security : ContentAccess.Denied; } - private bool CheckPermissionsPath(string path, IUser user, IReadOnlyList permissionsToCheck = null) + private bool CheckPermissionsPath(string? path, IUser user, IReadOnlyList permissionsToCheck = null) { if (permissionsToCheck == null) { @@ -220,12 +220,12 @@ namespace Umbraco.Cms.Core.Security return allowed; } - public static bool HasPathAccess(string path, int[] startNodeIds, int recycleBinId) + public static bool HasPathAccess(string? path, int[]? startNodeIds, int recycleBinId) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(path)); // check for no access - if (startNodeIds.Length == 0) + if (startNodeIds is null || startNodeIds.Length == 0) return false; // check for root access diff --git a/src/Umbraco.Core/Serialization/IJsonSerializer.cs b/src/Umbraco.Core/Serialization/IJsonSerializer.cs index fe1abcc044..ef2e712b9a 100644 --- a/src/Umbraco.Core/Serialization/IJsonSerializer.cs +++ b/src/Umbraco.Core/Serialization/IJsonSerializer.cs @@ -2,7 +2,7 @@ { public interface IJsonSerializer { - string Serialize(object input); + string Serialize(object? input); T Deserialize(string input); diff --git a/src/Umbraco.Core/Services/IEntityService.cs b/src/Umbraco.Core/Services/IEntityService.cs index 5992196c69..ff4b2cd301 100644 --- a/src/Umbraco.Core/Services/IEntityService.cs +++ b/src/Umbraco.Core/Services/IEntityService.cs @@ -234,7 +234,7 @@ namespace Umbraco.Cms.Core.Services /// /// Gets paths for entities. /// - IEnumerable GetAllPaths(UmbracoObjectTypes objectType, params int[] ids); + IEnumerable GetAllPaths(UmbracoObjectTypes objectType, params int[]? ids); /// /// Gets paths for entities. diff --git a/src/Umbraco.Core/Services/ILocalizedTextService.cs b/src/Umbraco.Core/Services/ILocalizedTextService.cs index d3cb837ff7..53028ec272 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/IMembershipRoleService.cs b/src/Umbraco.Core/Services/IMembershipRoleService.cs index be7c75c766..682b02727b 100644 --- a/src/Umbraco.Core/Services/IMembershipRoleService.cs +++ b/src/Umbraco.Core/Services/IMembershipRoleService.cs @@ -5,7 +5,7 @@ using Umbraco.Cms.Core.Persistence.Querying; namespace Umbraco.Cms.Core.Services { - public interface IMembershipRoleService + public interface IMembershipRoleService where T : class, IMembershipUser { void AddRole(string roleName); @@ -14,7 +14,7 @@ namespace Umbraco.Cms.Core.Services IEnumerable GetAllRoles(int memberId); - IEnumerable GetAllRoles(string username); + IEnumerable GetAllRoles(string? username); IEnumerable GetAllRolesIds(); diff --git a/src/Umbraco.Core/Services/IUserService.cs b/src/Umbraco.Core/Services/IUserService.cs index 25ce49b65d..2e1c0ffca3 100644 --- a/src/Umbraco.Core/Services/IUserService.cs +++ b/src/Umbraco.Core/Services/IUserService.cs @@ -157,7 +157,7 @@ namespace Umbraco.Cms.Core.Services /// /// User to check permissions for /// Path to check permissions for - EntityPermissionSet GetPermissionsForPath(IUser user, string path); + EntityPermissionSet GetPermissionsForPath(IUser user, string? path); /// /// Gets the permissions for the provided groups and path diff --git a/src/Umbraco.Core/Services/LocalizedTextServiceExtensions.cs b/src/Umbraco.Core/Services/LocalizedTextServiceExtensions.cs index b341757946..1f56ab8c22 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); /// @@ -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 8a1d007be8..d8a7f201de 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; @@ -33,7 +33,7 @@ namespace Umbraco.Extensions foreach (var roleRule in roleRules) { //a rule is being updated so flag this entry to be saved - roleRule.RuleValue = newRolename; + roleRule.RuleValue = newRolename ?? String.Empty; save = true; } if (save) diff --git a/src/Umbraco.Core/Strings/Css/StylesheetHelper.cs b/src/Umbraco.Core/Strings/Css/StylesheetHelper.cs index 51dffe5ab9..b540f3683a 100644 --- a/src/Umbraco.Core/Strings/Css/StylesheetHelper.cs +++ b/src/Umbraco.Core/Strings/Css/StylesheetHelper.cs @@ -10,34 +10,38 @@ namespace Umbraco.Cms.Core.Strings.Css { private const string RuleRegexFormat = @"/\*\*\s*umb_name:\s*(?{0}?)\s*\*/\s*(?[^,{{]*?)\s*{{\s*(?.*?)\s*}}"; - public static IEnumerable ParseRules(string input) + public static IEnumerable ParseRules(string? input) { var rules = new List(); var ruleRegex = new Regex(string.Format(RuleRegexFormat, @"[^\*\r\n]*"), RegexOptions.IgnoreCase | RegexOptions.Singleline); - var contents = input; - var ruleMatches = ruleRegex.Matches(contents); - - foreach (Match match in ruleMatches) + if (input is not null) { - var name = match.Groups["Name"].Value; + var contents = input; + var ruleMatches = ruleRegex.Matches(contents); - //If this name already exists, only use the first one - if (rules.Any(x => x.Name == name)) continue; - - rules.Add(new StylesheetRule + foreach (Match match in ruleMatches) { - Name = match.Groups["Name"].Value, - Selector = match.Groups["Selector"].Value, - // Only match first selector when chained together - Styles = string.Join(Environment.NewLine, match.Groups["Styles"].Value.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None).Select(x => x.Trim()).ToArray()) - }); + var name = match.Groups["Name"].Value; + + //If this name already exists, only use the first one + if (rules.Any(x => x.Name == name)) continue; + + rules.Add(new StylesheetRule + { + Name = match.Groups["Name"].Value, + Selector = match.Groups["Selector"].Value, + // Only match first selector when chained together + Styles = string.Join(Environment.NewLine, match.Groups["Styles"].Value.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None).Select(x => x.Trim()).ToArray()) + }); + } } + return rules; } - public static string ReplaceRule(string input, string oldRuleName, StylesheetRule rule) + public static string ReplaceRule(string input, string oldRuleName, StylesheetRule? rule) { var contents = input; var ruleRegex = new Regex(string.Format(RuleRegexFormat, oldRuleName.EscapeRegexSpecialCharacters()), RegexOptions.IgnoreCase | RegexOptions.Singleline); diff --git a/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs b/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs index 558e1af75c..dec59d3699 100644 --- a/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs +++ b/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs @@ -116,7 +116,7 @@ namespace Umbraco.Cms.Core.Strings /// /// Url segments are Ascii only (no accents...). /// - public virtual string CleanStringForUrlSegment(string text, string culture) + public virtual string CleanStringForUrlSegment(string text, string? culture) { return CleanString(text, CleanStringType.UrlSegment, culture); } @@ -217,7 +217,7 @@ namespace Umbraco.Cms.Core.Strings /// strings are cleaned up to camelCase and Ascii. /// The culture. /// The clean string. - public string CleanString(string text, CleanStringType stringType, string culture) + public string CleanString(string text, CleanStringType stringType, string? culture) { return CleanString(text, stringType, culture, null); } @@ -236,7 +236,7 @@ namespace Umbraco.Cms.Core.Strings return CleanString(text, stringType, culture, separator); } - protected virtual string CleanString(string text, CleanStringType stringType, string culture, char? separator) + protected virtual string CleanString(string text, CleanStringType stringType, string? culture, char? separator) { // be safe if (text == null) throw new ArgumentNullException(nameof(text)); diff --git a/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs b/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs index cf5e71a568..ebdd86a835 100644 --- a/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs +++ b/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs @@ -30,7 +30,7 @@ namespace Umbraco.Cms.Core.Strings public string DefaultCulture { get; set; } = ""; // invariant - public Dictionary UrlReplaceCharacters { get; set; } + public Dictionary? UrlReplaceCharacters { get; set; } public DefaultShortStringHelperConfig WithConfig(Config config) { @@ -165,8 +165,8 @@ namespace Umbraco.Cms.Core.Strings }; } - public Func PreFilter { get; set; } - public Func PostFilter { get; set; } + public Func? PreFilter { get; set; } + public Func? PostFilter { get; set; } public Func IsTerm { get; set; } public CleanStringType StringType { get; set; } diff --git a/src/Umbraco.Core/Strings/DefaultUrlSegmentProvider.cs b/src/Umbraco.Core/Strings/DefaultUrlSegmentProvider.cs index f908856e38..22b8a40c0e 100644 --- a/src/Umbraco.Core/Strings/DefaultUrlSegmentProvider.cs +++ b/src/Umbraco.Core/Strings/DefaultUrlSegmentProvider.cs @@ -21,14 +21,14 @@ namespace Umbraco.Cms.Core.Strings /// The content. /// The culture. /// The URL segment. - public string GetUrlSegment(IContentBase content, string? culture = null) + public string? GetUrlSegment(IContentBase content, string? culture = null) { - return GetUrlSegmentSource(content, culture).ToUrlSegment(_shortStringHelper, culture); + return GetUrlSegmentSource(content, culture)?.ToUrlSegment(_shortStringHelper, culture); } - private static string GetUrlSegmentSource(IContentBase content, string culture) + private static string? GetUrlSegmentSource(IContentBase content, string? culture) { - string source = null; + string? source = null; if (content.HasProperty(Constants.Conventions.Content.UrlName)) source = (content.GetValue(Constants.Conventions.Content.UrlName, culture) ?? string.Empty).Trim(); if (string.IsNullOrWhiteSpace(source)) diff --git a/src/Umbraco.Core/Strings/Diff.cs b/src/Umbraco.Core/Strings/Diff.cs index b0cf7100de..8d7ef9feaa 100644 --- a/src/Umbraco.Core/Strings/Diff.cs +++ b/src/Umbraco.Core/Strings/Diff.cs @@ -247,7 +247,7 @@ namespace Umbraco.Cms.Core.Strings if (ignoreCase) s = s.ToLower(); - object aCode = h[s]; + object? aCode = h[s]; if (aCode == null) { lastUsedCode++; diff --git a/src/Umbraco.Core/Strings/IShortStringHelper.cs b/src/Umbraco.Core/Strings/IShortStringHelper.cs index a424a0bf45..a436758d9a 100644 --- a/src/Umbraco.Core/Strings/IShortStringHelper.cs +++ b/src/Umbraco.Core/Strings/IShortStringHelper.cs @@ -39,7 +39,7 @@ /// The text to filter. /// The culture. /// The safe URL segment. - string CleanStringForUrlSegment(string text, string culture); + string CleanStringForUrlSegment(string text, string? culture); /// /// Cleans a string, in the context of the invariant culture, to produce a string that can safely be used as a filename, diff --git a/src/Umbraco.Core/Strings/IUrlSegmentProvider.cs b/src/Umbraco.Core/Strings/IUrlSegmentProvider.cs index 6e1eccdde5..74d147173f 100644 --- a/src/Umbraco.Core/Strings/IUrlSegmentProvider.cs +++ b/src/Umbraco.Core/Strings/IUrlSegmentProvider.cs @@ -17,7 +17,7 @@ namespace Umbraco.Cms.Core.Strings /// This is for when Umbraco is capable of managing more than one URL /// per content, in 1-to-1 multilingual configurations. Then there would be one /// URL per culture. - string GetUrlSegment(IContentBase content, string? culture = null); + string? GetUrlSegment(IContentBase content, string? culture = null); // TODO: For the 301 tracking, we need to add another extended interface to this so that // the RedirectTrackingEventHandler can ask the IUrlSegmentProvider if the URL is changing. diff --git a/src/Umbraco.Core/Sync/IServerAddress.cs b/src/Umbraco.Core/Sync/IServerAddress.cs index a177454886..4de7490d8f 100644 --- a/src/Umbraco.Core/Sync/IServerAddress.cs +++ b/src/Umbraco.Core/Sync/IServerAddress.cs @@ -8,7 +8,7 @@ namespace Umbraco.Cms.Core.Sync /// /// Gets the server address. /// - string ServerAddress { get; } + string? ServerAddress { get; } // TODO: Should probably add things like port, protocol, server name, app id } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 2252aa36f2..62f0f8652e 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -9,7 +9,7 @@ Contains the core assembly needed to run Umbraco Cms. This package only contains the assembly, and can be used for package development. Use the template in the Umbraco.Templates package to setup Umbraco Umbraco CMS enable - + Nullable