Enhance implementation of ObservableDictionary so we can re-use this in more places, changes CultureNameCollection to ObservableDictionary, fixes issue with dirty tracking changed property type collections ... this was working by pure fluke before! Fixes more tests.
This commit is contained in:
@@ -1,16 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Collections
|
||||
{
|
||||
/// <summary>
|
||||
/// A readonly keyed collection
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public interface IReadOnlyKeyedCollection<TKey, TVal> : IReadOnlyList<TVal>
|
||||
{
|
||||
IEnumerable<TKey> Keys { get; }
|
||||
bool TryGetValue(TKey key, out TVal val);
|
||||
TVal this[string key] { get; }
|
||||
bool Contains(TKey key);
|
||||
}
|
||||
}
|
||||
@@ -14,20 +14,21 @@ namespace Umbraco.Core.Collections
|
||||
/// </remarks>
|
||||
/// <typeparam name="TValue">The type of elements contained in the BindableCollection</typeparam>
|
||||
/// <typeparam name="TKey">The type of the indexing key</typeparam>
|
||||
public class ObservableDictionary<TKey, TValue> : ObservableCollection<TValue>
|
||||
public class ObservableDictionary<TKey, TValue> : ObservableCollection<TValue>, IReadOnlyDictionary<TKey, TValue>, IDictionary<TKey, TValue>
|
||||
{
|
||||
protected Dictionary<TKey, int> Indecies = new Dictionary<TKey, int>();
|
||||
protected Func<TValue, TKey> KeySelector;
|
||||
protected Dictionary<TKey, int> Indecies { get; }
|
||||
protected Func<TValue, TKey> KeySelector { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create new ObservableDictionary
|
||||
/// </summary>
|
||||
/// <param name="keySelector">Selector function to create key from value</param>
|
||||
public ObservableDictionary(Func<TValue, TKey> keySelector)
|
||||
public ObservableDictionary(Func<TValue, TKey> keySelector, IEqualityComparer<TKey> equalityComparer = null)
|
||||
: base()
|
||||
{
|
||||
if (keySelector == null) throw new ArgumentException("keySelector");
|
||||
KeySelector = keySelector;
|
||||
Indecies = new Dictionary<TKey, int>(equalityComparer);
|
||||
}
|
||||
|
||||
#region Protected Methods
|
||||
@@ -73,7 +74,7 @@ namespace Umbraco.Core.Collections
|
||||
}
|
||||
#endregion
|
||||
|
||||
public virtual bool ContainsKey(TKey key)
|
||||
public bool ContainsKey(TKey key)
|
||||
{
|
||||
return Indecies.ContainsKey(key);
|
||||
}
|
||||
@@ -83,7 +84,7 @@ namespace Umbraco.Core.Collections
|
||||
/// </summary>
|
||||
/// <param name="key">Key of element to replace</param>
|
||||
/// <returns></returns>
|
||||
public virtual TValue this[TKey key]
|
||||
public TValue this[TKey key]
|
||||
{
|
||||
|
||||
get { return this[Indecies[key]]; }
|
||||
@@ -112,7 +113,7 @@ namespace Umbraco.Core.Collections
|
||||
///
|
||||
/// <exception cref="InvalidOperationException"></exception>
|
||||
/// <returns>False if key not found</returns>
|
||||
public virtual bool Replace(TKey key, TValue value)
|
||||
public bool Replace(TKey key, TValue value)
|
||||
{
|
||||
if (!Indecies.ContainsKey(key)) return false;
|
||||
//confirm key matches
|
||||
@@ -124,7 +125,7 @@ namespace Umbraco.Core.Collections
|
||||
|
||||
}
|
||||
|
||||
public virtual bool Remove(TKey key)
|
||||
public bool Remove(TKey key)
|
||||
{
|
||||
if (!Indecies.ContainsKey(key)) return false;
|
||||
|
||||
@@ -138,7 +139,7 @@ namespace Umbraco.Core.Collections
|
||||
/// </summary>
|
||||
/// <param name="currentKey"></param>
|
||||
/// <param name="newKey"></param>
|
||||
public virtual void ChangeKey(TKey currentKey, TKey newKey)
|
||||
public void ChangeKey(TKey currentKey, TKey newKey)
|
||||
{
|
||||
if (!Indecies.ContainsKey(currentKey))
|
||||
{
|
||||
@@ -155,6 +156,75 @@ namespace Umbraco.Core.Collections
|
||||
Indecies.Add(newKey, currentIndex);
|
||||
}
|
||||
|
||||
#region IDictionary and IReadOnlyDictionary implementation
|
||||
|
||||
public bool TryGetValue(TKey key, out TValue val)
|
||||
{
|
||||
if (Indecies.TryGetValue(key, out var index))
|
||||
{
|
||||
val = this[index];
|
||||
return true;
|
||||
}
|
||||
val = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all keys
|
||||
/// </summary>
|
||||
public IEnumerable<TKey> Keys => Indecies.Keys;
|
||||
|
||||
/// <summary>
|
||||
/// Returns all values
|
||||
/// </summary>
|
||||
public IEnumerable<TValue> Values => base.Items;
|
||||
|
||||
ICollection<TKey> IDictionary<TKey, TValue>.Keys => Indecies.Keys;
|
||||
|
||||
//this will never be used
|
||||
ICollection<TValue> IDictionary<TKey, TValue>.Values => Values.ToList();
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
|
||||
{
|
||||
foreach (var i in Values)
|
||||
{
|
||||
var key = KeySelector(i);
|
||||
yield return new KeyValuePair<TKey, TValue>(key, i);
|
||||
}
|
||||
}
|
||||
|
||||
void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
|
||||
{
|
||||
Add(value);
|
||||
}
|
||||
|
||||
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
Add(item.Value);
|
||||
}
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
return ContainsKey(item.Key);
|
||||
}
|
||||
|
||||
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
return Remove(item.Key);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
internal class DuplicateKeyException : Exception
|
||||
{
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace Umbraco.Core.Models
|
||||
public readonly PropertyInfo PublishedSelector = ExpressionHelper.GetPropertyInfo<Content, bool>(x => x.Published);
|
||||
public readonly PropertyInfo ReleaseDateSelector = ExpressionHelper.GetPropertyInfo<Content, DateTime?>(x => x.ReleaseDate);
|
||||
public readonly PropertyInfo ExpireDateSelector = ExpressionHelper.GetPropertyInfo<Content, DateTime?>(x => x.ExpireDate);
|
||||
public readonly PropertyInfo PublishNamesSelector = ExpressionHelper.GetPropertyInfo<Content, IReadOnlyCollection<CultureName>>(x => x.PublishNames);
|
||||
public readonly PropertyInfo PublishNamesSelector = ExpressionHelper.GetPropertyInfo<Content, IReadOnlyDictionary<string, CultureName>>(x => x.PublishNames);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -224,13 +224,13 @@ namespace Umbraco.Core.Models
|
||||
public bool IsCulturePublished(string culture)
|
||||
// just check _publishInfos
|
||||
// a non-available culture could not become published anyways
|
||||
=> _publishInfos != null && _publishInfos.Contains(culture);
|
||||
=> _publishInfos != null && _publishInfos.ContainsKey(culture);
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool WasCulturePublished(string culture)
|
||||
// just check _publishInfosOrig - a copy of _publishInfos
|
||||
// a non-available culture could not become published anyways
|
||||
=> _publishInfosOrig != null && _publishInfosOrig.Contains(culture);
|
||||
=> _publishInfosOrig != null && _publishInfosOrig.ContainsKey(culture);
|
||||
|
||||
// adjust dates to sync between version, cultures etc
|
||||
// used by the repo when persisting
|
||||
@@ -260,7 +260,7 @@ namespace Umbraco.Core.Models
|
||||
|
||||
/// <inheritdoc/>
|
||||
[IgnoreDataMember]
|
||||
public IReadOnlyKeyedCollection<string, CultureName> PublishNames => _publishInfos ?? NoNames;
|
||||
public IReadOnlyDictionary<string, CultureName> PublishNames => _publishInfos ?? NoNames;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string GetPublishName(string culture)
|
||||
@@ -508,6 +508,9 @@ namespace Umbraco.Core.Models
|
||||
//turn off change tracking
|
||||
clone.DisableChangeTracking();
|
||||
|
||||
//need to manually clone this since it's not settable
|
||||
clone._contentType = (IContentType)ContentType.DeepClone();
|
||||
|
||||
//if culture infos exist then deal with event bindings
|
||||
if (clone._publishInfos != null)
|
||||
{
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace Umbraco.Core.Models
|
||||
public readonly PropertyInfo DefaultContentTypeIdSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.ContentTypeId);
|
||||
public readonly PropertyInfo PropertyCollectionSelector = ExpressionHelper.GetPropertyInfo<ContentBase, PropertyCollection>(x => x.Properties);
|
||||
public readonly PropertyInfo WriterSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.WriterId);
|
||||
public readonly PropertyInfo CultureNamesSelector = ExpressionHelper.GetPropertyInfo<ContentBase, IReadOnlyCollection<CultureName>>(x => x.CultureNames);
|
||||
public readonly PropertyInfo CultureNamesSelector = ExpressionHelper.GetPropertyInfo<ContentBase, IReadOnlyDictionary<string, CultureName>>(x => x.CultureNames);
|
||||
}
|
||||
|
||||
protected void PropertiesChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
@@ -156,11 +156,11 @@ namespace Umbraco.Core.Models
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsCultureAvailable(string culture)
|
||||
=> _cultureInfos != null && _cultureInfos.Contains(culture);
|
||||
=> _cultureInfos != null && _cultureInfos.ContainsKey(culture);
|
||||
|
||||
/// <inheritdoc />
|
||||
[DataMember]
|
||||
public virtual IReadOnlyKeyedCollection<string, CultureName> CultureNames => _cultureInfos ?? NoNames;
|
||||
public virtual IReadOnlyDictionary<string, CultureName> CultureNames => _cultureInfos ?? NoNames;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetCultureName(string culture)
|
||||
@@ -373,7 +373,7 @@ namespace Umbraco.Core.Models
|
||||
foreach (var (otherCulture, otherName) in other.CultureNames)
|
||||
{
|
||||
if (culture == "*" || culture == otherCulture)
|
||||
SetCultureName(otherName, otherCulture);
|
||||
SetCultureName(otherName.Name, otherCulture);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Umbraco.Core.Models
|
||||
private bool _allowedAsRoot; // note: only one that's not 'pure element type'
|
||||
private bool _isContainer;
|
||||
private PropertyGroupCollection _propertyGroups;
|
||||
private PropertyTypeCollection _propertyTypes;
|
||||
private PropertyTypeCollection _noGroupPropertyTypes;
|
||||
private IEnumerable<ContentTypeSort> _allowedContentTypes;
|
||||
private bool _hasPropertyTypeBeenRemoved;
|
||||
private ContentVariation _variations;
|
||||
@@ -43,8 +43,8 @@ namespace Umbraco.Core.Models
|
||||
|
||||
// actually OK as IsPublishing is constant
|
||||
// ReSharper disable once VirtualMemberCallInConstructor
|
||||
_propertyTypes = new PropertyTypeCollection(IsPublishing);
|
||||
_propertyTypes.CollectionChanged += PropertyTypesChanged;
|
||||
_noGroupPropertyTypes = new PropertyTypeCollection(IsPublishing);
|
||||
_noGroupPropertyTypes.CollectionChanged += PropertyTypesChanged;
|
||||
|
||||
_variations = ContentVariation.Nothing;
|
||||
}
|
||||
@@ -64,8 +64,8 @@ namespace Umbraco.Core.Models
|
||||
|
||||
// actually OK as IsPublishing is constant
|
||||
// ReSharper disable once VirtualMemberCallInConstructor
|
||||
_propertyTypes = new PropertyTypeCollection(IsPublishing);
|
||||
_propertyTypes.CollectionChanged += PropertyTypesChanged;
|
||||
_noGroupPropertyTypes = new PropertyTypeCollection(IsPublishing);
|
||||
_noGroupPropertyTypes.CollectionChanged += PropertyTypesChanged;
|
||||
|
||||
_variations = ContentVariation.Nothing;
|
||||
}
|
||||
@@ -248,7 +248,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
get
|
||||
{
|
||||
return _propertyTypes.Union(PropertyGroups.SelectMany(x => x.PropertyTypes));
|
||||
return _noGroupPropertyTypes.Union(PropertyGroups.SelectMany(x => x.PropertyTypes));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,12 +261,12 @@ namespace Umbraco.Core.Models
|
||||
[DoNotClone]
|
||||
public IEnumerable<PropertyType> NoGroupPropertyTypes
|
||||
{
|
||||
get => _propertyTypes;
|
||||
get => _noGroupPropertyTypes;
|
||||
set
|
||||
{
|
||||
_propertyTypes = new PropertyTypeCollection(IsPublishing, value);
|
||||
_propertyTypes.CollectionChanged += PropertyTypesChanged;
|
||||
PropertyTypesChanged(_propertyTypes, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
_noGroupPropertyTypes = new PropertyTypeCollection(IsPublishing, value);
|
||||
_noGroupPropertyTypes.CollectionChanged += PropertyTypesChanged;
|
||||
PropertyTypesChanged(_noGroupPropertyTypes, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
if (PropertyTypeExists(propertyType.Alias) == false)
|
||||
{
|
||||
_propertyTypes.Add(propertyType);
|
||||
_noGroupPropertyTypes.Add(propertyType);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -384,7 +384,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
//check through each local property type collection (not assigned to a tab)
|
||||
if (_propertyTypes.RemoveItem(propertyTypeAlias))
|
||||
if (_noGroupPropertyTypes.RemoveItem(propertyTypeAlias))
|
||||
{
|
||||
if (!HasPropertyTypeBeenRemoved)
|
||||
{
|
||||
@@ -408,7 +408,7 @@ namespace Umbraco.Core.Models
|
||||
foreach (var property in group.PropertyTypes)
|
||||
{
|
||||
property.PropertyGroupId = null;
|
||||
_propertyTypes.Add(property);
|
||||
_noGroupPropertyTypes.Add(property);
|
||||
}
|
||||
|
||||
// actually remove the group
|
||||
@@ -421,7 +421,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
//fixme should we mark this as EditorBrowsable hidden since it really isn't ever used?
|
||||
internal PropertyTypeCollection PropertyTypeCollection => _propertyTypes;
|
||||
internal PropertyTypeCollection PropertyTypeCollection => _noGroupPropertyTypes;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the current entity is dirty.
|
||||
@@ -474,15 +474,15 @@ namespace Umbraco.Core.Models
|
||||
//turn off change tracking
|
||||
clone.DisableChangeTracking();
|
||||
|
||||
if (clone._propertyTypes != null)
|
||||
if (clone._noGroupPropertyTypes != null)
|
||||
{
|
||||
//need to manually wire up the event handlers for the property type collections - we've ensured
|
||||
// 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._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._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
|
||||
}
|
||||
|
||||
if (clone._propertyGroups != null)
|
||||
|
||||
@@ -12,13 +12,14 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// The culture names of a content's variants
|
||||
/// </summary>
|
||||
public class CultureNameCollection : KeyedCollection<string, CultureName>, INotifyCollectionChanged, IDeepCloneable, IReadOnlyKeyedCollection<string, CultureName>
|
||||
public class CultureNameCollection : ObservableDictionary<string, CultureName>, IDeepCloneable
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new collection from another collection
|
||||
/// </summary>
|
||||
/// <param name="names"></param>
|
||||
public CultureNameCollection(IEnumerable<CultureName> names) : base(StringComparer.InvariantCultureIgnoreCase)
|
||||
public CultureNameCollection(IEnumerable<CultureName> names)
|
||||
: base(x => x.Culture, StringComparer.InvariantCultureIgnoreCase)
|
||||
{
|
||||
foreach (var n in names)
|
||||
Add(n);
|
||||
@@ -27,21 +28,11 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Creates a new collection
|
||||
/// </summary>
|
||||
public CultureNameCollection() : base(StringComparer.InvariantCultureIgnoreCase)
|
||||
public CultureNameCollection()
|
||||
: base(x => x.Culture, StringComparer.InvariantCultureIgnoreCase)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all keys in the collection
|
||||
/// </summary>
|
||||
public IEnumerable<string> Keys => Dictionary != null ? Dictionary.Keys : this.Select(x => x.Culture);
|
||||
|
||||
public bool TryGetValue(string culture, out CultureName name)
|
||||
{
|
||||
name = this.FirstOrDefault(x => x.Culture.InvariantEquals(culture));
|
||||
return name != null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Add or update the <see cref="CultureName"/>
|
||||
/// </summary>
|
||||
@@ -63,78 +54,20 @@ namespace Umbraco.Core.Models
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the index for a specified culture
|
||||
/// </summary>
|
||||
public int IndexOfKey(string key)
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
if (this[i].Culture.InvariantEquals(key))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
||||
|
||||
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
|
||||
{
|
||||
CollectionChanged?.Invoke(this, args);
|
||||
}
|
||||
|
||||
public object DeepClone()
|
||||
{
|
||||
var clone = new CultureNameCollection();
|
||||
foreach (var name in this)
|
||||
{
|
||||
clone.Add((CultureName)name.DeepClone());
|
||||
name.DisableChangeTracking();
|
||||
var copy = (CultureName)name.DeepClone();
|
||||
copy.ResetDirtyProperties(false);
|
||||
clone.Add(copy);
|
||||
name.EnableChangeTracking();
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
protected override string GetKeyForItem(CultureName item)
|
||||
{
|
||||
return item.Culture;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the collection to only contain the <see cref="CultureName"/> instances referenced in the <paramref name="names"/> parameter.
|
||||
/// </summary>
|
||||
/// <param name="names">The property groups.</param>
|
||||
/// <remarks></remarks>
|
||||
internal void Reset(IEnumerable<CultureName> names)
|
||||
{
|
||||
Clear();
|
||||
foreach (var name in names)
|
||||
Add(name);
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
|
||||
protected override void SetItem(int index, CultureName item)
|
||||
{
|
||||
base.SetItem(index, item);
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
|
||||
}
|
||||
|
||||
protected override void RemoveItem(int index)
|
||||
{
|
||||
var removed = this[index];
|
||||
base.RemoveItem(index);
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, removed));
|
||||
}
|
||||
|
||||
protected override void InsertItem(int index, CultureName item)
|
||||
{
|
||||
base.InsertItem(index, item);
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
|
||||
}
|
||||
|
||||
protected override void ClearItems()
|
||||
{
|
||||
base.ClearItems();
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ namespace Umbraco.Core.Models
|
||||
/// <para>Because a dictionary key cannot be <c>null</c> this cannot get the invariant
|
||||
/// name, which must be get via the <see cref="PublishName"/> property.</para>
|
||||
/// </remarks>
|
||||
IReadOnlyKeyedCollection<string, CultureName> PublishNames { get; }
|
||||
IReadOnlyDictionary<string, CultureName> PublishNames { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the published cultures.
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace Umbraco.Core.Models
|
||||
/// <para>Because a dictionary key cannot be <c>null</c> this cannot contain the invariant
|
||||
/// culture name, which must be get or set via the <see cref="TreeEntityBase.Name"/> property.</para>
|
||||
/// </remarks>
|
||||
IReadOnlyKeyedCollection<string, CultureName> CultureNames { get; }
|
||||
IReadOnlyDictionary<string, CultureName> CultureNames { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the available cultures.
|
||||
|
||||
@@ -14,10 +14,12 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract]
|
||||
//TODO: Change this to ObservableDictionary so we can reduce the INotifyCollectionChanged implementation details
|
||||
public class PropertyGroupCollection : KeyedCollection<string, PropertyGroup>, INotifyCollectionChanged, IDeepCloneable
|
||||
{
|
||||
private readonly ReaderWriterLockSlim _addLocker = new ReaderWriterLockSlim();
|
||||
|
||||
//fixme: this doesn't seem to be used anywhere
|
||||
internal Action OnAdd;
|
||||
|
||||
internal PropertyGroupCollection()
|
||||
|
||||
@@ -13,11 +13,13 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract]
|
||||
//TODO: Change this to ObservableDictionary so we can reduce the INotifyCollectionChanged implementation details
|
||||
public class PropertyTypeCollection : KeyedCollection<string, PropertyType>, INotifyCollectionChanged, IDeepCloneable
|
||||
{
|
||||
[IgnoreDataMember]
|
||||
private readonly ReaderWriterLockSlim _addLocker = new ReaderWriterLockSlim();
|
||||
|
||||
//fixme: This doesn't seem to be used
|
||||
[IgnoreDataMember]
|
||||
internal Action OnAdd;
|
||||
|
||||
|
||||
@@ -326,9 +326,11 @@ AND umbracoNode.id <> @id",
|
||||
});
|
||||
}
|
||||
|
||||
// delete property types
|
||||
// ... by excepting entries from db with entries from collections
|
||||
if (entity.IsPropertyDirty("PropertyTypes") || entity.PropertyTypes.Any(x => x.IsDirty()))
|
||||
// Delete property types ... by excepting entries from db with entries from collections.
|
||||
// We check if the entity's own PropertyTypes has been modified and then also check
|
||||
// any of the property groups PropertyTypes has been modified.
|
||||
// This specifically tells us if any property type collections have changed.
|
||||
if (entity.IsPropertyDirty("PropertyTypes") || entity.PropertyGroups.Any(x => x.IsPropertyDirty("PropertyTypes")))
|
||||
{
|
||||
var dbPropertyTypes = Database.Fetch<PropertyTypeDto>("WHERE contentTypeId = @Id", new { entity.Id });
|
||||
var dbPropertyTypeAlias = dbPropertyTypes.Select(x => x.Id);
|
||||
@@ -338,10 +340,11 @@ AND umbracoNode.id <> @id",
|
||||
DeletePropertyType(entity.Id, item);
|
||||
}
|
||||
|
||||
// delete tabs
|
||||
// ... by excepting entries from db with entries from collections
|
||||
// Delete tabs ... by excepting entries from db with entries from collections.
|
||||
// We check if the entity's own PropertyGroups has been modified.
|
||||
// This specifically tells us if the property group collections have changed.
|
||||
List<int> orphanPropertyTypeIds = null;
|
||||
if (entity.IsPropertyDirty("PropertyGroups") || entity.PropertyGroups.Any(x => x.IsDirty()))
|
||||
if (entity.IsPropertyDirty("PropertyGroups"))
|
||||
{
|
||||
// todo
|
||||
// we used to try to propagate tabs renaming downstream, relying on ParentId, but
|
||||
|
||||
@@ -359,7 +359,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
|
||||
// names also impact 'edited'
|
||||
foreach (var (culture, name) in content.CultureNames)
|
||||
if (name != content.GetPublishName(culture))
|
||||
if (name.Name != content.GetPublishName(culture))
|
||||
(editedCultures ?? (editedCultures = new HashSet<string>(StringComparer.OrdinalIgnoreCase))).Add(culture);
|
||||
|
||||
// insert content variations
|
||||
@@ -521,7 +521,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
|
||||
// names also impact 'edited'
|
||||
foreach (var (culture, name) in content.CultureNames)
|
||||
if (name != content.GetPublishName(culture))
|
||||
if (name.Name != content.GetPublishName(culture))
|
||||
{
|
||||
edited = true;
|
||||
(editedCultures ?? (editedCultures = new HashSet<string>(StringComparer.OrdinalIgnoreCase))).Add(culture);
|
||||
@@ -1120,7 +1120,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
VersionId = content.VersionId,
|
||||
LanguageId = LanguageRepository.GetIdByIsoCode(culture) ?? throw new InvalidOperationException("Not a valid culture."),
|
||||
Culture = culture,
|
||||
Name = name,
|
||||
Name = name.Name,
|
||||
UpdateDate = content.GetUpdateDate(culture) ?? DateTime.MinValue // we *know* there is a value
|
||||
};
|
||||
|
||||
@@ -1135,7 +1135,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
VersionId = content.PublishedVersionId,
|
||||
LanguageId = LanguageRepository.GetIdByIsoCode(culture) ?? throw new InvalidOperationException("Not a valid culture."),
|
||||
Culture = culture,
|
||||
Name = name,
|
||||
Name = name.Name,
|
||||
UpdateDate = content.GetPublishDate(culture) ?? DateTime.MinValue // we *know* there is a value
|
||||
};
|
||||
}
|
||||
@@ -1210,7 +1210,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
var defaultCulture = LanguageRepository.GetDefaultIsoCode();
|
||||
content.Name = defaultCulture != null && content.CultureNames.TryGetValue(defaultCulture, out var cultureName)
|
||||
? cultureName.Name
|
||||
: content.CultureNames[0].Name;
|
||||
: content.CultureNames.First().Value.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1265,13 +1265,13 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
|
||||
// get a unique name
|
||||
var otherNames = cultureNames.Select(x => new SimilarNodeName { Id = x.Id, Name = x.Name });
|
||||
var uniqueName = SimilarNodeName.GetUniqueName(otherNames, 0, name);
|
||||
var uniqueName = SimilarNodeName.GetUniqueName(otherNames, 0, name.Name);
|
||||
|
||||
if (uniqueName == content.GetCultureName(culture)) continue;
|
||||
|
||||
// update the name, and the publish name if published
|
||||
content.SetCultureName(uniqueName, culture);
|
||||
if (publishing && content.PublishNames.Contains(culture))
|
||||
if (publishing && content.PublishNames.ContainsKey(culture))
|
||||
content.SetPublishInfo(culture, uniqueName, DateTime.Now);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
|
||||
//update the properties if they've changed
|
||||
var macro = (Macro)entity;
|
||||
if (macro.IsPropertyDirty("Properties") || macro.Properties.Any(x => x.IsDirty()))
|
||||
if (macro.IsPropertyDirty("Properties") || macro.Properties.Values.Any(x => x.IsDirty()))
|
||||
{
|
||||
var ids = dto.MacroPropertyDtos.Where(x => x.Id > 0).Select(x => x.Id).ToArray();
|
||||
if (ids.Length > 0)
|
||||
@@ -173,7 +173,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
var aliases = new Dictionary<string, string>();
|
||||
foreach (var propDto in dto.MacroPropertyDtos)
|
||||
{
|
||||
var prop = macro.Properties.FirstOrDefault(x => x.Id == propDto.Id);
|
||||
var prop = macro.Properties.Values.FirstOrDefault(x => x.Id == propDto.Id);
|
||||
if (prop == null) throw new Exception("oops: property.");
|
||||
if (propDto.Id == 0 || prop.IsPropertyDirty("Alias"))
|
||||
{
|
||||
@@ -195,7 +195,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
else
|
||||
{
|
||||
// update
|
||||
var property = macro.Properties.FirstOrDefault(x => x.Id == propDto.Id);
|
||||
var property = macro.Properties.Values.FirstOrDefault(x => x.Id == propDto.Id);
|
||||
if (property == null) throw new Exception("oops: property.");
|
||||
if (property.IsDirty())
|
||||
Database.Update(propDto);
|
||||
|
||||
@@ -836,7 +836,7 @@ namespace Umbraco.Core.Services.Implement
|
||||
|
||||
//track the cultures that have changed
|
||||
var culturesChanging = content.ContentType.VariesByCulture()
|
||||
? string.Join(",", content.CultureNames.Where(x => x.IsDirty()).Select(x => x.Culture))
|
||||
? string.Join(",", content.CultureNames.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.
|
||||
@@ -1069,7 +1069,7 @@ namespace Umbraco.Core.Services.Implement
|
||||
}
|
||||
else
|
||||
{
|
||||
culturesChanging = string.Join(",", content.PublishNames.Where(x => x.IsDirty()).Select(x => x.Culture));
|
||||
culturesChanging = string.Join(",", content.PublishNames.Where(x => x.Value.IsDirty()).Select(x => x.Key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1852,7 +1852,7 @@ namespace Umbraco.Core.Services.Implement
|
||||
|
||||
//track the cultures changing for auditing
|
||||
var culturesChanging = content.ContentType.VariesByCulture()
|
||||
? string.Join(",", content.CultureNames.Where(x => x.IsDirty()).Select(x => x.Culture))
|
||||
? string.Join(",", content.CultureNames.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.
|
||||
|
||||
@@ -1318,7 +1318,7 @@ namespace Umbraco.Core.Services.Implement
|
||||
sortOrder = int.Parse(sortOrderAttribute.Value);
|
||||
}
|
||||
|
||||
if (macro.Properties.Any(x => string.Equals(x.Alias, propertyAlias, StringComparison.OrdinalIgnoreCase))) continue;
|
||||
if (macro.Properties.Values.Any(x => string.Equals(x.Alias, propertyAlias, StringComparison.OrdinalIgnoreCase))) continue;
|
||||
macro.Properties.Add(new MacroProperty(propertyAlias, propertyName, sortOrder, editorAlias));
|
||||
sortOrder++;
|
||||
}
|
||||
|
||||
@@ -109,7 +109,6 @@
|
||||
<Compile Include="Attempt.cs" />
|
||||
<Compile Include="AttemptOfTResult.cs" />
|
||||
<Compile Include="AttemptOfTResultTStatus.cs" />
|
||||
<Compile Include="Collections\IReadOnlyKeyedCollection.cs" />
|
||||
<Compile Include="Components\AuditEventsComponent.cs" />
|
||||
<Compile Include="BindingRedirects.cs" />
|
||||
<Compile Include="ByteArrayExtensions.cs" />
|
||||
|
||||
@@ -272,7 +272,7 @@ AnotherContentFinder
|
||||
public void Resolves_Actions()
|
||||
{
|
||||
var actions = _typeLoader.GetActions();
|
||||
Assert.AreEqual(34, actions.Count());
|
||||
Assert.AreEqual(33, actions.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -237,9 +237,9 @@ namespace Umbraco.Tests.Models
|
||||
|
||||
// variant dictionary of names work
|
||||
Assert.AreEqual(2, content.CultureNames.Count);
|
||||
Assert.IsTrue(content.CultureNames.Contains(langFr));
|
||||
Assert.IsTrue(content.CultureNames.ContainsKey(langFr));
|
||||
Assert.AreEqual("name-fr", content.CultureNames[langFr].Name);
|
||||
Assert.IsTrue(content.CultureNames.Contains(langUk));
|
||||
Assert.IsTrue(content.CultureNames.ContainsKey(langUk));
|
||||
Assert.AreEqual("name-uk", content.CultureNames[langUk].Name);
|
||||
}
|
||||
|
||||
|
||||
@@ -175,7 +175,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
// Assert
|
||||
Assert.That(macro.HasIdentity, Is.True);
|
||||
Assert.That(macro.Id, Is.EqualTo(4));//With 3 existing entries the Id should be 4
|
||||
Assert.Greater(macro.Properties.Single().Id, 0);
|
||||
Assert.Greater(macro.Properties.Values.Single().Id, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,15 +268,14 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
repository.Save(macro);
|
||||
|
||||
|
||||
// Assert
|
||||
Assert.Greater(macro.Properties.First().Id, 0); //ensure id is returned
|
||||
Assert.Greater(macro.Properties.Values.First().Id, 0); //ensure id is returned
|
||||
var result = repository.Get(1);
|
||||
Assert.Greater(result.Properties.First().Id, 0);
|
||||
Assert.AreEqual(1, result.Properties.Count());
|
||||
Assert.AreEqual("new1", result.Properties.First().Alias);
|
||||
Assert.AreEqual("New1", result.Properties.First().Name);
|
||||
Assert.AreEqual(3, result.Properties.First().SortOrder);
|
||||
Assert.Greater(result.Properties.Values.First().Id, 0);
|
||||
Assert.AreEqual(1, result.Properties.Values.Count());
|
||||
Assert.AreEqual("new1", result.Properties.Values.First().Alias);
|
||||
Assert.AreEqual("New1", result.Properties.Values.First().Name);
|
||||
Assert.AreEqual(3, result.Properties.Values.First().SortOrder);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -298,10 +297,10 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
// Assert
|
||||
var result = repository.Get(macro.Id);
|
||||
Assert.AreEqual(1, result.Properties.Count());
|
||||
Assert.AreEqual("blah1", result.Properties.First().Alias);
|
||||
Assert.AreEqual("New1", result.Properties.First().Name);
|
||||
Assert.AreEqual(4, result.Properties.First().SortOrder);
|
||||
Assert.AreEqual(1, result.Properties.Values.Count());
|
||||
Assert.AreEqual("blah1", result.Properties.Values.First().Alias);
|
||||
Assert.AreEqual("New1", result.Properties.Values.First().Name);
|
||||
Assert.AreEqual(4, result.Properties.Values.First().SortOrder);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -325,7 +324,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
// Assert
|
||||
result = repository.Get(macro.Id);
|
||||
Assert.AreEqual(0, result.Properties.Count());
|
||||
Assert.AreEqual(0, result.Properties.Values.Count());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -355,8 +354,8 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
// Assert
|
||||
var result = repository.Get(macro.Id);
|
||||
|
||||
Assert.AreEqual(1, result.Properties.Count());
|
||||
Assert.AreEqual("blah2", result.Properties.Single().Alias);
|
||||
Assert.AreEqual(1, result.Properties.Values.Count());
|
||||
Assert.AreEqual("blah2", result.Properties.Values.Single().Alias);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -382,8 +381,8 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
// Assert
|
||||
var result = repository.Get(1);
|
||||
Assert.AreEqual("new1", result.Properties.First().Alias);
|
||||
Assert.AreEqual("this is a new name", result.Properties.First().Name);
|
||||
Assert.AreEqual("new1", result.Properties.Values.First().Alias);
|
||||
Assert.AreEqual("this is a new name", result.Properties.Values.First().Name);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -408,7 +407,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
// Assert
|
||||
var result = repository.Get(1);
|
||||
Assert.AreEqual("newAlias", result.Properties.First().Alias);
|
||||
Assert.AreEqual("newAlias", result.Properties.Values.First().Alias);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1308,7 +1308,7 @@ namespace Umbraco.Tests.Services
|
||||
var published = ServiceContext.ContentService.SavePublishing(content);
|
||||
//audit log will only show that french was published
|
||||
var lastLog = ServiceContext.AuditService.GetLogs(content.Id).Last();
|
||||
Assert.AreEqual($"Published culture fr-fr", lastLog.Comment);
|
||||
Assert.AreEqual($"Published cultures: fr-fr", lastLog.Comment);
|
||||
|
||||
//re-get
|
||||
content = ServiceContext.ContentService.GetById(content.Id);
|
||||
@@ -1317,7 +1317,7 @@ namespace Umbraco.Tests.Services
|
||||
published = ServiceContext.ContentService.SavePublishing(content);
|
||||
//audit log will only show that english was published
|
||||
lastLog = ServiceContext.AuditService.GetLogs(content.Id).Last();
|
||||
Assert.AreEqual($"Published culture en-uk", lastLog.Comment);
|
||||
Assert.AreEqual($"Published cultures: en-uk", lastLog.Comment);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -628,7 +628,7 @@ namespace Umbraco.Tests.Services.Importing
|
||||
|
||||
// Assert
|
||||
Assert.That(macros.Any(), Is.True);
|
||||
Assert.That(macros.First().Properties.Any(), Is.True);
|
||||
Assert.That(macros.First().Properties.Values.Any(), Is.True);
|
||||
|
||||
var allMacros = ServiceContext.MacroService.GetAll().ToList();
|
||||
foreach (var macro in macros)
|
||||
|
||||
@@ -195,7 +195,7 @@ namespace Umbraco.Tests.Services
|
||||
macro.Properties["blah1"].EditorAlias = "new";
|
||||
macro.Properties.Remove("blah3");
|
||||
|
||||
var allPropKeys = macro.Properties.Select(x => new { x.Alias, x.Key }).ToArray();
|
||||
var allPropKeys = macro.Properties.Values.Select(x => new { x.Alias, x.Key }).ToArray();
|
||||
|
||||
macroService.Save(macro);
|
||||
|
||||
@@ -228,10 +228,10 @@ namespace Umbraco.Tests.Services
|
||||
macroService.Save(macro);
|
||||
|
||||
var result1 = macroService.GetById(macro.Id);
|
||||
Assert.AreEqual(4, result1.Properties.Count());
|
||||
Assert.AreEqual(4, result1.Properties.Values.Count());
|
||||
|
||||
//simulate clearing the sections
|
||||
foreach (var s in result1.Properties.ToArray())
|
||||
foreach (var s in result1.Properties.Values.ToArray())
|
||||
{
|
||||
result1.Properties.Remove(s.Alias);
|
||||
}
|
||||
@@ -244,7 +244,7 @@ namespace Umbraco.Tests.Services
|
||||
|
||||
//re-get
|
||||
result1 = macroService.GetById(result1.Id);
|
||||
Assert.AreEqual(2, result1.Properties.Count());
|
||||
Assert.AreEqual(2, result1.Properties.Values.Count());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ using Umbraco.Web.Security;
|
||||
using Umbraco.Web.Templates;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Tests.Web
|
||||
{
|
||||
@@ -49,6 +50,8 @@ namespace Umbraco.Tests.Web
|
||||
Umbraco.Web.Composing.Current.UmbracoContextAccessor = new TestUmbracoContextAccessor();
|
||||
|
||||
Udi.ResetUdiTypes();
|
||||
|
||||
UmbracoConfig.For.SetUmbracoSettings(SettingsForTests.GetDefaultUmbracoSettings());
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
@@ -90,7 +93,7 @@ namespace Umbraco.Tests.Web
|
||||
.Returns((UmbracoContext umbCtx, IPublishedContent content, UrlProviderMode mode, string culture, Uri url) => "/my-test-url");
|
||||
|
||||
var globalSettings = SettingsForTests.GenerateMockGlobalSettings();
|
||||
|
||||
|
||||
var contentType = new PublishedContentType(666, "alias", PublishedItemType.Content, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Nothing);
|
||||
var publishedContent = Mock.Of<IPublishedContent>();
|
||||
Mock.Get(publishedContent).Setup(x => x.Id).Returns(1234);
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace Umbraco.Web.UI.Umbraco.Developer.Macros
|
||||
{
|
||||
var macroPropertyId = (HtmlInputHidden)((Control)sender).Parent.FindControl("macroPropertyID");
|
||||
|
||||
var property = _macro.Properties.Single(x => x.Id == int.Parse(macroPropertyId.Value));
|
||||
var property = _macro.Properties.Values.Single(x => x.Id == int.Parse(macroPropertyId.Value));
|
||||
_macro.Properties.Remove(property);
|
||||
|
||||
Services.MacroService.Save(_macro);
|
||||
@@ -104,7 +104,7 @@ namespace Umbraco.Web.UI.Umbraco.Developer.Macros
|
||||
|
||||
public void MacroPropertyBind()
|
||||
{
|
||||
macroProperties.DataSource = _macro.Properties.OrderBy(x => x.SortOrder);
|
||||
macroProperties.DataSource = _macro.Properties.Values.OrderBy(x => x.SortOrder);
|
||||
macroProperties.DataBind();
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ namespace Umbraco.Web.UI.Umbraco.Developer.Macros
|
||||
_macro.Properties.Add(new MacroProperty(
|
||||
macroPropertyAliasNew.Text.Trim(),
|
||||
macroPropertyNameNew.Text.Trim(),
|
||||
_macro.Properties.Any() ? _macro.Properties.Max(x => x.SortOrder) + 1 : 0,
|
||||
_macro.Properties.Values.Any() ? _macro.Properties.Values.Max(x => x.SortOrder) + 1 : 0,
|
||||
macroPropertyTypeNew.SelectedValue));
|
||||
|
||||
Services.MacroService.Save(_macro);
|
||||
@@ -246,7 +246,7 @@ namespace Umbraco.Web.UI.Umbraco.Developer.Macros
|
||||
var macroElementSortOrder = (TextBox)item.FindControl("macroPropertySortOrder");
|
||||
var macroElementType = (DropDownList)item.FindControl("macroPropertyType");
|
||||
|
||||
var prop = _macro.Properties.Single(x => x.Id == int.Parse(macroPropertyId.Value));
|
||||
var prop = _macro.Properties.Values.Single(x => x.Id == int.Parse(macroPropertyId.Value));
|
||||
var sortOrder = 0;
|
||||
int.TryParse(macroElementSortOrder.Text, out sortOrder);
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(dto => dto.AdditionalData, expression => expression.Ignore());
|
||||
|
||||
CreateMap<IMacro, IEnumerable<MacroParameter>>()
|
||||
.ConvertUsing(macro => macro.Properties.Select(Mapper.Map<MacroParameter>).ToList());
|
||||
.ConvertUsing(macro => macro.Properties.Values.Select(Mapper.Map<MacroParameter>).ToList());
|
||||
|
||||
CreateMap<IMacroProperty, MacroParameter>()
|
||||
.ForMember(x => x.View, expression => expression.Ignore())
|
||||
|
||||
@@ -1199,7 +1199,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
foreach (var (culture, name) in names)
|
||||
{
|
||||
cultureData[culture] = new CultureVariation { Name = name, Date = content.GetUpdateDate(culture) ?? DateTime.MinValue };
|
||||
cultureData[culture] = new CultureVariation { Name = name.Name, Date = content.GetUpdateDate(culture) ?? DateTime.MinValue };
|
||||
}
|
||||
|
||||
//the dictionary that will be serialized
|
||||
|
||||
@@ -33,9 +33,9 @@ namespace Umbraco.Web.Security
|
||||
|
||||
public WebSecurity(HttpContextBase httpContext, IUserService userService, IGlobalSettings globalSettings)
|
||||
{
|
||||
_httpContext = httpContext ?? throw new ArgumentNullException(nameof(httpContext));
|
||||
_userService = userService ?? throw new ArgumentNullException(nameof(userService));
|
||||
_globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings));
|
||||
_httpContext = httpContext;
|
||||
_userService = userService;
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -396,7 +396,7 @@ namespace umbraco
|
||||
return _cultureInfos;
|
||||
|
||||
return _cultureInfos = _inner.PublishNames
|
||||
.ToDictionary(x => x.Culture, x => new PublishedCultureInfo(x.Culture, x.Name, x.Date));
|
||||
.ToDictionary(x => x.Key, x => new PublishedCultureInfo(x.Key, x.Value.Name, x.Value.Date));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user