Merge remote-tracking branch 'origin/v8/dev' into netcore/dev
# Conflicts: # src/Umbraco.Infrastructure/Models/Property.cs # src/Umbraco.Tests/Models/ContentTests.cs
This commit is contained in:
@@ -81,9 +81,10 @@ namespace Umbraco.Core.Models
|
||||
if (propertyInfo.PropertyType.IsGenericType
|
||||
&& (propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IEnumerable<>)
|
||||
|| propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>)
|
||||
|| propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IList<>)))
|
||||
|| propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IList<>)
|
||||
|| propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IReadOnlyCollection<>)))
|
||||
{
|
||||
//if it is a IEnumerable<>, IList<T> or ICollection<> we'll use a List<>
|
||||
//if it is a IEnumerable<>, IReadOnlyCollection<T>, IList<T> or ICollection<> we'll use a List<> since it implements them all
|
||||
var genericType = typeof(List<>).MakeGenericType(propertyInfo.PropertyType.GetGenericArguments());
|
||||
return new ClonePropertyInfo(propertyInfo) { GenericListType = genericType };
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Represents a property value.
|
||||
/// </summary>
|
||||
public class PropertyValue : IPropertyValue, IEquatable<PropertyValue>
|
||||
public class PropertyValue : IPropertyValue, IDeepCloneable, IEquatable<PropertyValue>
|
||||
{
|
||||
// TODO: Either we allow change tracking at this class level, or we add some special change tracking collections to the Property
|
||||
// class to deal with change tracking which variants have changed
|
||||
@@ -144,6 +144,7 @@ namespace Umbraco.Core.Models
|
||||
public IPropertyValue Clone()
|
||||
=> new PropertyValue { _culture = _culture, _segment = _segment, PublishedValue = PublishedValue, EditedValue = EditedValue };
|
||||
|
||||
public object DeepClone() => Clone();
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
@@ -154,14 +155,18 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
return other != null &&
|
||||
_culture == other._culture &&
|
||||
_segment == other._segment;
|
||||
_segment == other._segment &&
|
||||
EqualityComparer<object>.Default.Equals(EditedValue, other.EditedValue) &&
|
||||
EqualityComparer<object>.Default.Equals(PublishedValue, other.PublishedValue);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hashCode = -1254204277;
|
||||
var hashCode = 1885328050;
|
||||
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(_culture);
|
||||
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(_segment);
|
||||
hashCode = hashCode * -1521134295 + EqualityComparer<object>.Default.GetHashCode(EditedValue);
|
||||
hashCode = hashCode * -1521134295 + EqualityComparer<object>.Default.GetHashCode(PublishedValue);
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
@@ -529,19 +534,6 @@ namespace Umbraco.Core.Models
|
||||
|
||||
var clonedEntity = (Property)clone;
|
||||
|
||||
//manually clone _values, _pvalue, _vvalues
|
||||
clonedEntity._values = _values?.Select(x => x.Clone()).ToList(); // all values get copied
|
||||
clonedEntity._pvalue = _pvalue?.Clone();
|
||||
// the tricky part here is that _values contains ALL values including the values in the _vvalues
|
||||
// dictionary and they are by reference which is why we have equality overloads on PropertyValue
|
||||
if (clonedEntity._vvalues != null)
|
||||
{
|
||||
clonedEntity._vvalues = new Dictionary<CompositeNStringNStringKey, IPropertyValue>();
|
||||
foreach (var item in _vvalues)
|
||||
{
|
||||
clonedEntity._vvalues[item.Key] = clonedEntity._values.First(x => x.Equals(item.Value));
|
||||
}
|
||||
}
|
||||
//need to manually assign since this is a readonly property
|
||||
clonedEntity.PropertyType = (PropertyType) PropertyType.DeepClone();
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ using Umbraco.Tests.TestHelpers;
|
||||
|
||||
namespace Umbraco.Tests.Models
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
public class ContentTests : UmbracoTestBase
|
||||
{
|
||||
@@ -460,7 +459,7 @@ namespace Umbraco.Tests.Models
|
||||
Assert.IsTrue(prop.WasPropertyDirty("Id"));
|
||||
}
|
||||
Assert.IsTrue(content.WasPropertyDirty("CultureInfos"));
|
||||
foreach(var culture in content.CultureInfos)
|
||||
foreach (var culture in content.CultureInfos)
|
||||
{
|
||||
Assert.IsTrue(culture.WasDirty());
|
||||
Assert.IsTrue(culture.WasPropertyDirty("Name"));
|
||||
@@ -538,7 +537,7 @@ namespace Umbraco.Tests.Models
|
||||
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
|
||||
|
||||
// Act
|
||||
content.PropertyValues(new { title = "This is the new title"});
|
||||
content.PropertyValues(new { title = "This is the new title" });
|
||||
|
||||
// Assert
|
||||
Assert.That(content.Properties.Any(), Is.True);
|
||||
@@ -602,13 +601,13 @@ namespace Umbraco.Tests.Models
|
||||
|
||||
// Act
|
||||
contentType.PropertyGroups["Content"].PropertyTypes.Add(new PropertyType(ShortStringHelper, "test", ValueStorageType.Ntext, "subtitle")
|
||||
{
|
||||
Name = "Subtitle",
|
||||
Description = "Optional subtitle",
|
||||
Mandatory = false,
|
||||
SortOrder = 3,
|
||||
DataTypeId = -88
|
||||
});
|
||||
{
|
||||
Name = "Subtitle",
|
||||
Description = "Optional subtitle",
|
||||
Mandatory = false,
|
||||
SortOrder = 3,
|
||||
DataTypeId = -88
|
||||
});
|
||||
|
||||
// Assert
|
||||
Assert.That(contentType.PropertyGroups["Content"].PropertyTypes.Count, Is.EqualTo(3));
|
||||
@@ -625,9 +624,13 @@ namespace Umbraco.Tests.Models
|
||||
|
||||
// Act
|
||||
var propertyType = new PropertyType(ShortStringHelper, "test", ValueStorageType.Ntext, "subtitle")
|
||||
{
|
||||
Name = "Subtitle", Description = "Optional subtitle", Mandatory = false, SortOrder = 3, DataTypeId = -88
|
||||
};
|
||||
{
|
||||
Name = "Subtitle",
|
||||
Description = "Optional subtitle",
|
||||
Mandatory = false,
|
||||
SortOrder = 3,
|
||||
DataTypeId = -88
|
||||
};
|
||||
contentType.PropertyGroups["Content"].PropertyTypes.Add(propertyType);
|
||||
var newProperty = new Property(propertyType);
|
||||
newProperty.SetValue("This is a subtitle Test");
|
||||
@@ -649,14 +652,14 @@ namespace Umbraco.Tests.Models
|
||||
|
||||
// Act
|
||||
var propertyType = new PropertyType(ShortStringHelper, "test", ValueStorageType.Ntext, "subtitle")
|
||||
{
|
||||
Name = "Subtitle",
|
||||
Description = "Optional subtitle",
|
||||
Mandatory = false,
|
||||
SortOrder = 3,
|
||||
DataTypeId = -88
|
||||
};
|
||||
var propertyGroup = new PropertyGroup(true) { Name = "Test Group", SortOrder = 3};
|
||||
{
|
||||
Name = "Subtitle",
|
||||
Description = "Optional subtitle",
|
||||
Mandatory = false,
|
||||
SortOrder = 3,
|
||||
DataTypeId = -88
|
||||
};
|
||||
var propertyGroup = new PropertyGroup(true) { Name = "Test Group", SortOrder = 3 };
|
||||
propertyGroup.PropertyTypes.Add(propertyType);
|
||||
contentType.PropertyGroups.Add(propertyGroup);
|
||||
var newProperty = new Property(propertyType);
|
||||
@@ -680,9 +683,13 @@ namespace Umbraco.Tests.Models
|
||||
|
||||
// Act - note that the PropertyType's properties like SortOrder is not updated through the Content object
|
||||
var propertyType = new PropertyType(ShortStringHelper, "test", ValueStorageType.Ntext, "title")
|
||||
{
|
||||
Name = "Title", Description = "Title description added", Mandatory = false, SortOrder = 10, DataTypeId = -88
|
||||
};
|
||||
{
|
||||
Name = "Title",
|
||||
Description = "Title description added",
|
||||
Mandatory = false,
|
||||
SortOrder = 10,
|
||||
DataTypeId = -88
|
||||
};
|
||||
content.Properties.Add(new Property(propertyType));
|
||||
|
||||
// Assert
|
||||
@@ -910,13 +917,13 @@ namespace Umbraco.Tests.Models
|
||||
|
||||
// Act
|
||||
var propertyType = new PropertyType(ShortStringHelper, "test", ValueStorageType.Ntext, "subtitle")
|
||||
{
|
||||
Name = "Subtitle",
|
||||
Description = "Optional subtitle",
|
||||
Mandatory = false,
|
||||
SortOrder = 3,
|
||||
DataTypeId = -88
|
||||
};
|
||||
{
|
||||
Name = "Subtitle",
|
||||
Description = "Optional subtitle",
|
||||
Mandatory = false,
|
||||
SortOrder = 3,
|
||||
DataTypeId = -88
|
||||
};
|
||||
contentType.PropertyGroups["Content"].PropertyTypes.Add(propertyType);
|
||||
|
||||
// Assert
|
||||
|
||||
63
src/Umbraco.Tests/Models/PropertyTests.cs
Normal file
63
src/Umbraco.Tests/Models/PropertyTests.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Tests.Testing;
|
||||
|
||||
namespace Umbraco.Tests.Models
|
||||
{
|
||||
[TestFixture]
|
||||
public class PropertyTests : UmbracoTestBase
|
||||
{
|
||||
[Test]
|
||||
public void Can_Deep_Clone()
|
||||
{
|
||||
// needs to be within collection to support publishing
|
||||
var ptCollection = new PropertyTypeCollection(true, new[] {new PropertyType("TestPropertyEditor", ValueStorageType.Nvarchar, "test")
|
||||
{
|
||||
Id = 3,
|
||||
CreateDate = DateTime.Now,
|
||||
DataTypeId = 5,
|
||||
PropertyEditorAlias = "propTest",
|
||||
Description = "testing",
|
||||
Key = Guid.NewGuid(),
|
||||
Mandatory = true,
|
||||
Name = "Test",
|
||||
PropertyGroupId = new Lazy<int>(() => 11),
|
||||
SortOrder = 9,
|
||||
UpdateDate = DateTime.Now,
|
||||
ValidationRegExp = "xxxx",
|
||||
ValueStorageType = ValueStorageType.Nvarchar
|
||||
}});
|
||||
|
||||
var property = new Property(123, ptCollection[0])
|
||||
{
|
||||
CreateDate = DateTime.Now,
|
||||
Id = 4,
|
||||
Key = Guid.NewGuid(),
|
||||
UpdateDate = DateTime.Now
|
||||
};
|
||||
|
||||
property.SetValue("hello");
|
||||
property.PublishValues();
|
||||
|
||||
var clone = (Property)property.DeepClone();
|
||||
|
||||
Assert.AreNotSame(clone, property);
|
||||
Assert.AreNotSame(clone.Values, property.Values);
|
||||
Assert.AreNotSame(property.PropertyType, clone.PropertyType);
|
||||
for (int i = 0; i < property.Values.Count; i++)
|
||||
{
|
||||
Assert.AreNotSame(property.Values.ElementAt(i), clone.Values.ElementAt(i));
|
||||
}
|
||||
|
||||
|
||||
//This double verifies by reflection
|
||||
var allProps = clone.GetType().GetProperties();
|
||||
foreach (var propertyInfo in allProps)
|
||||
{
|
||||
Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(property, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -143,6 +143,7 @@
|
||||
<Compile Include="Models\CultureImpactTests.cs" />
|
||||
<Compile Include="Models\ImageProcessorImageUrlGeneratorTest.cs" />
|
||||
<Compile Include="Models\PathValidationTests.cs" />
|
||||
<Compile Include="Models\PropertyTests.cs" />
|
||||
<Compile Include="Models\VariationTests.cs" />
|
||||
<Compile Include="Persistence\Mappers\MapperTestBase.cs" />
|
||||
<Compile Include="Persistence\Repositories\DocumentRepositoryTest.cs" />
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
<umb-dropdown class="pull-right" ng-if="vm.page.showStatusFilter" on-close="vm.page.showStatusFilter = false;">
|
||||
<umb-dropdown-item ng-repeat="userState in vm.userStatesFilter | filter:{ count: '!0', key: '!All'}" style="padding: 8px 20px 8px 16px;">
|
||||
<umb-dropdown-item ng-repeat="userState in vm.userStatesFilter | filter:{ key: '!All'}" ng-show="userState.count > 0" style="padding: 8px 20px 8px 16px;">
|
||||
<umb-checkbox model="userState.selected"
|
||||
on-change="vm.setUserStatesFilter(userState)"
|
||||
text="{{ userState.name }} ({{userState.count}})">
|
||||
|
||||
Reference in New Issue
Block a user