Merge pull request #5946 from umbraco/v8/bugfix/5886-fixes-Children

Fixes issue with Children(culture) method
This commit is contained in:
Warren Buckley
2019-07-22 14:54:49 +01:00
committed by GitHub
2 changed files with 223 additions and 103 deletions

View File

@@ -103,18 +103,26 @@ namespace Umbraco.Core
/// Gets the children of the content item.
/// </summary>
/// <param name="content">The content item.</param>
/// <param name="culture">The specific culture to get the url children for. If null is used the current culture is used (Default is null).</param>
/// <param name="culture">
/// The specific culture to get the url children for. Default is null which will use the current culture in <see cref="VariationContext"/>
/// </param>
/// <remarks>
/// <para>Gets children that are available for the specified culture.</para>
/// <para>Children are sorted by their sortOrder.</para>
/// <para>The '*' culture and supported and returns everything.</para>
/// <para>
/// For culture,
/// if null is used the current culture is used.
/// If an empty string is used only invariant children are returned.
/// If "*" is used all children are returned.
/// </para>
/// <para>
/// If a variant culture is specified or there is a current culture in the <see cref="VariationContext"/> then the Children returned
/// will include both the variant children matching the culture AND the invariant children because the invariant children flow with the current culture.
/// However, if an empty string is specified only invariant children are returned.
/// </para>
/// </remarks>
public static IEnumerable<IPublishedContent> Children(this IPublishedContent content, string culture = null)
{
// invariant has invariant value (whatever the requested culture)
if (!content.ContentType.VariesByCulture() && culture != "*")
culture = "";
// handle context culture for variant
if (culture == null)
culture = VariationContextAccessor?.VariationContext?.Culture ?? "";

View File

@@ -151,117 +151,139 @@ namespace Umbraco.Tests.PublishedContent
Mock.Get(factory).Setup(x => x.GetInstance(typeof(IVariationContextAccessor))).Returns(_variationAccesor);
}
private IEnumerable<ContentNodeKit> GetNestedVariantKits()
{
var paths = new Dictionary<int, string> { { -1, "-1" } };
//1x variant (root)
yield return CreateVariantKit(1, -1, 1, paths);
//1x invariant under root
yield return CreateInvariantKit(4, 1, 1, paths);
//1x variant under root
yield return CreateVariantKit(7, 1, 4, paths);
//2x mixed under invariant
yield return CreateVariantKit(10, 4, 1, paths);
yield return CreateInvariantKit(11, 4, 2, paths);
//2x mixed under variant
yield return CreateVariantKit(12, 7, 1, paths);
yield return CreateInvariantKit(13, 7, 2, paths);
}
private IEnumerable<ContentNodeKit> GetInvariantKits()
{
var paths = new Dictionary<int, string> { { -1, "-1" } };
ContentNodeKit CreateKit(int id, int parentId, int sortOrder)
yield return CreateInvariantKit(1, -1, 1, paths);
yield return CreateInvariantKit(2, -1, 2, paths);
yield return CreateInvariantKit(3, -1, 3, paths);
yield return CreateInvariantKit(4, 1, 1, paths);
yield return CreateInvariantKit(5, 1, 2, paths);
yield return CreateInvariantKit(6, 1, 3, paths);
yield return CreateInvariantKit(7, 2, 3, paths);
yield return CreateInvariantKit(8, 2, 2, paths);
yield return CreateInvariantKit(9, 2, 1, paths);
yield return CreateInvariantKit(10, 3, 1, paths);
yield return CreateInvariantKit(11, 4, 1, paths);
yield return CreateInvariantKit(12, 4, 2, paths);
}
private ContentNodeKit CreateInvariantKit(int id, int parentId, int sortOrder, Dictionary<int, string> paths)
{
if (!paths.TryGetValue(parentId, out var parentPath))
throw new Exception("Unknown parent.");
var path = paths[id] = parentPath + "," + id;
var level = path.Count(x => x == ',');
var now = DateTime.Now;
return new ContentNodeKit
{
if (!paths.TryGetValue(parentId, out var parentPath))
throw new Exception("Unknown parent.");
var path = paths[id] = parentPath + "," + id;
var level = path.Count(x => x == ',');
var now = DateTime.Now;
return new ContentNodeKit
ContentTypeId = _contentTypeInvariant.Id,
Node = new ContentNode(id, Guid.NewGuid(), level, path, sortOrder, parentId, DateTime.Now, 0),
DraftData = null,
PublishedData = new ContentData
{
ContentTypeId = _contentTypeInvariant.Id,
Node = new ContentNode(id, Guid.NewGuid(), level, path, sortOrder, parentId, DateTime.Now, 0),
DraftData = null,
PublishedData = new ContentData
{
Name = "N" + id,
Published = true,
TemplateId = 0,
VersionId = 1,
VersionDate = now,
WriterId = 0,
Properties = new Dictionary<string, PropertyData[]>(),
CultureInfos = new Dictionary<string, CultureVariation>()
}
};
}
yield return CreateKit(1, -1, 1);
yield return CreateKit(2, -1, 2);
yield return CreateKit(3, -1, 3);
yield return CreateKit(4, 1, 1);
yield return CreateKit(5, 1, 2);
yield return CreateKit(6, 1, 3);
yield return CreateKit(7, 2, 3);
yield return CreateKit(8, 2, 2);
yield return CreateKit(9, 2, 1);
yield return CreateKit(10, 3, 1);
yield return CreateKit(11, 4, 1);
yield return CreateKit(12, 4, 2);
Name = "N" + id,
Published = true,
TemplateId = 0,
VersionId = 1,
VersionDate = now,
WriterId = 0,
Properties = new Dictionary<string, PropertyData[]>(),
CultureInfos = new Dictionary<string, CultureVariation>()
}
};
}
private IEnumerable<ContentNodeKit> GetVariantKits()
{
var paths = new Dictionary<int, string> { { -1, "-1" } };
Dictionary<string, CultureVariation> GetCultureInfos(int id, DateTime now)
yield return CreateVariantKit(1, -1, 1, paths);
yield return CreateVariantKit(2, -1, 2, paths);
yield return CreateVariantKit(3, -1, 3, paths);
yield return CreateVariantKit(4, 1, 1, paths);
yield return CreateVariantKit(5, 1, 2, paths);
yield return CreateVariantKit(6, 1, 3, paths);
yield return CreateVariantKit(7, 2, 3, paths);
yield return CreateVariantKit(8, 2, 2, paths);
yield return CreateVariantKit(9, 2, 1, paths);
yield return CreateVariantKit(10, 3, 1, paths);
yield return CreateVariantKit(11, 4, 1, paths);
yield return CreateVariantKit(12, 4, 2, paths);
}
private static Dictionary<string, CultureVariation> GetCultureInfos(int id, DateTime now)
{
var en = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
var fr = new[] { 1, 3, 4, 6, 7, 9, 10, 12 };
var infos = new Dictionary<string, CultureVariation>();
if (en.Contains(id))
infos["en-US"] = new CultureVariation { Name = "N" + id + "-" + "en-US", Date = now, IsDraft = false };
if (fr.Contains(id))
infos["fr-FR"] = new CultureVariation { Name = "N" + id + "-" + "fr-FR", Date = now, IsDraft = false };
return infos;
}
private ContentNodeKit CreateVariantKit(int id, int parentId, int sortOrder, Dictionary<int, string> paths)
{
if (!paths.TryGetValue(parentId, out var parentPath))
throw new Exception("Unknown parent.");
var path = paths[id] = parentPath + "," + id;
var level = path.Count(x => x == ',');
var now = DateTime.Now;
return new ContentNodeKit
{
var en = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
var fr = new[] { 1, 3, 4, 6, 7, 9, 10, 12 };
var infos = new Dictionary<string, CultureVariation>();
if (en.Contains(id))
infos["en-US"] = new CultureVariation { Name = "N" + id + "-" + "en-US", Date = now, IsDraft = false };
if (fr.Contains(id))
infos["fr-FR"] = new CultureVariation { Name = "N" + id + "-" + "fr-FR", Date = now, IsDraft = false };
return infos;
}
ContentNodeKit CreateKit(int id, int parentId, int sortOrder)
{
if (!paths.TryGetValue(parentId, out var parentPath))
throw new Exception("Unknown parent.");
var path = paths[id] = parentPath + "," + id;
var level = path.Count(x => x == ',');
var now = DateTime.Now;
return new ContentNodeKit
ContentTypeId = _contentTypeVariant.Id,
Node = new ContentNode(id, Guid.NewGuid(), level, path, sortOrder, parentId, DateTime.Now, 0),
DraftData = null,
PublishedData = new ContentData
{
ContentTypeId = _contentTypeVariant.Id,
Node = new ContentNode(id, Guid.NewGuid(), level, path, sortOrder, parentId, DateTime.Now, 0),
DraftData = null,
PublishedData = new ContentData
{
Name = "N" + id,
Published = true,
TemplateId = 0,
VersionId = 1,
VersionDate = now,
WriterId = 0,
Properties = new Dictionary<string, PropertyData[]>(),
CultureInfos = GetCultureInfos(id, now)
}
};
}
yield return CreateKit(1, -1, 1);
yield return CreateKit(2, -1, 2);
yield return CreateKit(3, -1, 3);
yield return CreateKit(4, 1, 1);
yield return CreateKit(5, 1, 2);
yield return CreateKit(6, 1, 3);
yield return CreateKit(7, 2, 3);
yield return CreateKit(8, 2, 2);
yield return CreateKit(9, 2, 1);
yield return CreateKit(10, 3, 1);
yield return CreateKit(11, 4, 1);
yield return CreateKit(12, 4, 2);
Name = "N" + id,
Published = true,
TemplateId = 0,
VersionId = 1,
VersionDate = now,
WriterId = 0,
Properties = new Dictionary<string, PropertyData[]>(),
CultureInfos = GetCultureInfos(id, now)
}
};
}
private IEnumerable<ContentNodeKit> GetVariantWithDraftKits()
@@ -660,6 +682,96 @@ namespace Umbraco.Tests.PublishedContent
Assert.AreEqual(1, snapshot.Content.GetById(7).Parent?.Id);
}
[Test]
public void NestedVariationChildrenTest()
{
var mixedKits = GetNestedVariantKits();
Init(mixedKits);
var snapshot = _snapshotService.CreatePublishedSnapshot(previewToken: null);
_snapshotAccessor.PublishedSnapshot = snapshot;
//TEST with en-us variation context
_variationAccesor.VariationContext = new VariationContext("en-US");
var documents = snapshot.Content.GetAtRoot().ToArray();
AssertDocuments(documents, "N1-en-US");
documents = snapshot.Content.GetById(1).Children().ToArray();
AssertDocuments(documents, "N4", "N7-en-US");
//Get the invariant and list children, there's a variation context so it should return invariant AND en-us variants
documents = snapshot.Content.GetById(4).Children().ToArray();
AssertDocuments(documents, "N10-en-US", "N11");
//Get the variant and list children, there's a variation context so it should return invariant AND en-us variants
documents = snapshot.Content.GetById(7).Children().ToArray();
AssertDocuments(documents, "N12-en-US", "N13");
//TEST with fr-fr variation context
_variationAccesor.VariationContext = new VariationContext("fr-FR");
documents = snapshot.Content.GetAtRoot().ToArray();
AssertDocuments(documents, "N1-fr-FR");
documents = snapshot.Content.GetById(1).Children().ToArray();
AssertDocuments(documents, "N4", "N7-fr-FR");
//Get the invariant and list children, there's a variation context so it should return invariant AND en-us variants
documents = snapshot.Content.GetById(4).Children().ToArray();
AssertDocuments(documents, "N10-fr-FR", "N11");
//Get the variant and list children, there's a variation context so it should return invariant AND en-us variants
documents = snapshot.Content.GetById(7).Children().ToArray();
AssertDocuments(documents, "N12-fr-FR", "N13");
//TEST specific cultures
documents = snapshot.Content.GetAtRoot("fr-FR").ToArray();
AssertDocuments(documents, "N1-fr-FR");
documents = snapshot.Content.GetById(1).Children("fr-FR").ToArray();
AssertDocuments(documents, "N4", "N7-fr-FR"); //NOTE: Returns invariant, this is expected
documents = snapshot.Content.GetById(1).Children("").ToArray();
AssertDocuments(documents, "N4"); //Only returns invariant since that is what was requested
documents = snapshot.Content.GetById(4).Children("fr-FR").ToArray();
AssertDocuments(documents, "N10-fr-FR", "N11"); //NOTE: Returns invariant, this is expected
documents = snapshot.Content.GetById(4).Children("").ToArray();
AssertDocuments(documents, "N11"); //Only returns invariant since that is what was requested
documents = snapshot.Content.GetById(7).Children("fr-FR").ToArray();
AssertDocuments(documents, "N12-fr-FR", "N13"); //NOTE: Returns invariant, this is expected
documents = snapshot.Content.GetById(7).Children("").ToArray();
AssertDocuments(documents, "N13"); //Only returns invariant since that is what was requested
//TEST without variation context
// This will actually convert the culture to "" which will be invariant since that's all it will know how to do
// This will return a NULL name for culture specific entities because there is no variation context
_variationAccesor.VariationContext = null;
documents = snapshot.Content.GetAtRoot().ToArray();
//will return nothing because there's only variant at root
Assert.AreEqual(0, documents.Length);
//so we'll continue to getting the known variant, do not fully assert this because the Name will NULL
documents = snapshot.Content.GetAtRoot("fr-FR").ToArray();
Assert.AreEqual(1, documents.Length);
documents = snapshot.Content.GetById(1).Children().ToArray();
AssertDocuments(documents, "N4");
//Get the invariant and list children
documents = snapshot.Content.GetById(4).Children().ToArray();
AssertDocuments(documents, "N11");
//Get the variant and list children
documents = snapshot.Content.GetById(7).Children().ToArray();
AssertDocuments(documents, "N13");
}
[Test]
public void VariantChildrenTest()
{