Merge remote-tracking branch 'origin/v10/dev' into v11/dev

This commit is contained in:
Bjarke Berg
2023-05-23 12:12:32 +02:00
6 changed files with 81 additions and 29 deletions

View File

@@ -8,13 +8,23 @@ namespace Umbraco.Cms.Core.Xml;
/// </summary>
public class UmbracoXPathPathSyntaxParser
{
[Obsolete("This will be removed in Umbraco 13. Use ParseXPathQuery which accepts a parentId instead")]
public static string ParseXPathQuery(
string xpathExpression,
int? nodeContextId,
Func<int, IEnumerable<string>?> getPath,
Func<int, bool> publishedContentExists) => ParseXPathQuery(xpathExpression, nodeContextId, null, getPath, publishedContentExists);
/// <summary>
/// Parses custom umbraco xpath expression
/// </summary>
/// <param name="xpathExpression">The Xpath expression</param>
/// <param name="nodeContextId">
/// The current node id context of executing the query - null if there is no current node, in which case
/// some of the parameters like $current, $parent, $site will be disabled
/// The current node id context of executing the query - null if there is no current node.
/// </param>
/// <param name="parentId">
/// The parent node id of the current node id context of executing the query. With this we can determine the
/// $parent and $site parameters even if the current node is not yet published.
/// </param>
/// <param name="getPath">The callback to create the nodeId path, given a node Id</param>
/// <param name="publishedContentExists">The callback to return whether a published node exists based on Id</param>
@@ -22,6 +32,7 @@ public class UmbracoXPathPathSyntaxParser
public static string ParseXPathQuery(
string xpathExpression,
int? nodeContextId,
int? parentId,
Func<int, IEnumerable<string>?> getPath,
Func<int, bool> publishedContentExists)
{
@@ -84,19 +95,27 @@ public class UmbracoXPathPathSyntaxParser
// parseable items:
var vars = new Dictionary<string, Func<string, string>>();
// These parameters must have a node id context
if (nodeContextId.HasValue)
if (parentId.HasValue)
{
vars.Add("$parent", q =>
{
var path = getPath(parentId.Value)?.ToArray();
var closestPublishedAncestorId = getClosestPublishedAncestor(path);
return q.Replace("$parent", string.Format(rootXpath, closestPublishedAncestorId));
});
vars.Add("$site", q =>
{
var closestPublishedAncestorId = getClosestPublishedAncestor(getPath(parentId.Value));
return q.Replace(
"$site",
string.Format(rootXpath, closestPublishedAncestorId) + "/ancestor-or-self::*[@level = 1]");
});
}
else if (nodeContextId.HasValue)
{
vars.Add("$current", q =>
{
var closestPublishedAncestorId = getClosestPublishedAncestor(getPath(nodeContextId.Value));
return q.Replace("$current", string.Format(rootXpath, closestPublishedAncestorId));
});
vars.Add("$parent", q =>
{
// remove the first item in the array if its the current node
// this happens when current is published, but we are looking for its parent specifically
var path = getPath(nodeContextId.Value)?.ToArray();
if (path?[0] == nodeContextId.ToString())
{
@@ -116,6 +135,16 @@ public class UmbracoXPathPathSyntaxParser
});
}
// These parameters must have a node id context
if (nodeContextId.HasValue)
{
vars.Add("$current", q =>
{
var closestPublishedAncestorId = getClosestPublishedAncestor(getPath(nodeContextId.Value));
return q.Replace("$current", string.Format(rootXpath, closestPublishedAncestorId));
});
}
// TODO: This used to just replace $root with string.Empty BUT, that would never work
// the root is always "/root . Need to confirm with Per why this was string.Empty before!
vars.Add("$root", q => q.Replace("$root", "/root"));