diff --git a/src/Umbraco.Core/Collections/CompositeIntStringKey.cs b/src/Umbraco.Core/Collections/CompositeIntStringKey.cs index 74ef4e45e1..cafc209e08 100644 --- a/src/Umbraco.Core/Collections/CompositeIntStringKey.cs +++ b/src/Umbraco.Core/Collections/CompositeIntStringKey.cs @@ -2,7 +2,6 @@ namespace Umbraco.Core.Collections { - /// /// Represents a composite key of (int, string) for fast dictionaries. /// diff --git a/src/Umbraco.Core/Collections/ObservableDictionary.cs b/src/Umbraco.Core/Collections/ObservableDictionary.cs index ded87c30a6..6518533476 100644 --- a/src/Umbraco.Core/Collections/ObservableDictionary.cs +++ b/src/Umbraco.Core/Collections/ObservableDictionary.cs @@ -23,22 +23,22 @@ namespace Umbraco.Core.Collections /// 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) - : base() { - if (keySelector == null) throw new ArgumentException("keySelector"); - KeySelector = keySelector; + KeySelector = keySelector ?? throw new ArgumentException("keySelector"); Indecies = new Dictionary(equalityComparer); } #region Protected Methods + protected override void InsertItem(int index, TValue item) { var key = KeySelector(item); if (Indecies.ContainsKey(key)) throw new DuplicateKeyException(key.ToString()); - if (index != this.Count) + if (index != Count) { foreach (var k in Indecies.Keys.Where(k => Indecies[k] >= index).ToList()) { @@ -48,7 +48,6 @@ namespace Umbraco.Core.Collections base.InsertItem(index, item); Indecies[key] = index; - } protected override void ClearItems() @@ -57,7 +56,6 @@ namespace Umbraco.Core.Collections Indecies.Clear(); } - protected override void RemoveItem(int index) { var item = this[index]; @@ -72,6 +70,7 @@ namespace Umbraco.Core.Collections Indecies[k]--; } } + #endregion public bool ContainsKey(TKey key) @@ -87,7 +86,7 @@ namespace Umbraco.Core.Collections public TValue this[TKey key] { - get { return this[Indecies[key]]; } + get => this[Indecies[key]]; set { //confirm key matches @@ -96,7 +95,7 @@ namespace Umbraco.Core.Collections if (!Indecies.ContainsKey(key)) { - this.Add(value); + Add(value); } else { @@ -116,6 +115,7 @@ namespace Umbraco.Core.Collections public bool Replace(TKey key, TValue value) { if (!Indecies.ContainsKey(key)) return false; + //confirm key matches if (!KeySelector(value).Equals(key)) throw new InvalidOperationException("Key of new value does not match"); @@ -129,7 +129,7 @@ namespace Umbraco.Core.Collections { if (!Indecies.ContainsKey(key)) return false; - this.RemoveAt(Indecies[key]); + RemoveAt(Indecies[key]); return true; } @@ -145,6 +145,7 @@ namespace Umbraco.Core.Collections { throw new InvalidOperationException("No item with the key " + currentKey + "was found in the collection"); } + if (ContainsKey(newKey)) { throw new DuplicateKeyException(newKey.ToString()); @@ -184,10 +185,7 @@ namespace Umbraco.Core.Collections //this will never be used ICollection IDictionary.Values => Values.ToList(); - bool ICollection>.IsReadOnly - { - get { return false; } - } + bool ICollection>.IsReadOnly => false; IEnumerator> IEnumerable>.GetEnumerator() { @@ -227,14 +225,13 @@ namespace Umbraco.Core.Collections internal class DuplicateKeyException : Exception { - - public string Key { get; private set; } public DuplicateKeyException(string key) - : base("Attempted to insert duplicate key " + key + " in collection") + : base("Attempted to insert duplicate key \"" + key + "\" in collection.") { Key = key; } - } + public string Key { get; } + } } } diff --git a/src/Umbraco.Core/Migrations/MigrationBase_Extra.cs b/src/Umbraco.Core/Migrations/MigrationBase_Extra.cs index b1b405bcf4..9e13badacf 100644 --- a/src/Umbraco.Core/Migrations/MigrationBase_Extra.cs +++ b/src/Umbraco.Core/Migrations/MigrationBase_Extra.cs @@ -18,12 +18,26 @@ namespace Umbraco.Core.Migrations AddColumn(table, table.Name, columnName); } + protected void AddColumnIfNotExists(IEnumerable columns, string columnName) + { + var table = DefinitionFactory.GetTableDefinition(typeof(T), SqlSyntax); + if (columns.Any(x => x.TableName.InvariantEquals(table.Name) && !x.ColumnName.InvariantEquals(columnName))) + AddColumn(table, table.Name, columnName); + } + protected void AddColumn(string tableName, string columnName) { var table = DefinitionFactory.GetTableDefinition(typeof(T), SqlSyntax); AddColumn(table, tableName, columnName); } + protected void AddColumnIfNotExists(IEnumerable columns, string tableName, string columnName) + { + var table = DefinitionFactory.GetTableDefinition(typeof(T), SqlSyntax); + if (columns.Any(x => x.TableName.InvariantEquals(tableName) && !x.ColumnName.InvariantEquals(columnName))) + AddColumn(table, tableName, columnName); + } + private void AddColumn(TableDefinition table, string tableName, string columnName) { if (ColumnExists(tableName, columnName)) return; diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/AddLogTableColumns.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/AddLogTableColumns.cs index d038da2573..c8a6e38dad 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/AddLogTableColumns.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/AddLogTableColumns.cs @@ -13,12 +13,8 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 { var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToList(); - if (columns.Any(x => x.TableName.InvariantEquals(Constants.DatabaseSchema.Tables.Log) && !x.ColumnName.InvariantEquals("entityType"))) - AddColumn("entityType"); - - if (columns.Any(x => x.TableName.InvariantEquals(Constants.DatabaseSchema.Tables.Log) && !x.ColumnName.InvariantEquals("parameters"))) - AddColumn("parameters"); - + AddColumnIfNotExists(columns, "entityType"); + AddColumnIfNotExists(columns, "parameters"); } } } diff --git a/src/Umbraco.Core/Models/AuditItem.cs b/src/Umbraco.Core/Models/AuditItem.cs index 483548f558..5fbde7f362 100644 --- a/src/Umbraco.Core/Models/AuditItem.cs +++ b/src/Umbraco.Core/Models/AuditItem.cs @@ -5,12 +5,8 @@ namespace Umbraco.Core.Models public sealed class AuditItem : EntityBase, IAuditItem { /// - /// Constructor for creating an item to be created + /// Initializes a new instance of the class. /// - /// - /// - /// - /// public AuditItem(int objectId, AuditType type, int userId, string entityType, string comment = null, string parameters = null) { DisableChangeTracking(); @@ -25,14 +21,19 @@ namespace Umbraco.Core.Models EnableChangeTracking(); } - public string Comment { get; } + /// + public AuditType AuditType { get; } /// public string EntityType { get; } + + /// + public int UserId { get; } + + /// + public string Comment { get; } + /// public string Parameters { get; } - - public AuditType AuditType { get; } - public int UserId { get; } } } diff --git a/src/Umbraco.Core/Models/AuditType.cs b/src/Umbraco.Core/Models/AuditType.cs index 759aac3bfc..8a57948805 100644 --- a/src/Umbraco.Core/Models/AuditType.cs +++ b/src/Umbraco.Core/Models/AuditType.cs @@ -1,96 +1,117 @@ namespace Umbraco.Core.Models { /// - /// Enums for vailable types of auditing + /// Defines audit types. /// public enum AuditType { /// - /// Used when new nodes are added + /// New node(s) being added. /// New, + /// - /// Used when nodes are saved + /// Node(s) being saved. /// Save, + /// - /// Used when variant(s) are saved + /// Variant(s) being saved. /// SaveVariant, + /// - /// Used when nodes are opened + /// Node(s) being opened. /// Open, + /// - /// Used when nodes are deleted + /// Node(s) being deleted. /// Delete, + /// - /// Used when nodes are published + /// Node(s) being published. /// Publish, + /// - /// Used when variant(s) are published + /// Variant(s) being published. /// PublishVariant, + /// - /// Used when nodes are sent for publishing + /// Node(s) being sent to publishing. /// SendToPublish, + /// - /// Used when variant(s) are sent for publishing - /// + /// Variant(s) being sent to publishing. + /// SendToPublishVariant, + /// - /// Used when nodes are unpublished + /// Node(s) being unpublished. /// Unpublish, + /// - /// Used when variant(s) are unpublished + /// Variant(s) being unpublished. /// UnpublishVariant, + /// - /// Used when nodes are moved + /// Node(s) being moved. /// Move, + /// - /// Used when nodes are copied + /// Node(s) being copied. /// Copy, + /// - /// Used when nodes are assígned a domain + /// Node(s) being assigned domains. /// AssignDomain, + /// - /// Used when public access are changed for a node + /// Node(s) public access changing. /// PublicAccess, + /// - /// Used when nodes are sorted + /// Node(s) being sorted. /// Sort, + /// - /// Used when a notification are send to a user + /// Notification(s) being sent to user. /// Notify, + /// - /// General system notification + /// General system audit message. /// System, + /// - /// Used when a node's content is rolled back to a previous version + /// Node's content being rolled back to a previous version. /// RollBack, + /// - /// Used when a package is installed + /// Package being installed. /// PackagerInstall, + /// - /// Used when a package is uninstalled + /// Package being uninstalled. /// - PackagerUninstall, + PackagerUninstall, + /// - /// Use this log action for custom log messages that should be shown in the audit trail + /// Custom audit message. /// Custom } diff --git a/src/Umbraco.Core/Models/Content.cs b/src/Umbraco.Core/Models/Content.cs index 25a30da6db..3e5becf021 100644 --- a/src/Umbraco.Core/Models/Content.cs +++ b/src/Umbraco.Core/Models/Content.cs @@ -4,7 +4,6 @@ using System.Collections.Specialized; using System.Linq; using System.Reflection; using System.Runtime.Serialization; -using Umbraco.Core.Collections; using Umbraco.Core.Exceptions; namespace Umbraco.Core.Models @@ -22,8 +21,8 @@ namespace Umbraco.Core.Models private PublishedState _publishedState; private DateTime? _releaseDate; private DateTime? _expireDate; - private CultureNameCollection _publishInfos; - private CultureNameCollection _publishInfosOrig; + private ContentCultureInfosCollection _publishInfos; + private ContentCultureInfosCollection _publishInfosOrig; private HashSet _editedCultures; private static readonly Lazy Ps = new Lazy(); @@ -89,7 +88,7 @@ namespace Umbraco.Core.Models public readonly PropertyInfo PublishedSelector = ExpressionHelper.GetPropertyInfo(x => x.Published); public readonly PropertyInfo ReleaseDateSelector = ExpressionHelper.GetPropertyInfo(x => x.ReleaseDate); public readonly PropertyInfo ExpireDateSelector = ExpressionHelper.GetPropertyInfo(x => x.ExpireDate); - public readonly PropertyInfo PublishNamesSelector = ExpressionHelper.GetPropertyInfo>(x => x.PublishNames); + public readonly PropertyInfo PublishCultureInfosSelector = ExpressionHelper.GetPropertyInfo>(x => x.PublishCultureInfos); } /// @@ -214,7 +213,7 @@ namespace Umbraco.Core.Models /// [IgnoreDataMember] - public IEnumerable EditedCultures => CultureNames.Keys.Where(IsCultureEdited); + public IEnumerable EditedCultures => CultureInfos.Keys.Where(IsCultureEdited); /// [IgnoreDataMember] @@ -224,7 +223,7 @@ namespace Umbraco.Core.Models public bool IsCulturePublished(string culture) // just check _publishInfos // a non-available culture could not become published anyways - => _publishInfos != null && _publishInfos.ContainsKey(culture); + => _publishInfos != null && _publishInfos.ContainsKey(culture); /// public bool WasCulturePublished(string culture) @@ -247,8 +246,8 @@ namespace Umbraco.Core.Models _publishInfos.AddOrUpdate(culture, publishInfos.Name, date); - if (CultureNames.TryGetValue(culture, out var name)) - SetCultureInfo(culture, name.Name, date); + if (CultureInfos.TryGetValue(culture, out var infos)) + SetCultureInfo(culture, infos.Name, date); } } @@ -260,7 +259,7 @@ namespace Umbraco.Core.Models /// [IgnoreDataMember] - public IReadOnlyDictionary PublishNames => _publishInfos ?? NoNames; + public IReadOnlyDictionary PublishCultureInfos => _publishInfos ?? NoInfos; /// public string GetPublishName(string culture) @@ -291,7 +290,7 @@ namespace Umbraco.Core.Models if (_publishInfos == null) { - _publishInfos = new CultureNameCollection(); + _publishInfos = new ContentCultureInfosCollection(); _publishInfos.CollectionChanged += PublishNamesCollectionChanged; } @@ -338,13 +337,11 @@ namespace Umbraco.Core.Models } /// - /// Event handler for when the culture names collection is modified + /// Handles culture infos collection changes. /// - /// - /// private void PublishNamesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { - OnPropertyChanged(Ps.Value.PublishNamesSelector); + OnPropertyChanged(Ps.Value.PublishCultureInfosSelector); } [IgnoreDataMember] @@ -477,11 +474,12 @@ namespace Umbraco.Core.Models // if this entity's previous culture publish state (regardless of the rememberDirty flag) _publishInfosOrig = _publishInfos == null ? null - : new CultureNameCollection(_publishInfos); + : new ContentCultureInfosCollection(_publishInfos); - if (_publishInfos != null) - foreach (var cultureName in _publishInfos) - cultureName.ResetDirtyProperties(rememberDirty); + if (_publishInfos == null) return; + + foreach (var infos in _publishInfos) + infos.ResetDirtyProperties(rememberDirty); } /// @@ -509,18 +507,16 @@ namespace Umbraco.Core.Models clone.DisableChangeTracking(); //need to manually clone this since it's not settable - clone._contentType = (IContentType)ContentType.DeepClone(); + clone._contentType = (IContentType) ContentType.DeepClone(); //if culture infos exist then deal with event bindings if (clone._publishInfos != null) { - clone._publishInfos.CollectionChanged -= this.PublishNamesCollectionChanged; //clear this event handler if any - clone._publishInfos = (CultureNameCollection)_publishInfos.DeepClone(); //manually deep clone - clone._publishInfos.CollectionChanged += clone.PublishNamesCollectionChanged; //re-assign correct event handler + clone._publishInfos.CollectionChanged -= PublishNamesCollectionChanged; //clear this event handler if any + clone._publishInfos = (ContentCultureInfosCollection) _publishInfos.DeepClone(); //manually deep clone + clone._publishInfos.CollectionChanged += clone.PublishNamesCollectionChanged; //re-assign correct event handler } - //this shouldn't really be needed since we're not tracking - clone.ResetDirtyProperties(false); //re-enable tracking clone.EnableChangeTracking(); diff --git a/src/Umbraco.Core/Models/ContentBase.cs b/src/Umbraco.Core/Models/ContentBase.cs index a288f7fac9..863374726d 100644 --- a/src/Umbraco.Core/Models/ContentBase.cs +++ b/src/Umbraco.Core/Models/ContentBase.cs @@ -5,8 +5,6 @@ using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.Serialization; -using System.Web; -using Umbraco.Core.Collections; using Umbraco.Core.Exceptions; using Umbraco.Core.Models.Entities; @@ -20,14 +18,14 @@ namespace Umbraco.Core.Models [DebuggerDisplay("Id: {Id}, Name: {Name}, ContentType: {ContentTypeBase.Alias}")] public abstract class ContentBase : TreeEntityBase, IContentBase { - protected static readonly CultureNameCollection NoNames = new CultureNameCollection(); + protected static readonly ContentCultureInfosCollection NoInfos = new ContentCultureInfosCollection(); private static readonly Lazy Ps = new Lazy(); private int _contentTypeId; protected IContentTypeComposition ContentTypeBase; private int _writerId; private PropertyCollection _properties; - private CultureNameCollection _cultureInfos; + private ContentCultureInfosCollection _cultureInfos; /// /// Initializes a new instance of the class. @@ -70,7 +68,7 @@ namespace Umbraco.Core.Models public readonly PropertyInfo DefaultContentTypeIdSelector = ExpressionHelper.GetPropertyInfo(x => x.ContentTypeId); public readonly PropertyInfo PropertyCollectionSelector = ExpressionHelper.GetPropertyInfo(x => x.Properties); public readonly PropertyInfo WriterSelector = ExpressionHelper.GetPropertyInfo(x => x.WriterId); - public readonly PropertyInfo CultureNamesSelector = ExpressionHelper.GetPropertyInfo>(x => x.CultureNames); + public readonly PropertyInfo CultureInfosSelector = ExpressionHelper.GetPropertyInfo>(x => x.CultureInfos); } protected void PropertiesChanged(object sender, NotifyCollectionChangedEventArgs e) @@ -160,7 +158,7 @@ namespace Umbraco.Core.Models /// [DataMember] - public virtual IReadOnlyDictionary CultureNames => _cultureInfos ?? NoNames; + public virtual IReadOnlyDictionary CultureInfos => _cultureInfos ?? NoInfos; /// public string GetCultureName(string culture) @@ -207,17 +205,9 @@ namespace Umbraco.Core.Models } } - //fixme: this isn't used anywhere - internal void TouchCulture(string culture) - { - if (ContentTypeBase.VariesByCulture() && _cultureInfos != null && _cultureInfos.TryGetValue(culture, out var infos)) - _cultureInfos.AddOrUpdate(culture, infos.Name, DateTime.Now); - } - protected void ClearCultureInfos() { - if (_cultureInfos != null) - _cultureInfos.Clear(); + _cultureInfos?.Clear(); _cultureInfos = null; } @@ -243,21 +233,19 @@ namespace Umbraco.Core.Models if (_cultureInfos == null) { - _cultureInfos = new CultureNameCollection(); - _cultureInfos.CollectionChanged += CultureNamesCollectionChanged; + _cultureInfos = new ContentCultureInfosCollection(); + _cultureInfos.CollectionChanged += CultureInfosCollectionChanged; } _cultureInfos.AddOrUpdate(culture, name, date); } /// - /// Event handler for when the culture names collection is modified + /// Handles culture infos collection changes. /// - /// - /// - private void CultureNamesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + private void CultureInfosCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { - OnPropertyChanged(Ps.Value.CultureNamesSelector); + OnPropertyChanged(Ps.Value.CultureInfosSelector); } #endregion @@ -370,10 +358,10 @@ namespace Umbraco.Core.Models if (culture == null || culture == "*") Name = other.Name; - foreach (var (otherCulture, otherName) in other.CultureNames) + foreach (var (otherCulture, otherInfos) in other.CultureInfos) { if (culture == "*" || culture == otherCulture) - SetCultureName(otherName.Name, otherCulture); + SetCultureName(otherInfos.Name, otherCulture); } } @@ -406,10 +394,11 @@ namespace Umbraco.Core.Models foreach (var prop in Properties) prop.ResetDirtyProperties(rememberDirty); - // take care of culture names - if (_cultureInfos != null) - foreach (var cultureName in _cultureInfos) - cultureName.ResetDirtyProperties(rememberDirty); + // take care of culture infos + if (_cultureInfos == null) return; + + foreach (var cultureInfo in _cultureInfos) + cultureInfo.ResetDirtyProperties(rememberDirty); } /// @@ -482,34 +471,33 @@ namespace Umbraco.Core.Models #endregion - /// - /// Override to deal with specific object instances - /// - /// + /// + /// + /// Overriden to deal with specific object instances + /// public override object DeepClone() { - var clone = (ContentBase)base.DeepClone(); + var clone = (ContentBase) base.DeepClone(); + //turn off change tracking clone.DisableChangeTracking(); //if culture infos exist then deal with event bindings if (clone._cultureInfos != null) { - clone._cultureInfos.CollectionChanged -= this.CultureNamesCollectionChanged; //clear this event handler if any - clone._cultureInfos = (CultureNameCollection)_cultureInfos.DeepClone(); //manually deep clone - clone._cultureInfos.CollectionChanged += clone.CultureNamesCollectionChanged; //re-assign correct event handler + clone._cultureInfos.CollectionChanged -= CultureInfosCollectionChanged; //clear this event handler if any + clone._cultureInfos = (ContentCultureInfosCollection) _cultureInfos.DeepClone(); //manually deep clone + clone._cultureInfos.CollectionChanged += clone.CultureInfosCollectionChanged; //re-assign correct event handler } //if properties exist then deal with event bindings if (clone._properties != null) { - clone._properties.CollectionChanged -= this.PropertiesChanged; //clear this event handler if any - clone._properties = (PropertyCollection)_properties.DeepClone(); //manually deep clone + clone._properties.CollectionChanged -= PropertiesChanged; //clear this event handler if any + clone._properties = (PropertyCollection) _properties.DeepClone(); //manually deep clone clone._properties.CollectionChanged += clone.PropertiesChanged; //re-assign correct event handler } - //this shouldn't really be needed since we're not tracking - clone.ResetDirtyProperties(false); //re-enable tracking clone.EnableChangeTracking(); diff --git a/src/Umbraco.Core/Models/CultureName.cs b/src/Umbraco.Core/Models/ContentCultureInfos.cs similarity index 52% rename from src/Umbraco.Core/Models/CultureName.cs rename to src/Umbraco.Core/Models/ContentCultureInfos.cs index d683f07b49..bcf1dbb1b1 100644 --- a/src/Umbraco.Core/Models/CultureName.cs +++ b/src/Umbraco.Core/Models/ContentCultureInfos.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Reflection; +using Umbraco.Core.Exceptions; using Umbraco.Core.Models.Entities; namespace Umbraco.Core.Models @@ -8,19 +9,26 @@ namespace Umbraco.Core.Models /// /// The name of a content variant for a given culture /// - public class CultureName : BeingDirtyBase, IDeepCloneable, IEquatable + public class ContentCultureInfos : BeingDirtyBase, IDeepCloneable, IEquatable { private DateTime _date; private string _name; private static readonly Lazy Ps = new Lazy(); /// - /// Used for cloning without change tracking + /// Initializes a new instance of the class. /// - /// - /// - /// - private CultureName(string culture, string name, DateTime date) + public ContentCultureInfos(string culture) + { + if (culture.IsNullOrWhiteSpace()) throw new ArgumentNullOrEmptyException(nameof(culture)); + Culture = culture; + } + + /// + /// Initializes a new instance of the class. + /// + /// Used for cloning, without change tracking. + private ContentCultureInfos(string culture, string name, DateTime date) : this(culture) { _name = name; @@ -28,45 +36,47 @@ namespace Umbraco.Core.Models } /// - /// Constructor + /// Gets the culture. /// - /// - public CultureName(string culture) - { - if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("message", nameof(culture)); - Culture = culture; - } - - public string Culture { get; private set; } + public string Culture { get; } + /// + /// Gets the name. + /// public string Name { get => _name; set => SetPropertyValueAndDetectChanges(value, ref _name, Ps.Value.NameSelector); } + /// + /// Gets the date. + /// public DateTime Date { get => _date; set => SetPropertyValueAndDetectChanges(value, ref _date, Ps.Value.DateSelector); } + /// public object DeepClone() { - return new CultureName(Culture, Name, Date); + return new ContentCultureInfos(Culture, Name, Date); } + /// public override bool Equals(object obj) { - return obj is CultureName && Equals((CultureName)obj); + return obj is ContentCultureInfos other && Equals(other); } - public bool Equals(CultureName other) + /// + public bool Equals(ContentCultureInfos other) { - return Culture == other.Culture && - Name == other.Name; + return other != null && Culture == other.Culture && Name == other.Name; } + /// public override int GetHashCode() { var hashCode = 479558943; @@ -76,22 +86,28 @@ namespace Umbraco.Core.Models } /// - /// Allows deconstructing into culture and name + /// Deconstructs into culture and name. /// - /// - /// public void Deconstruct(out string culture, out string name) { culture = Culture; name = Name; } + /// + /// Deconstructs into culture, name and date. + /// + public void Deconstruct(out string culture, out string name, out DateTime date) + { + Deconstruct(out culture, out name); + date = Date; + } + // ReSharper disable once ClassNeverInstantiated.Local private class PropertySelectors { - public readonly PropertyInfo CultureSelector = ExpressionHelper.GetPropertyInfo(x => x.Culture); - public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo(x => x.Name); - public readonly PropertyInfo DateSelector = ExpressionHelper.GetPropertyInfo(x => x.Date); + public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo(x => x.Name); + public readonly PropertyInfo DateSelector = ExpressionHelper.GetPropertyInfo(x => x.Date); } } } diff --git a/src/Umbraco.Core/Models/ContentCultureInfosCollection.cs b/src/Umbraco.Core/Models/ContentCultureInfosCollection.cs new file mode 100644 index 0000000000..5238e65631 --- /dev/null +++ b/src/Umbraco.Core/Models/ContentCultureInfosCollection.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using Umbraco.Core.Collections; +using Umbraco.Core.Exceptions; + +namespace Umbraco.Core.Models +{ + /// + /// The culture names of a content's variants + /// + public class ContentCultureInfosCollection : ObservableDictionary, IDeepCloneable + { + /// + /// Initializes a new instance of the class. + /// + public ContentCultureInfosCollection() + : base(x => x.Culture, StringComparer.InvariantCultureIgnoreCase) + { } + + /// + /// Initializes a new instance of the class with items. + /// + public ContentCultureInfosCollection(IEnumerable items) + : base(x => x.Culture, StringComparer.InvariantCultureIgnoreCase) + { + foreach (var item in items) + Add(item); + } + + /// + /// Adds or updates a instance. + /// + public void AddOrUpdate(string culture, string name, DateTime date) + { + if (culture.IsNullOrWhiteSpace()) throw new ArgumentNullOrEmptyException(nameof(culture)); + culture = culture.ToLowerInvariant(); + + if (TryGetValue(culture, out var item)) + { + item.Name = name; + item.Date = date; + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, item)); + } + else + { + Add(new ContentCultureInfos(culture) + { + Name = name, + Date = date + }); + } + } + + /// + public object DeepClone() + { + var clone = new ContentCultureInfosCollection(); + + foreach (var item in this) + { + var itemClone = (ContentCultureInfos) item.DeepClone(); + itemClone.ResetDirtyProperties(false); + clone.Add(itemClone); + } + + return clone; + } + } +} diff --git a/src/Umbraco.Core/Models/ContentTypeBase.cs b/src/Umbraco.Core/Models/ContentTypeBase.cs index 0a86f4cf09..9f848c6d14 100644 --- a/src/Umbraco.Core/Models/ContentTypeBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeBase.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; -using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Reflection; @@ -470,7 +469,8 @@ namespace Umbraco.Core.Models public override object DeepClone() { - var clone = (ContentTypeBase)base.DeepClone(); + var clone = (ContentTypeBase) base.DeepClone(); + //turn off change tracking clone.DisableChangeTracking(); @@ -480,20 +480,18 @@ namespace Umbraco.Core.Models // its ignored from the auto-clone process because its return values are unions, not raw and // we end up with duplicates, see: http://issues.umbraco.org/issue/U4-4842 - clone._noGroupPropertyTypes.CollectionChanged -= this.PropertyTypesChanged; //clear this event handler if any - clone._noGroupPropertyTypes = (PropertyTypeCollection)_noGroupPropertyTypes.DeepClone(); //manually deep clone - clone._noGroupPropertyTypes.CollectionChanged += clone.PropertyTypesChanged; //re-assign correct event handler + clone._noGroupPropertyTypes.CollectionChanged -= PropertyTypesChanged; //clear this event handler if any + clone._noGroupPropertyTypes = (PropertyTypeCollection) _noGroupPropertyTypes.DeepClone(); //manually deep clone + clone._noGroupPropertyTypes.CollectionChanged += clone.PropertyTypesChanged; //re-assign correct event handler } if (clone._propertyGroups != null) { - clone._propertyGroups.CollectionChanged -= this.PropertyGroupsChanged; //clear this event handler if any - clone._propertyGroups = (PropertyGroupCollection)_propertyGroups.DeepClone(); //manually deep clone - clone._propertyGroups.CollectionChanged += clone.PropertyGroupsChanged; //re-assign correct event handler + clone._propertyGroups.CollectionChanged -= PropertyGroupsChanged; //clear this event handler if any + clone._propertyGroups = (PropertyGroupCollection) _propertyGroups.DeepClone(); //manually deep clone + clone._propertyGroups.CollectionChanged += clone.PropertyGroupsChanged; //re-assign correct event handler } - //this shouldn't really be needed since we're not tracking - clone.ResetDirtyProperties(false); //re-enable tracking clone.EnableChangeTracking(); diff --git a/src/Umbraco.Core/Models/CultureNameCollection.cs b/src/Umbraco.Core/Models/CultureNameCollection.cs deleted file mode 100644 index 406abc7c0f..0000000000 --- a/src/Umbraco.Core/Models/CultureNameCollection.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Collections.Specialized; -using System.Linq; -using Umbraco.Core.Collections; - -namespace Umbraco.Core.Models -{ - - - /// - /// The culture names of a content's variants - /// - public class CultureNameCollection : ObservableDictionary, IDeepCloneable - { - /// - /// Creates a new collection from another collection - /// - /// - public CultureNameCollection(IEnumerable names) - : base(x => x.Culture, StringComparer.InvariantCultureIgnoreCase) - { - foreach (var n in names) - Add(n); - } - - /// - /// Creates a new collection - /// - public CultureNameCollection() - : base(x => x.Culture, StringComparer.InvariantCultureIgnoreCase) - { - } - - /// - /// Add or update the - /// - /// - public void AddOrUpdate(string culture, string name, DateTime date) - { - culture = culture.ToLowerInvariant(); - if (TryGetValue(culture, out var found)) - { - found.Name = name; - found.Date = date; - OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, found, found)); - } - else - Add(new CultureName(culture) - { - Name = name, - Date = date - }); - } - - public object DeepClone() - { - var clone = new CultureNameCollection(); - foreach (var name in this) - { - name.DisableChangeTracking(); - var copy = (CultureName)name.DeepClone(); - copy.ResetDirtyProperties(false); - clone.Add(copy); - name.EnableChangeTracking(); - } - return clone; - } - - - } -} diff --git a/src/Umbraco.Core/Models/Entities/EntityBase.cs b/src/Umbraco.Core/Models/Entities/EntityBase.cs index f1ff5f3bf5..0b69586abf 100644 --- a/src/Umbraco.Core/Models/Entities/EntityBase.cs +++ b/src/Umbraco.Core/Models/Entities/EntityBase.cs @@ -13,7 +13,7 @@ namespace Umbraco.Core.Models.Entities [DebuggerDisplay("Id: {" + nameof(Id) + "}")] public abstract class EntityBase : BeingDirtyBase, IEntity { -#if ModelDebug +#if DEBUG_MODEL public Guid InstanceId = Guid.NewGuid(); #endif @@ -165,11 +165,10 @@ namespace Umbraco.Core.Models.Entities var unused = Key; // ensure that 'this' has a key, before cloning var clone = (EntityBase) MemberwiseClone(); -#if ModelDebug +#if DEBUG_MODEL clone.InstanceId = Guid.NewGuid(); #endif - // clear changes (ensures the clone has its own dictionaries) // then disable change tracking clone.ResetDirtyProperties(false); diff --git a/src/Umbraco.Core/Models/IAuditItem.cs b/src/Umbraco.Core/Models/IAuditItem.cs index c1dfd99dbb..ed70ada8ad 100644 --- a/src/Umbraco.Core/Models/IAuditItem.cs +++ b/src/Umbraco.Core/Models/IAuditItem.cs @@ -1,22 +1,35 @@ -using System; -using Umbraco.Core.Models.Entities; +using Umbraco.Core.Models.Entities; namespace Umbraco.Core.Models { + /// + /// Represents an audit item. + /// public interface IAuditItem : IEntity { - string Comment { get; } + /// + /// Gets the audit type. + /// + AuditType AuditType { get; } /// - /// The entity type for the log entry + /// Gets the audited entity type. /// string EntityType { get; } /// - /// Optional additional data parameters for the log + /// Gets the audit user identifier. + /// + int UserId { get; } + + /// + /// Gets the audit comments. + /// + string Comment { get; } + + /// + /// Gets optional additional data parameters. /// string Parameters { get; } - AuditType AuditType { get; } - int UserId { get; } } } diff --git a/src/Umbraco.Core/Models/IContent.cs b/src/Umbraco.Core/Models/IContent.cs index 125c1a0f55..0c0d9449e0 100644 --- a/src/Umbraco.Core/Models/IContent.cs +++ b/src/Umbraco.Core/Models/IContent.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using Umbraco.Core.Collections; namespace Umbraco.Core.Models { @@ -127,13 +126,13 @@ namespace Umbraco.Core.Models string GetPublishName(string culture); /// - /// Gets the published names of the content. + /// Gets the published culture infos of the content. /// /// /// Because a dictionary key cannot be null this cannot get the invariant /// name, which must be get via the property. /// - IReadOnlyDictionary PublishNames { get; } + IReadOnlyDictionary PublishCultureInfos { get; } /// /// Gets the published cultures. diff --git a/src/Umbraco.Core/Models/IContentBase.cs b/src/Umbraco.Core/Models/IContentBase.cs index c84c768e9c..cef8086207 100644 --- a/src/Umbraco.Core/Models/IContentBase.cs +++ b/src/Umbraco.Core/Models/IContentBase.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using Umbraco.Core.Collections; using Umbraco.Core.Models.Entities; namespace Umbraco.Core.Models @@ -52,13 +51,13 @@ namespace Umbraco.Core.Models string GetCultureName(string culture); /// - /// Gets the names of the content item. + /// Gets culture infos of the content item. /// /// /// Because a dictionary key cannot be null this cannot contain the invariant /// culture name, which must be get or set via the property. /// - IReadOnlyDictionary CultureNames { get; } + IReadOnlyDictionary CultureInfos { get; } /// /// Gets the available cultures. diff --git a/src/Umbraco.Core/Models/Media.cs b/src/Umbraco.Core/Models/Media.cs index 097fc46351..9c13a22caa 100644 --- a/src/Umbraco.Core/Models/Media.cs +++ b/src/Umbraco.Core/Models/Media.cs @@ -1,6 +1,5 @@ using System; using System.Runtime.Serialization; -using Umbraco.Core.Persistence.Mappers; namespace Umbraco.Core.Models { @@ -21,8 +20,7 @@ namespace Umbraco.Core.Models /// MediaType for the current Media object public Media(string name, IMedia parent, IMediaType contentType) : this(name, parent, contentType, new PropertyCollection()) - { - } + { } /// /// Constructor for creating a Media object @@ -45,8 +43,7 @@ namespace Umbraco.Core.Models /// MediaType for the current Media object public Media(string name, int parentId, IMediaType contentType) : this(name, parentId, contentType, new PropertyCollection()) - { - } + { } /// /// Constructor for creating a Media object @@ -117,6 +114,5 @@ namespace Umbraco.Core.Models //The Media Recycle Bin Id is -21 so we correct that here ParentId = parentId == -20 ? -21 : parentId; } - } } diff --git a/src/Umbraco.Core/Models/PropertyGroup.cs b/src/Umbraco.Core/Models/PropertyGroup.cs index 90f3ef2b55..6c1f2e5c61 100644 --- a/src/Umbraco.Core/Models/PropertyGroup.cs +++ b/src/Umbraco.Core/Models/PropertyGroup.cs @@ -103,18 +103,17 @@ namespace Umbraco.Core.Models public override object DeepClone() { var clone = (PropertyGroup)base.DeepClone(); + //turn off change tracking clone.DisableChangeTracking(); if (clone._propertyTypes != null) { - clone._propertyTypes.CollectionChanged -= this.PropertyTypesChanged; //clear this event handler if any - clone._propertyTypes = (PropertyTypeCollection)_propertyTypes.DeepClone(); //manually deep clone - clone._propertyTypes.CollectionChanged += clone.PropertyTypesChanged; //re-assign correct event handler + clone._propertyTypes.CollectionChanged -= PropertyTypesChanged; //clear this event handler if any + clone._propertyTypes = (PropertyTypeCollection) _propertyTypes.DeepClone(); //manually deep clone + clone._propertyTypes.CollectionChanged += clone.PropertyTypesChanged; //re-assign correct event handler } - //this shouldn't really be needed since we're not tracking - clone.ResetDirtyProperties(false); //re-enable tracking clone.EnableChangeTracking(); diff --git a/src/Umbraco.Core/Models/PublicAccessEntry.cs b/src/Umbraco.Core/Models/PublicAccessEntry.cs index 26e249a35a..7fd0849e27 100644 --- a/src/Umbraco.Core/Models/PublicAccessEntry.cs +++ b/src/Umbraco.Core/Models/PublicAccessEntry.cs @@ -155,18 +155,17 @@ namespace Umbraco.Core.Models public override object DeepClone() { - var clone = (PublicAccessEntry)base.DeepClone(); + var clone = (PublicAccessEntry) base.DeepClone(); + //turn off change tracking clone.DisableChangeTracking(); if (clone._ruleCollection != null) { - clone._ruleCollection.CollectionChanged -= this._ruleCollection_CollectionChanged; //clear this event handler if any - clone._ruleCollection.CollectionChanged += clone._ruleCollection_CollectionChanged; //re-assign correct event handler + clone._ruleCollection.CollectionChanged -= _ruleCollection_CollectionChanged; //clear this event handler if any + clone._ruleCollection.CollectionChanged += clone._ruleCollection_CollectionChanged; //re-assign correct event handler } - //this shouldn't really be needed since we're not tracking - clone.ResetDirtyProperties(false); //re-enable tracking clone.EnableChangeTracking(); diff --git a/src/Umbraco.Core/Persistence/Dtos/LogDto.cs b/src/Umbraco.Core/Persistence/Dtos/LogDto.cs index a362d5d50c..9a710c1fec 100644 --- a/src/Umbraco.Core/Persistence/Dtos/LogDto.cs +++ b/src/Umbraco.Core/Persistence/Dtos/LogDto.cs @@ -5,11 +5,13 @@ using Umbraco.Core.Persistence.DatabaseModelDefinitions; namespace Umbraco.Core.Persistence.Dtos { - [TableName(Constants.DatabaseSchema.Tables.Log)] + [TableName(TableName)] [PrimaryKey("id")] [ExplicitColumns] internal class LogDto { + public const string TableName = Constants.DatabaseSchema.Tables.Log; + private int? _userId; [Column("id")] diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs index f5de3dc1d7..adb3b8c6b3 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs @@ -372,8 +372,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement content.AdjustDates(contentVersionDto.VersionDate); // names also impact 'edited' - foreach (var (culture, name) in content.CultureNames) - if (name.Name != content.GetPublishName(culture)) + foreach (var (culture, infos) in content.CultureInfos) + if (infos.Name != content.GetPublishName(culture)) (editedCultures ?? (editedCultures = new HashSet(StringComparer.OrdinalIgnoreCase))).Add(culture); // insert content variations @@ -534,8 +534,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement content.AdjustDates(contentVersionDto.VersionDate); // names also impact 'edited' - foreach (var (culture, name) in content.CultureNames) - if (name.Name != content.GetPublishName(culture)) + foreach (var (culture, infos) in content.CultureInfos) + if (infos.Name != content.GetPublishName(culture)) { edited = true; (editedCultures ?? (editedCultures = new HashSet(StringComparer.OrdinalIgnoreCase))).Add(culture); @@ -1131,7 +1131,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private IEnumerable GetContentVariationDtos(IContent content, bool publishing) { // create dtos for the 'current' (non-published) version, all cultures - foreach (var (culture, name) in content.CultureNames) + foreach (var (culture, name) in content.CultureInfos) yield return new ContentVersionCultureVariationDto { VersionId = content.VersionId, @@ -1146,7 +1146,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement if (!publishing) yield break; // create dtos for the 'published' version, for published cultures (those having a name) - foreach (var (culture, name) in content.PublishNames) + foreach (var (culture, name) in content.PublishCultureInfos) yield return new ContentVersionCultureVariationDto { VersionId = content.PublishedVersionId, @@ -1219,15 +1219,15 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { // content varies by culture // then it must have at least a variant name, else it makes no sense - if (content.CultureNames.Count == 0) + if (content.CultureInfos.Count == 0) throw new InvalidOperationException("Cannot save content with an empty name."); // and then, we need to set the invariant name implicitely, // using the default culture if it has a name, otherwise anything we can var defaultCulture = LanguageRepository.GetDefaultIsoCode(); - content.Name = defaultCulture != null && content.CultureNames.TryGetValue(defaultCulture, out var cultureName) + content.Name = defaultCulture != null && content.CultureInfos.TryGetValue(defaultCulture, out var cultureName) ? cultureName.Name - : content.CultureNames.First().Value.Name; + : content.CultureInfos.First().Value.Name; } else { @@ -1260,7 +1260,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private void EnsureVariantNamesAreUnique(Content content, bool publishing) { - if (!EnsureUniqueNaming || !content.ContentType.VariesByCulture() || content.CultureNames.Count == 0) return; + if (!EnsureUniqueNaming || !content.ContentType.VariesByCulture() || content.CultureInfos.Count == 0) return; // get names per culture, at same level (ie all siblings) var sql = SqlEnsureVariantNamesAreUnique.Sql(true, NodeObjectTypeId, content.ParentId, content.Id); @@ -1274,7 +1274,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement // of whether the name has changed (ie the culture has been updated) - some saving culture // fr-FR could cause culture en-UK name to change - not sure that is clean - foreach (var (culture, name) in content.CultureNames) + foreach (var (culture, name) in content.CultureInfos) { var langId = LanguageRepository.GetIdByIsoCode(culture); if (!langId.HasValue) continue; @@ -1288,7 +1288,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement // update the name, and the publish name if published content.SetCultureName(uniqueName, culture); - if (publishing && content.PublishNames.ContainsKey(culture)) + if (publishing && content.PublishCultureInfos.ContainsKey(culture)) content.SetPublishInfo(culture, uniqueName, DateTime.Now); } } diff --git a/src/Umbraco.Core/Services/Implement/ContentService.cs b/src/Umbraco.Core/Services/Implement/ContentService.cs index 2af6de24c7..ebdbe8d83e 100644 --- a/src/Umbraco.Core/Services/Implement/ContentService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentService.cs @@ -849,7 +849,7 @@ namespace Umbraco.Core.Services.Implement //track the cultures that have changed var culturesChanging = content.ContentType.VariesByCulture() - ? string.Join(",", content.CultureNames.Where(x => x.Value.IsDirty()).Select(x => x.Key)) + ? string.Join(",", content.CultureInfos.Where(x => x.Value.IsDirty()).Select(x => x.Key)) : null; //TODO: Currently there's no way to change track which variant properties have changed, we only have change // tracking enabled on all values on the Property which doesn't allow us to know which variants have changed. @@ -1082,7 +1082,7 @@ namespace Umbraco.Core.Services.Implement } else { - culturesChanging = string.Join(",", content.PublishNames.Where(x => x.Value.IsDirty()).Select(x => x.Key)); + culturesChanging = string.Join(",", content.PublishCultureInfos.Where(x => x.Value.IsDirty()).Select(x => x.Key)); } } @@ -1865,7 +1865,7 @@ namespace Umbraco.Core.Services.Implement //track the cultures changing for auditing var culturesChanging = content.ContentType.VariesByCulture() - ? string.Join(",", content.CultureNames.Where(x => x.Value.IsDirty()).Select(x => x.Key)) + ? string.Join(",", content.CultureInfos.Where(x => x.Value.IsDirty()).Select(x => x.Key)) : null; //TODO: Currently there's no way to change track which variant properties have changed, we only have change // tracking enabled on all values on the Property which doesn't allow us to know which variants have changed. @@ -2604,7 +2604,7 @@ namespace Umbraco.Core.Services.Implement //Logging & Audit message Logger.Info("User '{UserId}' rolled back content '{ContentId}' to version '{VersionId}'", userId, id, versionId); - Audit(AuditType.RollBack, $"Content '{content.Name}' was rolled back to version '{versionId}'", userId, id); + Audit(AuditType.RollBack, userId, id, $"Content '{content.Name}' was rolled back to version '{versionId}'"); } scope.Complete(); diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index bc6c8fee54..e0aa93efec 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -376,8 +376,8 @@ - - + + diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index 1c3e2453c3..807231730b 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -53,23 +53,23 @@ namespace Umbraco.Tests.Models contentType.Variations = ContentVariation.Culture; - Assert.IsFalse(content.IsPropertyDirty("CultureNames")); //hasn't been changed + Assert.IsFalse(content.IsPropertyDirty("CultureInfos")); //hasn't been changed Thread.Sleep(500); //The "Date" wont be dirty if the test runs too fast since it will be the same date content.SetCultureName("name-fr", langFr); - Assert.IsTrue(content.IsPropertyDirty("CultureNames")); //now it will be changed since the collection has changed - var frCultureName = content.CultureNames[langFr]; + Assert.IsTrue(content.IsPropertyDirty("CultureInfos")); //now it will be changed since the collection has changed + var frCultureName = content.CultureInfos[langFr]; Assert.IsTrue(frCultureName.IsPropertyDirty("Date")); content.ResetDirtyProperties(); - Assert.IsFalse(content.IsPropertyDirty("CultureNames")); //it's been reset - Assert.IsTrue(content.WasPropertyDirty("CultureNames")); + Assert.IsFalse(content.IsPropertyDirty("CultureInfos")); //it's been reset + Assert.IsTrue(content.WasPropertyDirty("CultureInfos")); Thread.Sleep(500); //The "Date" wont be dirty if the test runs too fast since it will be the same date content.SetCultureName("name-fr", langFr); Assert.IsTrue(frCultureName.IsPropertyDirty("Date")); - Assert.IsTrue(content.IsPropertyDirty("CultureNames")); //it's true now since we've updated a name + Assert.IsTrue(content.IsPropertyDirty("CultureInfos")); //it's true now since we've updated a name } [Test] @@ -82,25 +82,25 @@ namespace Umbraco.Tests.Models contentType.Variations = ContentVariation.Culture; - Assert.IsFalse(content.IsPropertyDirty("PublishNames")); //hasn't been changed + Assert.IsFalse(content.IsPropertyDirty("PublishCultureInfos")); //hasn't been changed Thread.Sleep(500); //The "Date" wont be dirty if the test runs too fast since it will be the same date content.SetCultureName("name-fr", langFr); content.PublishCulture(langFr); //we've set the name, now we're publishing it - Assert.IsTrue(content.IsPropertyDirty("PublishNames")); //now it will be changed since the collection has changed - var frCultureName = content.PublishNames[langFr]; + Assert.IsTrue(content.IsPropertyDirty("PublishCultureInfos")); //now it will be changed since the collection has changed + var frCultureName = content.PublishCultureInfos[langFr]; Assert.IsTrue(frCultureName.IsPropertyDirty("Date")); content.ResetDirtyProperties(); - Assert.IsFalse(content.IsPropertyDirty("PublishNames")); //it's been reset - Assert.IsTrue(content.WasPropertyDirty("PublishNames")); + Assert.IsFalse(content.IsPropertyDirty("PublishCultureInfos")); //it's been reset + Assert.IsTrue(content.WasPropertyDirty("PublishCultureInfos")); Thread.Sleep(500); //The "Date" wont be dirty if the test runs too fast since it will be the same date content.SetCultureName("name-fr", langFr); content.PublishCulture(langFr); //we've set the name, now we're publishing it Assert.IsTrue(frCultureName.IsPropertyDirty("Date")); - Assert.IsTrue(content.IsPropertyDirty("PublishNames")); //it's true now since we've updated a name + Assert.IsTrue(content.IsPropertyDirty("PublishCultureInfos")); //it's true now since we've updated a name } [Test] diff --git a/src/Umbraco.Tests/Models/VariationTests.cs b/src/Umbraco.Tests/Models/VariationTests.cs index 8a996f9782..e6f4e53d26 100644 --- a/src/Umbraco.Tests/Models/VariationTests.cs +++ b/src/Umbraco.Tests/Models/VariationTests.cs @@ -236,11 +236,11 @@ namespace Umbraco.Tests.Models Assert.AreEqual("name-uk", content.GetCultureName(langUk)); // variant dictionary of names work - Assert.AreEqual(2, content.CultureNames.Count); - Assert.IsTrue(content.CultureNames.ContainsKey(langFr)); - Assert.AreEqual("name-fr", content.CultureNames[langFr].Name); - Assert.IsTrue(content.CultureNames.ContainsKey(langUk)); - Assert.AreEqual("name-uk", content.CultureNames[langUk].Name); + Assert.AreEqual(2, content.CultureInfos.Count); + Assert.IsTrue(content.CultureInfos.ContainsKey(langFr)); + Assert.AreEqual("name-fr", content.CultureInfos[langFr].Name); + Assert.IsTrue(content.CultureInfos.ContainsKey(langUk)); + Assert.AreEqual("name-uk", content.CultureInfos[langUk].Name); } [Test] diff --git a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs index 62c3116ab1..9f84d9faf5 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs @@ -767,7 +767,7 @@ namespace Umbraco.Tests.Persistence.Repositories foreach (var r in result) { var isInvariant = r.ContentType.Alias == "umbInvariantTextpage"; - var name = isInvariant ? r.Name : r.CultureNames["en-US"].Name; + var name = isInvariant ? r.Name : r.CultureInfos["en-US"].Name; var namePrefix = isInvariant ? "INV" : "VAR"; //ensure the correct name (invariant vs variant) is in the result diff --git a/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs index 4557dfb1bd..d5da9ecb51 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentMapperProfile.cs @@ -132,7 +132,7 @@ namespace Umbraco.Web.Models.Mapping // if we don't have a name for a culture, it means the culture is not available, and // hey we should probably not be mapping it, but it's too late, return a fallback name - return source.CultureNames.TryGetValue(culture, out var name) && !name.Name.IsNullOrWhiteSpace() ? name.Name : $"(({source.Name}))"; + return source.CultureInfos.TryGetValue(culture, out var name) && !name.Name.IsNullOrWhiteSpace() ? name.Name : $"(({source.Name}))"; } } } diff --git a/src/Umbraco.Web/Models/Mapping/MemberMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/MemberMapperProfile.cs index f64d8dc529..0cfa3cf154 100644 --- a/src/Umbraco.Web/Models/Mapping/MemberMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/MemberMapperProfile.cs @@ -48,7 +48,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.CreatorId, opt => opt.Ignore()) .ForMember(dest => dest.Level, opt => opt.Ignore()) .ForMember(dest => dest.Name, opt => opt.Ignore()) - .ForMember(dest => dest.CultureNames, opt => opt.Ignore()) + .ForMember(dest => dest.CultureInfos, opt => opt.Ignore()) .ForMember(dest => dest.ParentId, opt => opt.Ignore()) .ForMember(dest => dest.Path, opt => opt.Ignore()) .ForMember(dest => dest.SortOrder, opt => opt.Ignore()) diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs index 355a4e7644..f414702824 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs @@ -1193,9 +1193,9 @@ namespace Umbraco.Web.PublishedCache.NuCache var names = content is IContent document ? (published - ? document.PublishNames - : document.CultureNames) - : content.CultureNames; + ? document.PublishCultureInfos + : document.CultureInfos) + : content.CultureInfos; foreach (var (culture, name) in names) { diff --git a/src/Umbraco.Web/umbraco.presentation/page.cs b/src/Umbraco.Web/umbraco.presentation/page.cs index ea1a563f9c..e8d395881c 100644 --- a/src/Umbraco.Web/umbraco.presentation/page.cs +++ b/src/Umbraco.Web/umbraco.presentation/page.cs @@ -395,7 +395,7 @@ namespace umbraco if (_cultureInfos != null) return _cultureInfos; - return _cultureInfos = _inner.PublishNames + return _cultureInfos = _inner.PublishCultureInfos .ToDictionary(x => x.Key, x => new PublishedCultureInfo(x.Key, x.Value.Name, x.Value.Date)); } }