Merge remote-tracking branch 'origin/v8/dev' into netcore/dev

# Conflicts:
#	NuGet.Config
#	src/Umbraco.Core/Models/RelationType.cs
#	src/Umbraco.Infrastructure/PropertyEditors/MediaPickerPropertyEditor.cs
This commit is contained in:
Bjarke Berg
2020-04-16 19:00:51 +02:00
10 changed files with 117 additions and 46 deletions

View File

@@ -1,5 +1,6 @@
using System;
using System.Runtime.Serialization;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
@@ -13,20 +14,25 @@ namespace Umbraco.Core.Models
{
private string _name;
private string _alias;
private bool _isBidrectional;
private bool _isBidirectional;
private Guid? _parentObjectType;
private Guid? _childObjectType;
public RelationType(string alias, string name)
: this(name, alias, false, null, null)
: this(name: name, alias: alias, false, null, null)
{
}
public RelationType(string name, string alias, bool isBidrectional, Guid? parentObjectType, Guid? childObjectType)
{
if (name == null) throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
if (alias == null) throw new ArgumentNullException(nameof(alias));
if (string.IsNullOrWhiteSpace(alias)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(alias));
_name = name;
_alias = alias;
_isBidrectional = isBidrectional;
_isBidirectional = isBidrectional;
_parentObjectType = parentObjectType;
_childObjectType = childObjectType;
}
@@ -57,8 +63,8 @@ namespace Umbraco.Core.Models
[DataMember]
public bool IsBidirectional
{
get => _isBidrectional;
set => SetPropertyValueAndDetectChanges(value, ref _isBidrectional, nameof(IsBidirectional));
get => _isBidirectional;
set => SetPropertyValueAndDetectChanges(value, ref _isBidirectional, nameof(IsBidirectional));
}
/// <summary>

View File

@@ -9,7 +9,7 @@ namespace Umbraco.Core.Persistence.Factories
public static IRelationType BuildEntity(RelationTypeDto dto)
{
var entity = new RelationType(dto.Name, dto.Alias, dto.Dual, dto.ChildObjectType, dto.ParentObjectType);
var entity = new RelationType(dto.Name, dto.Alias, dto.Dual, dto.ParentObjectType, dto.ChildObjectType);
try
{

View File

@@ -23,7 +23,6 @@ namespace Umbraco.Core.PropertyEditors
public class DataEditor : IDataEditor
{
private IDictionary<string, object> _defaultConfiguration;
private IDataValueEditor _dataValueEditor;
/// <summary>
/// Initializes a new instance of the <see cref="DataEditor"/> class.
@@ -105,7 +104,7 @@ namespace Umbraco.Core.PropertyEditors
/// simple enough for now.</para>
/// </remarks>
// TODO: point of that one? shouldn't we always configure?
public IDataValueEditor GetValueEditor() => ExplicitValueEditor ?? (_dataValueEditor ?? (_dataValueEditor = CreateValueEditor()));
public IDataValueEditor GetValueEditor() => ExplicitValueEditor ?? CreateValueEditor();
/// <inheritdoc />
/// <remarks>

View File

@@ -186,6 +186,10 @@ namespace Umbraco.Web.PropertyEditors
public IEnumerable<UmbracoEntityReference> GetReferences(object value)
{
var rawJson = value == null ? string.Empty : value is string str ? str : value.ToString();
if (rawJson.IsNullOrWhiteSpace())
yield break;
DeserializeGridValue(rawJson, out var richTextEditorValues, out var mediaValues);
foreach (var umbracoEntityReference in richTextEditorValues.SelectMany(x =>

View File

@@ -57,9 +57,11 @@ namespace Umbraco.Web.PropertyEditors
if (string.IsNullOrEmpty(asString)) yield break;
if (UdiParser.TryParse(asString, out var udi))
yield return new UmbracoEntityReference(udi);
foreach (var udiStr in asString.Split(','))
{
if (UdiParser.TryParse(udiStr, out var udi))
yield return new UmbracoEntityReference(udi);
}
}
}
}

View File

@@ -876,9 +876,11 @@ namespace Umbraco.Web.PublishedCache.NuCache
var id = content.FirstChildContentId;
while (id > 0)
{
// get the required link node, this ensures that both `link` and `link.Value` are not null
var link = GetRequiredLinkedNode(id, "child", null);
ClearBranchLocked(link.Value);
id = link.Value.NextSiblingContentId;
var linkValue = link.Value; // capture local since clearing in recurse can clear it
ClearBranchLocked(linkValue); // recurse
id = linkValue.NextSiblingContentId;
}
}

View File

@@ -107,13 +107,16 @@ namespace Umbraco.Tests.Persistence.Repositories
var repository = CreateRepository(provider);
// Act
var relationType = repository.Get(RelationTypeDto.NodeIdSeed);
var relationType = repository.Get(RelationTypeDto.NodeIdSeed + 2);
// Assert
Assert.That(relationType, Is.Not.Null);
Assert.That(relationType.HasIdentity, Is.True);
Assert.That(relationType.Alias, Is.EqualTo("relateContentOnCopy"));
Assert.That(relationType.Name, Is.EqualTo("Relate Content on Copy"));
Assert.That(relationType.IsBidirectional, Is.True);
Assert.That(relationType.Alias, Is.EqualTo("relateContentToMedia"));
Assert.That(relationType.Name, Is.EqualTo("Relate Content to Media"));
Assert.That(relationType.ChildObjectType, Is.EqualTo(Constants.ObjectTypes.Media));
Assert.That(relationType.ParentObjectType, Is.EqualTo(Constants.ObjectTypes.Document));
}
}
@@ -133,7 +136,7 @@ namespace Umbraco.Tests.Persistence.Repositories
Assert.That(relationTypes, Is.Not.Null);
Assert.That(relationTypes.Any(), Is.True);
Assert.That(relationTypes.Any(x => x == null), Is.False);
Assert.That(relationTypes.Count(), Is.EqualTo(7));
Assert.That(relationTypes.Count(), Is.EqualTo(8));
}
}
@@ -190,7 +193,7 @@ namespace Umbraco.Tests.Persistence.Repositories
int count = repository.Count(query);
// Assert
Assert.That(count, Is.EqualTo(5));
Assert.That(count, Is.EqualTo(6));
}
}
@@ -224,8 +227,9 @@ namespace Umbraco.Tests.Persistence.Repositories
public void CreateTestData()
{
var relateContent = new RelationType("Relate Content on Copy", "relateContentOnCopy", true, Constants.ObjectTypes.Document, new Guid("C66BA18E-EAF3-4CFF-8A22-41B16D66A972"));
var relateContentType = new RelationType("Relate ContentType on Copy", "relateContentTypeOnCopy", true, Constants.ObjectTypes.DocumentType, new Guid("A2CB7800-F571-4787-9638-BC48539A0EFB"));
var relateContent = new RelationType("Relate Content on Copy", "relateContentOnCopy", true, Constants.ObjectTypes.Document, Constants.ObjectTypes.Document);
var relateContentType = new RelationType("Relate ContentType on Copy", "relateContentTypeOnCopy", true, Constants.ObjectTypes.DocumentType, Constants.ObjectTypes.DocumentType);
var relateContentMedia = new RelationType("Relate Content to Media", "relateContentToMedia", true, Constants.ObjectTypes.Document, Constants.ObjectTypes.Media);
var provider = TestObjects.GetScopeProvider(Logger);
using (var scope = ScopeProvider.CreateScope())
@@ -234,6 +238,7 @@ namespace Umbraco.Tests.Persistence.Repositories
repository.Save(relateContent);//Id 2
repository.Save(relateContentType);//Id 3
repository.Save(relateContentMedia);//Id 4
scope.Complete();
}
}

View File

@@ -53,7 +53,7 @@ namespace Umbraco.Tests.PublishedContent
_snapshotService?.Dispose();
}
private void Init(IEnumerable<ContentNodeKit> kits)
private void Init(Func<IEnumerable<ContentNodeKit>> kits)
{
Current.Reset();
@@ -142,7 +142,7 @@ namespace Umbraco.Tests.PublishedContent
_snapshotAccessor = new TestPublishedSnapshotAccessor();
// create a data source for NuCache
_source = new TestDataSource(kits);
_source = new TestDataSource(kits());
var typeFinder = TestHelper.GetTypeFinder();
var settings = Mock.Of<INuCacheSettings>();
@@ -387,7 +387,7 @@ namespace Umbraco.Tests.PublishedContent
[Test]
public void EmptyTest()
{
Init(Enumerable.Empty<ContentNodeKit>());
Init(() => Enumerable.Empty<ContentNodeKit>());
var snapshot = _snapshotService.CreatePublishedSnapshot(previewToken: null);
_snapshotAccessor.PublishedSnapshot = snapshot;
@@ -399,7 +399,7 @@ namespace Umbraco.Tests.PublishedContent
[Test]
public void ChildrenTest()
{
Init(GetInvariantKits());
Init(GetInvariantKits);
var snapshot = _snapshotService.CreatePublishedSnapshot(previewToken: null);
_snapshotAccessor.PublishedSnapshot = snapshot;
@@ -426,7 +426,7 @@ namespace Umbraco.Tests.PublishedContent
[Test]
public void ParentTest()
{
Init(GetInvariantKits());
Init(GetInvariantKits);
var snapshot = _snapshotService.CreatePublishedSnapshot(previewToken: null);
_snapshotAccessor.PublishedSnapshot = snapshot;
@@ -452,7 +452,7 @@ namespace Umbraco.Tests.PublishedContent
[Test]
public void MoveToRootTest()
{
Init(GetInvariantKits());
Init(GetInvariantKits);
// get snapshot
var snapshot = _snapshotService.CreatePublishedSnapshot(previewToken: null);
@@ -494,7 +494,7 @@ namespace Umbraco.Tests.PublishedContent
[Test]
public void MoveFromRootTest()
{
Init(GetInvariantKits());
Init(GetInvariantKits);
// get snapshot
var snapshot = _snapshotService.CreatePublishedSnapshot(previewToken: null);
@@ -536,7 +536,7 @@ namespace Umbraco.Tests.PublishedContent
[Test]
public void ReOrderTest()
{
Init(GetInvariantKits());
Init(GetInvariantKits);
// get snapshot
var snapshot = _snapshotService.CreatePublishedSnapshot(previewToken: null);
@@ -611,7 +611,7 @@ namespace Umbraco.Tests.PublishedContent
[Test]
public void MoveTest()
{
Init(GetInvariantKits());
Init(GetInvariantKits);
// get snapshot
var snapshot = _snapshotService.CreatePublishedSnapshot(previewToken: null);
@@ -712,11 +712,61 @@ namespace Umbraco.Tests.PublishedContent
Assert.AreEqual(1, snapshot.Content.GetById(7).Parent?.Id);
}
[Test]
public void Clear_Branch_Locked()
{
// This test replicates an issue we saw here https://github.com/umbraco/Umbraco-CMS/pull/7907#issuecomment-610259393
// The data was sent to me and this replicates it's structure
var paths = new Dictionary<int, string> { { -1, "-1" } };
Init(() => new List<ContentNodeKit>
{
CreateInvariantKit(1, -1, 1, paths), // first level
CreateInvariantKit(2, 1, 1, paths), // second level
CreateInvariantKit(3, 2, 1, paths), // third level
CreateInvariantKit(4, 3, 1, paths), // fourth level (we'll copy this one to the same level)
CreateInvariantKit(5, 4, 1, paths), // 6th level
CreateInvariantKit(6, 5, 2, paths), // 7th level
CreateInvariantKit(7, 5, 3, paths),
CreateInvariantKit(8, 5, 4, paths),
CreateInvariantKit(9, 5, 5, paths),
CreateInvariantKit(10, 5, 6, paths)
});
// get snapshot
var snapshot = _snapshotService.CreatePublishedSnapshot(previewToken: null);
_snapshotAccessor.PublishedSnapshot = snapshot;
var snapshotService = (PublishedSnapshotService)_snapshotService;
var contentStore = snapshotService.GetContentStore();
//This will set a flag to force creating a new Gen next time the store is locked (i.e. In Notify)
contentStore.CreateSnapshot();
// notify - which ensures there are 2 generations in the cache meaning each LinkedNode has a Next value.
_snapshotService.Notify(new[]
{
new ContentCacheRefresher.JsonPayload(4, Guid.Empty, TreeChangeTypes.RefreshBranch)
}, out _, out _);
// refresh the branch again, this used to show the issue where a null ref exception would occur
// because in the ClearBranchLocked logic, when SetValueLocked was called within a recursive call
// to a child, we null out the .Value of the LinkedNode within the while loop because we didn't capture
// this value before recursing.
Assert.DoesNotThrow(() =>
_snapshotService.Notify(new[]
{
new ContentCacheRefresher.JsonPayload(4, Guid.Empty, TreeChangeTypes.RefreshBranch)
}, out _, out _));
}
[Test]
public void NestedVariationChildrenTest()
{
var mixedKits = GetNestedVariantKits();
Init(mixedKits);
Init(GetNestedVariantKits);
var snapshot = _snapshotService.CreatePublishedSnapshot(previewToken: null);
_snapshotAccessor.PublishedSnapshot = snapshot;
@@ -805,7 +855,7 @@ namespace Umbraco.Tests.PublishedContent
[Test]
public void VariantChildrenTest()
{
Init(GetVariantKits());
Init(GetVariantKits);
var snapshot = _snapshotService.CreatePublishedSnapshot(previewToken: null);
_snapshotAccessor.PublishedSnapshot = snapshot;
@@ -877,7 +927,7 @@ namespace Umbraco.Tests.PublishedContent
[Test]
public void RemoveTest()
{
Init(GetInvariantKits());
Init(GetInvariantKits);
var snapshot = _snapshotService.CreatePublishedSnapshot(previewToken: null);
_snapshotAccessor.PublishedSnapshot = snapshot;
@@ -926,7 +976,7 @@ namespace Umbraco.Tests.PublishedContent
[Test]
public void UpdateTest()
{
Init(GetInvariantKits());
Init(GetInvariantKits);
var snapshot = _snapshotService.CreatePublishedSnapshot(previewToken: null);
_snapshotAccessor.PublishedSnapshot = snapshot;
@@ -979,7 +1029,7 @@ namespace Umbraco.Tests.PublishedContent
[Test]
public void AtRootTest()
{
Init(GetVariantWithDraftKits());
Init(GetVariantWithDraftKits);
var snapshot = _snapshotService.CreatePublishedSnapshot(previewToken: null);
_snapshotAccessor.PublishedSnapshot = snapshot;
@@ -1008,7 +1058,7 @@ namespace Umbraco.Tests.PublishedContent
yield return CreateInvariantKit(2, 1, 1, paths);
}
Init(GetKits());
Init(GetKits);
var snapshotService = (PublishedSnapshotService)_snapshotService;
var contentStore = snapshotService.GetContentStore();
@@ -1047,7 +1097,7 @@ namespace Umbraco.Tests.PublishedContent
yield return CreateInvariantKit(4, 1, 3, paths);
}
Init(GetKits());
Init(GetKits);
var snapshotService = (PublishedSnapshotService)_snapshotService;
var contentStore = snapshotService.GetContentStore();
@@ -1127,7 +1177,7 @@ namespace Umbraco.Tests.PublishedContent
yield return CreateInvariantKit(40, 1, 3, paths);
}
Init(GetKits());
Init(GetKits);
var snapshotService = (PublishedSnapshotService)_snapshotService;
var contentStore = snapshotService.GetContentStore();
@@ -1199,7 +1249,7 @@ namespace Umbraco.Tests.PublishedContent
}
//init with all published
Init(GetKits());
Init(GetKits);
var snapshotService = (PublishedSnapshotService)_snapshotService;
var contentStore = snapshotService.GetContentStore();
@@ -1216,7 +1266,7 @@ namespace Umbraco.Tests.PublishedContent
//Change the root publish flag
var kit = rootKit.Clone(PublishedModelFactory);
kit.DraftData = published ? null : kit.PublishedData;
kit.PublishedData = published? kit.PublishedData : null;
kit.PublishedData = published ? kit.PublishedData : null;
_source.Kits[1] = kit;
_snapshotService.Notify(new[]
@@ -1269,7 +1319,7 @@ namespace Umbraco.Tests.PublishedContent
yield return CreateInvariantKit(4, 1, 3, paths);
}
Init(GetKits());
Init(GetKits);
var snapshotService = (PublishedSnapshotService)_snapshotService;
var contentStore = snapshotService.GetContentStore();
@@ -1329,14 +1379,13 @@ namespace Umbraco.Tests.PublishedContent
public void MultipleCacheIteration()
{
//see https://github.com/umbraco/Umbraco-CMS/issues/7798
this.Init(this.GetInvariantKits());
Init(GetInvariantKits);
var snapshot = this._snapshotService.CreatePublishedSnapshot(previewToken: null);
this._snapshotAccessor.PublishedSnapshot = snapshot;
_snapshotAccessor.PublishedSnapshot = snapshot;
var items = snapshot.Content.GetByXPath("/root/itype");
Assert.AreEqual(items.Count(), items.Count());
}
private void AssertLinkedNode(ContentNode node, int parent, int prevSibling, int nextSibling, int firstChild, int lastChild)
{
Assert.AreEqual(parent, node.ParentContentId);

View File

@@ -110,8 +110,8 @@ namespace Umbraco.Tests.Services
Assert.AreEqual("Test", rt.Name);
Assert.AreEqual("repeatedEventOccurence", rt.Alias);
Assert.AreEqual(false, rt.IsBidirectional);
Assert.AreEqual(Constants.ObjectTypes.Document, rt.ChildObjectType.Value);
Assert.AreEqual(Constants.ObjectTypes.Media, rt.ParentObjectType.Value);
Assert.AreEqual(Constants.ObjectTypes.Document, rt.ParentObjectType.Value);
Assert.AreEqual(Constants.ObjectTypes.Media, rt.ChildObjectType.Value);
}
[Test]

View File

@@ -342,6 +342,10 @@
<DevelopmentServerPort>9000</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:9000/</IISUrl>
<IISUrl>http://localhost:8700</IISUrl>
<DevelopmentServerPort>8610</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:8610</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>