Merge pull request #7542 from AndyButland/feature/netcore-publish-cache
Moved PublishedCache from Umbraco.Web into .Net standard project (#7551)
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
|
||||
namespace Umbraco.Infrastructure.PublishedCache
|
||||
{
|
||||
public static class CompositionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets the published snapshot service.
|
||||
/// </summary>
|
||||
/// <param name="composition">The composition.</param>
|
||||
/// <param name="factory">A function creating a published snapshot service.</param>
|
||||
public static void SetPublishedSnapshotService(this Composition composition, Func<IFactory, IPublishedSnapshotService> factory)
|
||||
{
|
||||
composition.RegisterUnique(factory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the published snapshot service.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the published snapshot service.</typeparam>
|
||||
/// <param name="composition">The composition.</param>
|
||||
public static void SetPublishedSnapshotService<T>(this Composition composition)
|
||||
where T : IPublishedSnapshotService
|
||||
{
|
||||
composition.RegisterUnique<IPublishedSnapshotService, T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the published snapshot service.
|
||||
/// </summary>
|
||||
/// <param name="composition">The composition.</param>
|
||||
/// <param name="service">A published snapshot service.</param>
|
||||
public static void SetPublishedSnapshotService(this Composition composition, IPublishedSnapshotService service)
|
||||
{
|
||||
composition.RegisterUnique(_ => service);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
public interface IPublishedCacheComposer : ICoreComposer
|
||||
{ }
|
||||
}
|
||||
@@ -60,11 +60,6 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
/// </summary>
|
||||
int CreatorId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the user who created the content item.
|
||||
/// </summary>
|
||||
string CreatorName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the date the content item was created.
|
||||
/// </summary>
|
||||
@@ -75,11 +70,6 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
/// </summary>
|
||||
int WriterId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the user who last updated the content item.
|
||||
/// </summary>
|
||||
string WriterName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the date the content item was last updated.
|
||||
/// </summary>
|
||||
@@ -90,15 +80,6 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
/// </remarks>
|
||||
DateTime UpdateDate { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the url of the content item for the current culture.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The value of this property is contextual. It depends on the 'current' request uri,
|
||||
/// if any.</para>
|
||||
/// </remarks>
|
||||
string Url { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets available culture infos.
|
||||
/// </summary>
|
||||
|
||||
-9
@@ -60,24 +60,15 @@ namespace Umbraco.Web.Models
|
||||
/// <inheritdoc />
|
||||
public abstract int CreatorId { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract string CreatorName { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract DateTime CreateDate { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract int WriterId { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract string WriterName { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract DateTime UpdateDate { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual string Url => this.Url();
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract IReadOnlyDictionary<string, PublishedCultureInfo> Cultures { get; }
|
||||
|
||||
@@ -78,24 +78,15 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
/// <inheritdoc />
|
||||
public virtual int CreatorId => _content.CreatorId;
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual string CreatorName => _content.CreatorName;
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual DateTime CreateDate => _content.CreateDate;
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual int WriterId => _content.WriterId;
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual string WriterName => _content.WriterName;
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual DateTime UpdateDate => _content.UpdateDate;
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual string Url => _content.Url;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyDictionary<string, PublishedCultureInfo> Cultures => _content.Cultures;
|
||||
|
||||
|
||||
@@ -160,5 +160,15 @@ namespace Umbraco.Web.PublishedCache
|
||||
void Notify(DomainCacheRefresher.JsonPayload[] payloads);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Status
|
||||
|
||||
string GetStatus();
|
||||
|
||||
string StatusUrl { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
void Collect();
|
||||
}
|
||||
}
|
||||
|
||||
+9
-2
@@ -8,8 +8,15 @@ using Umbraco.Core.Xml;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache
|
||||
{
|
||||
abstract class PublishedCacheBase : IPublishedCache
|
||||
public abstract class PublishedCacheBase : IPublishedCache
|
||||
{
|
||||
private readonly IVariationContextAccessor _variationContextAccessor;
|
||||
|
||||
public PublishedCacheBase(IVariationContextAccessor variationContextAccessor)
|
||||
{
|
||||
_variationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor));
|
||||
|
||||
}
|
||||
public bool PreviewDefault { get; }
|
||||
|
||||
protected PublishedCacheBase(bool previewDefault)
|
||||
@@ -97,7 +104,7 @@ namespace Umbraco.Web.PublishedCache
|
||||
// this is probably not super-efficient, but works
|
||||
// some cache implementation may want to override it, though
|
||||
return GetAtRoot()
|
||||
.SelectMany(x => x.DescendantsOrSelf())
|
||||
.SelectMany(x => x.DescendantsOrSelf(_variationContextAccessor))
|
||||
.Where(x => x.ContentType.Id == contentType.Id);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -14,7 +14,7 @@ namespace Umbraco.Web.PublishedCache
|
||||
// an entirely new models factory + not even sure it makes sense at all since
|
||||
// sets are created manually todo yes it does! - what does this all mean?
|
||||
//
|
||||
internal class PublishedElement : IPublishedElement
|
||||
public class PublishedElement : IPublishedElement
|
||||
{
|
||||
// initializes a new instance of the PublishedElement class
|
||||
// within the context of a published snapshot service (eg a published content property value)
|
||||
-4
@@ -141,10 +141,6 @@ namespace Umbraco.Web.PublishedCache
|
||||
|
||||
public override string UrlSegment => throw new NotSupportedException();
|
||||
|
||||
public override string WriterName => _member.GetCreatorProfile(_userService).Name;
|
||||
|
||||
public override string CreatorName => _member.GetCreatorProfile(_userService).Name;
|
||||
|
||||
public override int WriterId => _member.CreatorId;
|
||||
|
||||
public override int CreatorId => _member.CreatorId;
|
||||
+9
-1
@@ -5,7 +5,7 @@ using Umbraco.Web.Cache;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache
|
||||
{
|
||||
abstract class PublishedSnapshotServiceBase : IPublishedSnapshotService
|
||||
public abstract class PublishedSnapshotServiceBase : IPublishedSnapshotService
|
||||
{
|
||||
protected PublishedSnapshotServiceBase(IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor)
|
||||
{
|
||||
@@ -38,5 +38,13 @@ namespace Umbraco.Web.PublishedCache
|
||||
|
||||
public virtual void Dispose()
|
||||
{ }
|
||||
|
||||
public abstract string GetStatus();
|
||||
|
||||
public virtual string StatusUrl => "views/dashboard/settings/publishedsnapshotcache.html";
|
||||
|
||||
public virtual void Collect()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
@@ -100,7 +101,6 @@ namespace Umbraco.Core
|
||||
return culture != "" && content.Cultures.TryGetValue(culture, out var infos) ? infos.Date : DateTime.MinValue;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the children of the content item.
|
||||
/// </summary>
|
||||
@@ -135,5 +135,727 @@ namespace Umbraco.Core
|
||||
? children
|
||||
: children.Where(x => x.IsInvariantOrHasCulture(culture));
|
||||
}
|
||||
|
||||
#region Writer and creator
|
||||
|
||||
public static string GetCreatorName(this IPublishedContent content, IUserService userService)
|
||||
{
|
||||
var user = userService.GetProfileById(content.CreatorId);
|
||||
return user?.Name;
|
||||
}
|
||||
|
||||
public static string GetWriterName(this IPublishedContent content, IUserService userService)
|
||||
{
|
||||
var user = userService.GetProfileById(content.WriterId);
|
||||
return user?.Name;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Axes: ancestors, ancestors-or-self
|
||||
|
||||
// as per XPath 1.0 specs �2.2,
|
||||
// - the ancestor axis contains the ancestors of the context node; the ancestors of the context node consist
|
||||
// of the parent of context node and the parent's parent and so on; thus, the ancestor axis will always
|
||||
// include the root node, unless the context node is the root node.
|
||||
// - the ancestor-or-self axis contains the context node and the ancestors of the context node; thus,
|
||||
// the ancestor axis will always include the root node.
|
||||
//
|
||||
// as per XPath 2.0 specs �3.2.1.1,
|
||||
// - the ancestor axis is defined as the transitive closure of the parent axis; it contains the ancestors
|
||||
// of the context node (the parent, the parent of the parent, and so on) - The ancestor axis includes the
|
||||
// root node of the tree in which the context node is found, unless the context node is the root node.
|
||||
// - the ancestor-or-self axis contains the context node and the ancestors of the context node; thus,
|
||||
// the ancestor-or-self axis will always include the root node.
|
||||
//
|
||||
// the ancestor and ancestor-or-self axis are reverse axes ie they contain the context node or nodes that
|
||||
// are before the context node in document order.
|
||||
//
|
||||
// document order is defined by �2.4.1 as:
|
||||
// - the root node is the first node.
|
||||
// - every node occurs before all of its children and descendants.
|
||||
// - the relative order of siblings is the order in which they occur in the children property of their parent node.
|
||||
// - children and descendants occur before following siblings.
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ancestors of the content.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The ancestors of the content, in down-top order.</returns>
|
||||
/// <remarks>Does not consider the content itself.</remarks>
|
||||
public static IEnumerable<IPublishedContent> Ancestors(this IPublishedContent content)
|
||||
{
|
||||
return content.AncestorsOrSelf(false, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ancestors of the content, at a level lesser or equal to a specified level.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="maxLevel">The level.</param>
|
||||
/// <returns>The ancestors of the content, at a level lesser or equal to the specified level, in down-top order.</returns>
|
||||
/// <remarks>Does not consider the content itself. Only content that are "high enough" in the tree are returned.</remarks>
|
||||
public static IEnumerable<IPublishedContent> Ancestors(this IPublishedContent content, int maxLevel)
|
||||
{
|
||||
return content.AncestorsOrSelf(false, n => n.Level <= maxLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ancestors of the content, of a specified content type.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="contentTypeAlias">The content type.</param>
|
||||
/// <returns>The ancestors of the content, of the specified content type, in down-top order.</returns>
|
||||
/// <remarks>Does not consider the content itself. Returns all ancestors, of the specified content type.</remarks>
|
||||
public static IEnumerable<IPublishedContent> Ancestors(this IPublishedContent content, string contentTypeAlias)
|
||||
{
|
||||
return content.AncestorsOrSelf(false, n => n.ContentType.Alias.InvariantEquals(contentTypeAlias));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ancestors of the content, of a specified content type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The ancestors of the content, of the specified content type, in down-top order.</returns>
|
||||
/// <remarks>Does not consider the content itself. Returns all ancestors, of the specified content type.</remarks>
|
||||
public static IEnumerable<T> Ancestors<T>(this IPublishedContent content)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Ancestors().OfType<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ancestors of the content, at a level lesser or equal to a specified level, and of a specified content type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="maxLevel">The level.</param>
|
||||
/// <returns>The ancestors of the content, at a level lesser or equal to the specified level, and of the specified
|
||||
/// content type, in down-top order.</returns>
|
||||
/// <remarks>Does not consider the content itself. Only content that are "high enough" in the trees, and of the
|
||||
/// specified content type, are returned.</remarks>
|
||||
public static IEnumerable<T> Ancestors<T>(this IPublishedContent content, int maxLevel)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Ancestors(maxLevel).OfType<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content and its ancestors.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The content and its ancestors, in down-top order.</returns>
|
||||
public static IEnumerable<IPublishedContent> AncestorsOrSelf(this IPublishedContent content)
|
||||
{
|
||||
return content.AncestorsOrSelf(true, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content and its ancestors, at a level lesser or equal to a specified level.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="maxLevel">The level.</param>
|
||||
/// <returns>The content and its ancestors, at a level lesser or equal to the specified level,
|
||||
/// in down-top order.</returns>
|
||||
/// <remarks>Only content that are "high enough" in the tree are returned. So it may or may not begin
|
||||
/// with the content itself, depending on its level.</remarks>
|
||||
public static IEnumerable<IPublishedContent> AncestorsOrSelf(this IPublishedContent content, int maxLevel)
|
||||
{
|
||||
return content.AncestorsOrSelf(true, n => n.Level <= maxLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content and its ancestors, of a specified content type.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="contentTypeAlias">The content type.</param>
|
||||
/// <returns>The content and its ancestors, of the specified content type, in down-top order.</returns>
|
||||
/// <remarks>May or may not begin with the content itself, depending on its content type.</remarks>
|
||||
public static IEnumerable<IPublishedContent> AncestorsOrSelf(this IPublishedContent content, string contentTypeAlias)
|
||||
{
|
||||
return content.AncestorsOrSelf(true, n => n.ContentType.Alias.InvariantEquals(contentTypeAlias));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content and its ancestors, of a specified content type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The content and its ancestors, of the specified content type, in down-top order.</returns>
|
||||
/// <remarks>May or may not begin with the content itself, depending on its content type.</remarks>
|
||||
public static IEnumerable<T> AncestorsOrSelf<T>(this IPublishedContent content)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.AncestorsOrSelf().OfType<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content and its ancestor, at a lever lesser or equal to a specified level, and of a specified content type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="maxLevel">The level.</param>
|
||||
/// <returns>The content and its ancestors, at a level lesser or equal to the specified level, and of the specified
|
||||
/// content type, in down-top order.</returns>
|
||||
/// <remarks>May or may not begin with the content itself, depending on its level and content type.</remarks>
|
||||
public static IEnumerable<T> AncestorsOrSelf<T>(this IPublishedContent content, int maxLevel)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.AncestorsOrSelf(maxLevel).OfType<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ancestor of the content, ie its parent.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The ancestor of the content.</returns>
|
||||
/// <remarks>This method is here for consistency purposes but does not make much sense.</remarks>
|
||||
public static IPublishedContent Ancestor(this IPublishedContent content)
|
||||
{
|
||||
return content.Parent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the nearest ancestor of the content, at a lever lesser or equal to a specified level.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="maxLevel">The level.</param>
|
||||
/// <returns>The nearest (in down-top order) ancestor of the content, at a level lesser or equal to the specified level.</returns>
|
||||
/// <remarks>Does not consider the content itself. May return <c>null</c>.</remarks>
|
||||
public static IPublishedContent Ancestor(this IPublishedContent content, int maxLevel)
|
||||
{
|
||||
return content.EnumerateAncestors(false).FirstOrDefault(x => x.Level <= maxLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the nearest ancestor of the content, of a specified content type.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="contentTypeAlias">The content type alias.</param>
|
||||
/// <returns>The nearest (in down-top order) ancestor of the content, of the specified content type.</returns>
|
||||
/// <remarks>Does not consider the content itself. May return <c>null</c>.</remarks>
|
||||
public static IPublishedContent Ancestor(this IPublishedContent content, string contentTypeAlias)
|
||||
{
|
||||
return content.EnumerateAncestors(false).FirstOrDefault(x => x.ContentType.Alias.InvariantEquals(contentTypeAlias));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the nearest ancestor of the content, of a specified content type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The nearest (in down-top order) ancestor of the content, of the specified content type.</returns>
|
||||
/// <remarks>Does not consider the content itself. May return <c>null</c>.</remarks>
|
||||
public static T Ancestor<T>(this IPublishedContent content)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Ancestors<T>().FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the nearest ancestor of the content, at the specified level and of the specified content type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="maxLevel">The level.</param>
|
||||
/// <returns>The ancestor of the content, at the specified level and of the specified content type.</returns>
|
||||
/// <remarks>Does not consider the content itself. If the ancestor at the specified level is
|
||||
/// not of the specified type, returns <c>null</c>.</remarks>
|
||||
public static T Ancestor<T>(this IPublishedContent content, int maxLevel)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Ancestors<T>(maxLevel).FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content or its nearest ancestor.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The content.</returns>
|
||||
/// <remarks>This method is here for consistency purposes but does not make much sense.</remarks>
|
||||
public static IPublishedContent AncestorOrSelf(this IPublishedContent content)
|
||||
{
|
||||
return content;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content or its nearest ancestor, at a lever lesser or equal to a specified level.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="maxLevel">The level.</param>
|
||||
/// <returns>The content or its nearest (in down-top order) ancestor, at a level lesser or equal to the specified level.</returns>
|
||||
/// <remarks>May or may not return the content itself depending on its level. May return <c>null</c>.</remarks>
|
||||
public static IPublishedContent AncestorOrSelf(this IPublishedContent content, int maxLevel)
|
||||
{
|
||||
return content.EnumerateAncestors(true).FirstOrDefault(x => x.Level <= maxLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content or its nearest ancestor, of a specified content type.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="contentTypeAlias">The content type.</param>
|
||||
/// <returns>The content or its nearest (in down-top order) ancestor, of the specified content type.</returns>
|
||||
/// <remarks>May or may not return the content itself depending on its content type. May return <c>null</c>.</remarks>
|
||||
public static IPublishedContent AncestorOrSelf(this IPublishedContent content, string contentTypeAlias)
|
||||
{
|
||||
return content.EnumerateAncestors(true).FirstOrDefault(x => x.ContentType.Alias.InvariantEquals(contentTypeAlias));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content or its nearest ancestor, of a specified content type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The content or its nearest (in down-top order) ancestor, of the specified content type.</returns>
|
||||
/// <remarks>May or may not return the content itself depending on its content type. May return <c>null</c>.</remarks>
|
||||
public static T AncestorOrSelf<T>(this IPublishedContent content)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.AncestorsOrSelf<T>().FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content or its nearest ancestor, at a lever lesser or equal to a specified level, and of a specified content type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="maxLevel">The level.</param>
|
||||
/// <returns></returns>
|
||||
public static T AncestorOrSelf<T>(this IPublishedContent content, int maxLevel)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.AncestorsOrSelf<T>(maxLevel).FirstOrDefault();
|
||||
}
|
||||
|
||||
public static IEnumerable<IPublishedContent> AncestorsOrSelf(this IPublishedContent content, bool orSelf, Func<IPublishedContent, bool> func)
|
||||
{
|
||||
var ancestorsOrSelf = content.EnumerateAncestors(orSelf);
|
||||
return func == null ? ancestorsOrSelf : ancestorsOrSelf.Where(func);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enumerates ancestors of the content, bottom-up.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="orSelf">Indicates whether the content should be included.</param>
|
||||
/// <returns>Enumerates bottom-up ie walking up the tree (parent, grand-parent, etc).</returns>
|
||||
internal static IEnumerable<IPublishedContent> EnumerateAncestors(this IPublishedContent content, bool orSelf)
|
||||
{
|
||||
if (content == null) throw new ArgumentNullException(nameof(content));
|
||||
if (orSelf) yield return content;
|
||||
while ((content = content.Parent) != null)
|
||||
yield return content;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Axes: descendants, descendants-or-self
|
||||
|
||||
/// <summary>
|
||||
/// Returns all DescendantsOrSelf of all content referenced
|
||||
/// </summary>
|
||||
/// <param name="parentNodes"></param>
|
||||
/// <param name="variationContextAccessor">Variation context accessor.</param>
|
||||
/// <param name="docTypeAlias"></param>
|
||||
/// <param name="culture">The specific culture to filter for. If null is used the current culture is used. (Default is null)</param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This can be useful in order to return all nodes in an entire site by a type when combined with TypedContentAtRoot
|
||||
/// </remarks>
|
||||
public static IEnumerable<IPublishedContent> DescendantsOrSelfOfType(this IEnumerable<IPublishedContent> parentNodes, IVariationContextAccessor variationContextAccessor, string docTypeAlias, string culture = null)
|
||||
{
|
||||
return parentNodes.SelectMany(x => x.DescendantsOrSelfOfType(variationContextAccessor, docTypeAlias, culture));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all DescendantsOrSelf of all content referenced
|
||||
/// </summary>
|
||||
/// <param name="parentNodes"></param>
|
||||
/// <param name="variationContextAccessor">Variation context accessor.</param>
|
||||
/// <param name="culture">The specific culture to filter for. If null is used the current culture is used. (Default is null)</param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This can be useful in order to return all nodes in an entire site by a type when combined with TypedContentAtRoot
|
||||
/// </remarks>
|
||||
public static IEnumerable<T> DescendantsOrSelf<T>(this IEnumerable<IPublishedContent> parentNodes, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return parentNodes.SelectMany(x => x.DescendantsOrSelf<T>(variationContextAccessor, culture));
|
||||
}
|
||||
|
||||
|
||||
// as per XPath 1.0 specs �2.2,
|
||||
// - the descendant axis contains the descendants of the context node; a descendant is a child or a child of a child and so on; thus
|
||||
// the descendant axis never contains attribute or namespace nodes.
|
||||
// - the descendant-or-self axis contains the context node and the descendants of the context node.
|
||||
//
|
||||
// as per XPath 2.0 specs �3.2.1.1,
|
||||
// - the descendant axis is defined as the transitive closure of the child axis; it contains the descendants of the context node (the
|
||||
// children, the children of the children, and so on).
|
||||
// - the descendant-or-self axis contains the context node and the descendants of the context node.
|
||||
//
|
||||
// the descendant and descendant-or-self axis are forward axes ie they contain the context node or nodes that are after the context
|
||||
// node in document order.
|
||||
//
|
||||
// document order is defined by �2.4.1 as:
|
||||
// - the root node is the first node.
|
||||
// - every node occurs before all of its children and descendants.
|
||||
// - the relative order of siblings is the order in which they occur in the children property of their parent node.
|
||||
// - children and descendants occur before following siblings.
|
||||
|
||||
public static IEnumerable<IPublishedContent> Descendants(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
{
|
||||
return content.DescendantsOrSelf(variationContextAccessor, false, null, culture);
|
||||
}
|
||||
|
||||
public static IEnumerable<IPublishedContent> Descendants(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string culture = null)
|
||||
{
|
||||
return content.DescendantsOrSelf(variationContextAccessor, false, p => p.Level >= level, culture);
|
||||
}
|
||||
|
||||
public static IEnumerable<IPublishedContent> DescendantsOfType(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string culture = null)
|
||||
{
|
||||
return content.DescendantsOrSelf(variationContextAccessor, false, p => p.ContentType.Alias.InvariantEquals(contentTypeAlias), culture);
|
||||
}
|
||||
|
||||
public static IEnumerable<T> Descendants<T>(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Descendants(variationContextAccessor, culture).OfType<T>();
|
||||
}
|
||||
|
||||
public static IEnumerable<T> Descendants<T>(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Descendants(variationContextAccessor, level, culture).OfType<T>();
|
||||
}
|
||||
|
||||
public static IEnumerable<IPublishedContent> DescendantsOrSelf(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
{
|
||||
return content.DescendantsOrSelf(variationContextAccessor, true, null, culture);
|
||||
}
|
||||
|
||||
public static IEnumerable<IPublishedContent> DescendantsOrSelf(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string culture = null)
|
||||
{
|
||||
return content.DescendantsOrSelf(variationContextAccessor, true, p => p.Level >= level, culture);
|
||||
}
|
||||
|
||||
public static IEnumerable<IPublishedContent> DescendantsOrSelfOfType(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string culture = null)
|
||||
{
|
||||
return content.DescendantsOrSelf(variationContextAccessor, true, p => p.ContentType.Alias.InvariantEquals(contentTypeAlias), culture);
|
||||
}
|
||||
|
||||
public static IEnumerable<T> DescendantsOrSelf<T>(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.DescendantsOrSelf(variationContextAccessor, culture).OfType<T>();
|
||||
}
|
||||
|
||||
public static IEnumerable<T> DescendantsOrSelf<T>(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.DescendantsOrSelf(variationContextAccessor, level, culture).OfType<T>();
|
||||
}
|
||||
|
||||
public static IPublishedContent Descendant(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
{
|
||||
return content.Children(variationContextAccessor, culture).FirstOrDefault();
|
||||
}
|
||||
|
||||
public static IPublishedContent Descendant(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string culture = null)
|
||||
{
|
||||
return content.EnumerateDescendants(variationContextAccessor, false, culture).FirstOrDefault(x => x.Level == level);
|
||||
}
|
||||
|
||||
public static IPublishedContent DescendantOfType(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string culture = null)
|
||||
{
|
||||
return content.EnumerateDescendants(variationContextAccessor, false, culture).FirstOrDefault(x => x.ContentType.Alias.InvariantEquals(contentTypeAlias));
|
||||
}
|
||||
|
||||
public static T Descendant<T>(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.EnumerateDescendants(variationContextAccessor, false, culture).FirstOrDefault(x => x is T) as T;
|
||||
}
|
||||
|
||||
public static T Descendant<T>(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Descendant(variationContextAccessor, level, culture) as T;
|
||||
}
|
||||
|
||||
public static IPublishedContent DescendantOrSelf(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
{
|
||||
return content;
|
||||
}
|
||||
|
||||
public static IPublishedContent DescendantOrSelf(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string culture = null)
|
||||
{
|
||||
return content.EnumerateDescendants(variationContextAccessor, true, culture).FirstOrDefault(x => x.Level == level);
|
||||
}
|
||||
|
||||
public static IPublishedContent DescendantOrSelfOfType(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string culture = null)
|
||||
{
|
||||
return content.EnumerateDescendants(variationContextAccessor, true, culture).FirstOrDefault(x => x.ContentType.Alias.InvariantEquals(contentTypeAlias));
|
||||
}
|
||||
|
||||
public static T DescendantOrSelf<T>(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.EnumerateDescendants(variationContextAccessor, true, culture).FirstOrDefault(x => x is T) as T;
|
||||
}
|
||||
|
||||
public static T DescendantOrSelf<T>(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.DescendantOrSelf(variationContextAccessor, level, culture) as T;
|
||||
}
|
||||
|
||||
internal static IEnumerable<IPublishedContent> DescendantsOrSelf(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, bool orSelf, Func<IPublishedContent, bool> func, string culture = null)
|
||||
{
|
||||
return content.EnumerateDescendants(variationContextAccessor, orSelf, culture).Where(x => func == null || func(x));
|
||||
}
|
||||
|
||||
internal static IEnumerable<IPublishedContent> EnumerateDescendants(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, bool orSelf, string culture = null)
|
||||
{
|
||||
if (content == null) throw new ArgumentNullException(nameof(content));
|
||||
if (orSelf) yield return content;
|
||||
|
||||
foreach (var desc in content.Children(variationContextAccessor, culture).SelectMany(x => x.EnumerateDescendants(variationContextAccessor, culture)))
|
||||
yield return desc;
|
||||
}
|
||||
|
||||
internal static IEnumerable<IPublishedContent> EnumerateDescendants(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
{
|
||||
yield return content;
|
||||
|
||||
foreach (var desc in content.Children(variationContextAccessor, culture).SelectMany(x => x.EnumerateDescendants(variationContextAccessor, culture)))
|
||||
yield return desc;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Axes: children
|
||||
|
||||
/// <summary>
|
||||
/// Gets the children of the content, filtered by a predicate.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="publishedSnapshot">Published snapshot instance</param>
|
||||
/// <param name="predicate">The predicate.</param>
|
||||
/// <param name="culture">The specific culture to filter for. If null is used the current culture is used. (Default is null)</param>
|
||||
/// <returns>The children of the content, filtered by the predicate.</returns>
|
||||
/// <remarks>
|
||||
/// <para>Children are sorted by their sortOrder.</para>
|
||||
/// </remarks>
|
||||
public static IEnumerable<IPublishedContent> Children(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, Func<IPublishedContent, bool> predicate, string culture = null)
|
||||
{
|
||||
return content.Children(variationContextAccessor, culture).Where(predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the children of the content, of any of the specified types.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="publishedSnapshot">Published snapshot instance</param>
|
||||
/// <param name="culture">The specific culture to filter for. If null is used the current culture is used. (Default is null)</param>
|
||||
/// <param name="contentTypeAlias">The content type alias.</param>
|
||||
/// <returns>The children of the content, of any of the specified types.</returns>
|
||||
public static IEnumerable<IPublishedContent> ChildrenOfType(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string culture = null)
|
||||
{
|
||||
return content.Children(variationContextAccessor, x => x.ContentType.Alias.InvariantEquals(contentTypeAlias), culture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the children of the content, of a given content type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="publishedSnapshot">Published snapshot instance</param>
|
||||
/// <param name="culture">The specific culture to filter for. If null is used the current culture is used. (Default is null)</param>
|
||||
/// <returns>The children of content, of the given content type.</returns>
|
||||
/// <remarks>
|
||||
/// <para>Children are sorted by their sortOrder.</para>
|
||||
/// </remarks>
|
||||
public static IEnumerable<T> Children<T>(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Children(variationContextAccessor, culture).OfType<T>();
|
||||
}
|
||||
|
||||
public static IPublishedContent FirstChild(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
{
|
||||
return content.Children(variationContextAccessor, culture).FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the first child of the content, of a given content type.
|
||||
/// </summary>
|
||||
public static IPublishedContent FirstChildOfType(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string culture = null)
|
||||
{
|
||||
return content.ChildrenOfType(variationContextAccessor, contentTypeAlias, culture).FirstOrDefault();
|
||||
}
|
||||
|
||||
public static IPublishedContent FirstChild(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, Func<IPublishedContent, bool> predicate, string culture = null)
|
||||
{
|
||||
return content.Children(variationContextAccessor, predicate, culture).FirstOrDefault();
|
||||
}
|
||||
|
||||
public static IPublishedContent FirstChild(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, Guid uniqueId, string culture = null)
|
||||
{
|
||||
return content.Children(variationContextAccessor, x => x.Key == uniqueId, culture).FirstOrDefault();
|
||||
}
|
||||
|
||||
public static T FirstChild<T>(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Children<T>(variationContextAccessor, culture).FirstOrDefault();
|
||||
}
|
||||
|
||||
public static T FirstChild<T>(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, Func<T, bool> predicate, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Children<T>(variationContextAccessor, culture).FirstOrDefault(predicate);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Axes: parent
|
||||
|
||||
// Parent is native
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parent of the content, of a given content type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The parent of content, of the given content type, else null.</returns>
|
||||
public static T Parent<T>(this IPublishedContent content)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
if (content == null) throw new ArgumentNullException(nameof(content));
|
||||
return content.Parent as T;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Axes: Siblings
|
||||
|
||||
/// <summary>
|
||||
/// Gets the siblings of the content.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="publishedSnapshot">Published snapshot instance</param>
|
||||
/// <param name="variationContextAccessor">Variation context accessor.</param>
|
||||
/// <param name="culture">The specific culture to filter for. If null is used the current culture is used. (Default is null)</param>
|
||||
/// <returns>The siblings of the content.</returns>
|
||||
/// <remarks>
|
||||
/// <para>Note that in V7 this method also return the content node self.</para>
|
||||
/// </remarks>
|
||||
public static IEnumerable<IPublishedContent> Siblings(this IPublishedContent content, IPublishedSnapshot publishedSnapshot, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
{
|
||||
return SiblingsAndSelf(content, publishedSnapshot, variationContextAccessor, culture).Where(x => x.Id != content.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the siblings of the content, of a given content type.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="publishedSnapshot">Published snapshot instance</param>
|
||||
/// <param name="variationContextAccessor">Variation context accessor.</param>
|
||||
/// <param name="culture">The specific culture to filter for. If null is used the current culture is used. (Default is null)</param>
|
||||
/// <param name="contentTypeAlias">The content type alias.</param>
|
||||
/// <returns>The siblings of the content, of the given content type.</returns>
|
||||
/// <remarks>
|
||||
/// <para>Note that in V7 this method also return the content node self.</para>
|
||||
/// </remarks>
|
||||
public static IEnumerable<IPublishedContent> SiblingsOfType(this IPublishedContent content, IPublishedSnapshot publishedSnapshot, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string culture = null)
|
||||
{
|
||||
return SiblingsAndSelfOfType(content, publishedSnapshot, variationContextAccessor, contentTypeAlias, culture).Where(x => x.Id != content.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the siblings of the content, of a given content type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="publishedSnapshot">Published snapshot instance</param>
|
||||
/// <param name="variationContextAccessor">Variation context accessor.</param>
|
||||
/// <param name="culture">The specific culture to filter for. If null is used the current culture is used. (Default is null)</param>
|
||||
/// <returns>The siblings of the content, of the given content type.</returns>
|
||||
/// <remarks>
|
||||
/// <para>Note that in V7 this method also return the content node self.</para>
|
||||
/// </remarks>
|
||||
public static IEnumerable<T> Siblings<T>(this IPublishedContent content, IPublishedSnapshot publishedSnapshot, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return SiblingsAndSelf<T>(content, publishedSnapshot, variationContextAccessor, culture).Where(x => x.Id != content.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the siblings of the content including the node itself to indicate the position.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="publishedSnapshot">Published snapshot instance</param>
|
||||
/// <param name="variationContextAccessor">Variation context accessor.</param>
|
||||
/// <param name="culture">The specific culture to filter for. If null is used the current culture is used. (Default is null)</param>
|
||||
/// <returns>The siblings of the content including the node itself.</returns>
|
||||
public static IEnumerable<IPublishedContent> SiblingsAndSelf(this IPublishedContent content, IPublishedSnapshot publishedSnapshot, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
{
|
||||
return content.Parent != null
|
||||
? content.Parent.Children(variationContextAccessor, culture)
|
||||
: publishedSnapshot.Content.GetAtRoot().WhereIsInvariantOrHasCulture(variationContextAccessor, culture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the siblings of the content including the node itself to indicate the position, of a given content type.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="publishedSnapshot">Published snapshot instance</param>
|
||||
/// <param name="variationContextAccessor">Variation context accessor.</param>
|
||||
/// <param name="culture">The specific culture to filter for. If null is used the current culture is used. (Default is null)</param>
|
||||
/// <param name="contentTypeAlias">The content type alias.</param>
|
||||
/// <returns>The siblings of the content including the node itself, of the given content type.</returns>
|
||||
public static IEnumerable<IPublishedContent> SiblingsAndSelfOfType(this IPublishedContent content, IPublishedSnapshot publishedSnapshot, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string culture = null)
|
||||
{
|
||||
return content.Parent != null
|
||||
? content.Parent.ChildrenOfType(variationContextAccessor, contentTypeAlias, culture)
|
||||
: publishedSnapshot.Content.GetAtRoot().OfTypes(contentTypeAlias).WhereIsInvariantOrHasCulture(variationContextAccessor, culture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the siblings of the content including the node itself to indicate the position, of a given content type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="publishedSnapshot">Published snapshot instance</param>
|
||||
/// <param name="variationContextAccessor">Variation context accessor.</param>
|
||||
/// <param name="culture">The specific culture to filter for. If null is used the current culture is used. (Default is null)</param>
|
||||
/// <returns>The siblings of the content including the node itself, of the given content type.</returns>
|
||||
public static IEnumerable<T> SiblingsAndSelf<T>(this IPublishedContent content, IPublishedSnapshot publishedSnapshot, IVariationContextAccessor variationContextAccessor, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Parent != null
|
||||
? content.Parent.Children<T>(variationContextAccessor, culture)
|
||||
: publishedSnapshot.Content.GetAtRoot().OfType<T>().WhereIsInvariantOrHasCulture(variationContextAccessor, culture);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Axes: custom
|
||||
|
||||
/// <summary>
|
||||
/// Gets the root content for this content.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The 'site' content ie AncestorOrSelf(1).</returns>
|
||||
public static IPublishedContent Root(this IPublishedContent content)
|
||||
{
|
||||
return content.AncestorOrSelf(1);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides extension methods for <c>IPublishedElement</c>.
|
||||
/// </summary>
|
||||
public static class PublishedElementExtensions
|
||||
{
|
||||
#region OfTypes
|
||||
|
||||
// the .OfType<T>() filter is nice when there's only one type
|
||||
// this is to support filtering with multiple types
|
||||
public static IEnumerable<T> OfTypes<T>(this IEnumerable<T> contents, params string[] types)
|
||||
where T : IPublishedElement
|
||||
{
|
||||
if (types == null || types.Length == 0) return Enumerable.Empty<T>();
|
||||
|
||||
return contents.Where(x => types.InvariantContains(x.ContentType.Alias));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -25,7 +25,7 @@ namespace Umbraco.Web.PublishedCache
|
||||
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
|
||||
|
||||
// default ctor
|
||||
internal PublishedContentTypeCache(IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, IMemberTypeService memberTypeService, IPublishedContentTypeFactory publishedContentTypeFactory, ILogger logger)
|
||||
public PublishedContentTypeCache(IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, IMemberTypeService memberTypeService, IPublishedContentTypeFactory publishedContentTypeFactory, ILogger logger)
|
||||
{
|
||||
_contentTypeService = contentTypeService;
|
||||
_mediaTypeService = mediaTypeService;
|
||||
@@ -51,9 +51,6 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
|
||||
<_Parameter1>Umbraco.Core</_Parameter1>
|
||||
</AssemblyAttribute>
|
||||
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
|
||||
<_Parameter1>Umbraco.Tests</_Parameter1>
|
||||
</AssemblyAttribute>
|
||||
|
||||
@@ -3,19 +3,16 @@ using System.Reflection;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.ModelsBuilder.Embedded.Building;
|
||||
using Umbraco.ModelsBuilder.Embedded.Configuration;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.PublishedCache.NuCache;
|
||||
using Umbraco.Web.Features;
|
||||
|
||||
namespace Umbraco.ModelsBuilder.Embedded.Compose
|
||||
{
|
||||
|
||||
|
||||
[ComposeBefore(typeof(NuCacheComposer))]
|
||||
[ComposeBefore(typeof(IPublishedCacheComposer))]
|
||||
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
|
||||
public sealed class ModelsBuilderComposer : ICoreComposer
|
||||
{
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// represents a content "node" ie a pair of draft + published versions
|
||||
// internal, never exposed, to be accessed from ContentStore (only!)
|
||||
[DebuggerDisplay("Id: {Id}, Path: {Path}")]
|
||||
internal class ContentNode
|
||||
public class ContentNode
|
||||
{
|
||||
// special ctor for root pseudo node
|
||||
public ContentNode()
|
||||
@@ -113,7 +113,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// everything that is common to both draft and published versions
|
||||
// keep this as small as possible
|
||||
|
||||
|
||||
|
||||
public readonly int Id;
|
||||
public readonly Guid Uid;
|
||||
public IPublishedContentType ContentType;
|
||||
+1
-1
@@ -4,7 +4,7 @@ using Umbraco.Web.PublishedCache.NuCache.DataSource;
|
||||
namespace Umbraco.Web.PublishedCache.NuCache
|
||||
{
|
||||
// what's needed to actually build a content node
|
||||
internal struct ContentNodeKit
|
||||
public struct ContentNodeKit
|
||||
{
|
||||
public ContentNode Node;
|
||||
public int ContentTypeId;
|
||||
+2
-2
@@ -26,7 +26,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
/// This class's logic is based on the <see cref="SnapDictionary{TKey, TValue}"/> class but has been slightly modified to suit these purposes.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
internal class ContentStore
|
||||
public class ContentStore
|
||||
{
|
||||
// this class is an extended version of SnapDictionary
|
||||
// most of the snapshots management code, etc is an exact copy
|
||||
@@ -1329,7 +1329,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
return _collectTask;
|
||||
|
||||
// ReSharper disable InconsistentlySynchronizedField
|
||||
var task = _collectTask = Task.Run(Collect);
|
||||
var task = _collectTask = Task.Run((Action)Collect);
|
||||
_collectTask.ContinueWith(_ =>
|
||||
{
|
||||
lock (_rlocko)
|
||||
+1
-1
@@ -4,7 +4,7 @@ using System.Collections.Generic;
|
||||
namespace Umbraco.Web.PublishedCache.NuCache.DataSource
|
||||
{
|
||||
// represents everything that is specific to edited or published version
|
||||
internal class ContentData
|
||||
public class ContentData
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string UrlSegment { get; set; }
|
||||
+1
-1
@@ -6,7 +6,7 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
|
||||
/// <summary>
|
||||
/// Represents the culture variation information on a content item
|
||||
/// </summary>
|
||||
internal class CultureVariation
|
||||
public class CultureVariation
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
+10
-4
@@ -10,7 +10,6 @@ using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
using Umbraco.Core.Scoping;
|
||||
using Umbraco.Core.Serialization;
|
||||
using Umbraco.Web.Composing;
|
||||
using static Umbraco.Core.Persistence.SqlExtensionsStatics;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache.NuCache.DataSource
|
||||
@@ -20,6 +19,13 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
|
||||
// provides efficient database access for NuCache
|
||||
internal class DatabaseDataSource : IDataSource
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public DatabaseDataSource(ILogger logger)
|
||||
{
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
// we want arrays, we want them all loaded, not an enumerable
|
||||
|
||||
private Sql<ISqlContext> ContentSourcesSelect(IScope scope, Func<Sql<ISqlContext>, Sql<ISqlContext>> joins = null)
|
||||
@@ -181,7 +187,7 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
|
||||
return scope.Database.Query<ContentSourceDto>(sql).Select(CreateMediaNodeKit);
|
||||
}
|
||||
|
||||
private static ContentNodeKit CreateContentNodeKit(ContentSourceDto dto)
|
||||
private ContentNodeKit CreateContentNodeKit(ContentSourceDto dto)
|
||||
{
|
||||
ContentData d = null;
|
||||
ContentData p = null;
|
||||
@@ -192,7 +198,7 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
|
||||
{
|
||||
if (Debugger.IsAttached)
|
||||
throw new Exception("Missing cmsContentNu edited content for node " + dto.Id + ", consider rebuilding.");
|
||||
Current.Logger.Warn<DatabaseDataSource>("Missing cmsContentNu edited content for node {NodeId}, consider rebuilding.", dto.Id);
|
||||
_logger.Warn<DatabaseDataSource>("Missing cmsContentNu edited content for node {NodeId}, consider rebuilding.", dto.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -219,7 +225,7 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
|
||||
{
|
||||
if (Debugger.IsAttached)
|
||||
throw new Exception("Missing cmsContentNu published content for node " + dto.Id + ", consider rebuilding.");
|
||||
Current.Logger.Warn<DatabaseDataSource>("Missing cmsContentNu published content for node {NodeId}, consider rebuilding.", dto.Id);
|
||||
_logger.Warn<DatabaseDataSource>("Missing cmsContentNu published content for node {NodeId}, consider rebuilding.", dto.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
+1
-1
@@ -3,7 +3,7 @@ using Newtonsoft.Json;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache.NuCache.DataSource
|
||||
{
|
||||
internal class PropertyData
|
||||
public class PropertyData
|
||||
{
|
||||
private string _culture;
|
||||
private string _segment;
|
||||
+1
-1
@@ -11,7 +11,7 @@ using Umbraco.Web.PublishedCache.NuCache.Navigable;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache.NuCache
|
||||
{
|
||||
internal class MediaCache : PublishedCacheBase, IPublishedMediaCache, INavigableData, IDisposable
|
||||
public class MediaCache : PublishedCacheBase, IPublishedMediaCache, INavigableData, IDisposable
|
||||
{
|
||||
private readonly ContentStore.Snapshot _snapshot;
|
||||
private readonly IVariationContextAccessor _variationContextAccessor;
|
||||
-2
@@ -6,11 +6,9 @@ using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Xml.XPath;
|
||||
using Umbraco.Web.PublishedCache.NuCache.Navigable;
|
||||
using Umbraco.Web.Security;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache.NuCache
|
||||
{
|
||||
+3
-2
@@ -3,11 +3,12 @@ using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Scoping;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Infrastructure.PublishedCache;
|
||||
using Umbraco.Web.PublishedCache.NuCache.DataSource;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache.NuCache
|
||||
{
|
||||
public class NuCacheComposer : ComponentComposer<NuCacheComponent>, ICoreComposer
|
||||
public class NuCacheComposer : ComponentComposer<NuCacheComponent>, IPublishedCacheComposer
|
||||
{
|
||||
public override void Compose(Composition composition)
|
||||
{
|
||||
@@ -31,7 +32,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
{
|
||||
idkSvc.SetMapper(UmbracoObjectTypes.Document, id => publishedSnapshotService.GetDocumentUid(id), uid => publishedSnapshotService.GetDocumentId(uid));
|
||||
idkSvc.SetMapper(UmbracoObjectTypes.Media, id => publishedSnapshotService.GetMediaUid(id), uid => publishedSnapshotService.GetMediaId(uid));
|
||||
}
|
||||
}
|
||||
return idkSvc;
|
||||
});
|
||||
|
||||
+1
-30
@@ -4,9 +4,8 @@ using System.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Web.Composing;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models;
|
||||
using Umbraco.Web.PublishedCache.NuCache.DataSource;
|
||||
|
||||
@@ -48,28 +47,6 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
PropertiesArray = properties.ToArray();
|
||||
}
|
||||
|
||||
private string GetProfileNameById(int id)
|
||||
{
|
||||
var cache = GetCurrentSnapshotCache();
|
||||
return cache == null
|
||||
? GetProfileNameByIdNoCache(id)
|
||||
: (string)cache.Get(CacheKeys.ProfileName(id), () => GetProfileNameByIdNoCache(id));
|
||||
}
|
||||
|
||||
private static string GetProfileNameByIdNoCache(int id)
|
||||
{
|
||||
#if DEBUG
|
||||
var userService = Current.Services?.UserService;
|
||||
if (userService == null) return "[null]"; // for tests
|
||||
#else
|
||||
// we don't want each published content to hold a reference to the service
|
||||
// so where should they get the service from really? from the locator...
|
||||
var userService = Current.Services.UserService;
|
||||
#endif
|
||||
var user = userService.GetProfileById(id);
|
||||
return user?.Name;
|
||||
}
|
||||
|
||||
// used when cloning in ContentNode
|
||||
public PublishedContent(
|
||||
ContentNode contentNode,
|
||||
@@ -170,18 +147,12 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
/// <inheritdoc />
|
||||
public override int CreatorId => _contentNode.CreatorId;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string CreatorName => GetProfileNameById(_contentNode.CreatorId);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DateTime CreateDate => _contentNode.CreateDate;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int WriterId => ContentData.WriterId;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string WriterName => GetProfileNameById(ContentData.WriterId);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DateTime UpdateDate => ContentData.VersionDate;
|
||||
|
||||
Executable → Regular
+4
-6
@@ -26,11 +26,9 @@ using Umbraco.Core.Services.Changes;
|
||||
using Umbraco.Core.Services.Implement;
|
||||
using Umbraco.Core.Strings;
|
||||
using Umbraco.Web.Cache;
|
||||
using Umbraco.Web.Install;
|
||||
using Umbraco.Web.PublishedCache.NuCache.DataSource;
|
||||
using Umbraco.Web.Routing;
|
||||
using File = System.IO.File;
|
||||
using Current = Umbraco.Web.Composing.Current;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache.NuCache
|
||||
{
|
||||
@@ -172,8 +170,8 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
internal int GetMediaId(Guid udi) => GetId(_mediaStore, udi);
|
||||
internal Guid GetDocumentUid(int id) => GetUid(_contentStore, id);
|
||||
internal Guid GetMediaUid(int id) => GetUid(_mediaStore, id);
|
||||
private int GetId(ContentStore store, Guid uid) => store.LiveSnapshot.Get(uid)?.Id ?? default;
|
||||
private Guid GetUid(ContentStore store, int id) => store.LiveSnapshot.Get(id)?.Uid ?? default;
|
||||
private int GetId(ContentStore store, Guid uid) => store.LiveSnapshot.Get(uid)?.Id ?? 0;
|
||||
private Guid GetUid(ContentStore store, int id) => store.LiveSnapshot.Get(id)?.Uid ?? Guid.Empty;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1767,7 +1765,7 @@ AND cmsContentNu.nodeId IS NULL
|
||||
|
||||
#region Instrument
|
||||
|
||||
public string GetStatus()
|
||||
public override string GetStatus()
|
||||
{
|
||||
var dbCacheIsOk = VerifyContentDbCache()
|
||||
&& VerifyMediaDbCache()
|
||||
@@ -1790,7 +1788,7 @@ AND cmsContentNu.nodeId IS NULL
|
||||
" and " + ms + " snapshot" + (ms > 1 ? "s" : "") + ".";
|
||||
}
|
||||
|
||||
public void Collect()
|
||||
public override void Collect()
|
||||
{
|
||||
var contentCollect = _contentStore.CollectAsync();
|
||||
var mediaCollect = _mediaStore.CollectAsync();
|
||||
@@ -0,0 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<RootNamespace>Umbraco.Infrastructure.PublishedCache</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CSharpTest.Net.Collections-NetStd2" Version="14.906.1403.1084" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Umbraco.Abstractions\Umbraco.Abstractions.csproj" />
|
||||
<ProjectReference Include="..\Umbraco.Infrastructure\Umbraco.Infrastructure.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
|
||||
<_Parameter1>Umbraco.Tests</_Parameter1>
|
||||
</AssemblyAttribute>
|
||||
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
|
||||
<_Parameter1>Umbraco.Tests.Benchmarks</_Parameter1>
|
||||
</AssemblyAttribute>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -25,6 +25,7 @@ namespace Umbraco.Tests.Cache.PublishedCache
|
||||
public class PublishMediaCacheTests : BaseWebTest
|
||||
{
|
||||
private Dictionary<string, PublishedContentType> _mediaTypes;
|
||||
private int _testWriterAndCreatorId;
|
||||
|
||||
private IUmbracoContextAccessor _umbracoContextAccessor;
|
||||
protected override void Compose()
|
||||
@@ -51,6 +52,8 @@ namespace Umbraco.Tests.Cache.PublishedCache
|
||||
{ testMediaType.Alias, testMediaType }
|
||||
};
|
||||
ContentTypesCache.GetPublishedContentTypeByAlias = alias => _mediaTypes[alias];
|
||||
|
||||
_testWriterAndCreatorId = ServiceContext.UserService.CreateUserWithIdentity("Shannon", "test").Id;
|
||||
}
|
||||
|
||||
private IMediaType MakeNewMediaType(IUser user, string text, int parentId = -1)
|
||||
@@ -201,7 +204,7 @@ namespace Umbraco.Tests.Cache.PublishedCache
|
||||
{"path", "-1,1234"},
|
||||
{"updateDate", DateTime.Parse("2012-07-16T10:34:09").Ticks.ToString()},
|
||||
{"createDate", DateTime.Parse("2012-07-17T10:34:09").Ticks.ToString()},
|
||||
{"creatorID", "0"},
|
||||
{"creatorID", _testWriterAndCreatorId.ToString()},
|
||||
{"creatorName", "Shannon"}
|
||||
};
|
||||
|
||||
@@ -210,7 +213,7 @@ namespace Umbraco.Tests.Cache.PublishedCache
|
||||
var store = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null, HostingEnvironment), ServiceContext.MediaService, ServiceContext.UserService, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance<IEntityXmlSerializer>(), Factory.GetInstance<IUmbracoContextAccessor>(), VariationContextAccessor);
|
||||
var doc = store.CreateFromCacheValues(store.ConvertFromSearchResult(result));
|
||||
|
||||
DoAssert(doc, 1234, key, null, 0, "/media/test.jpg", "Image", 23, "Shannon", "Shannon", 0, 0, "-1,1234", DateTime.Parse("2012-07-17T10:34:09"), DateTime.Parse("2012-07-16T10:34:09"), 2);
|
||||
DoAssert(doc, 1234, key, null, 0, "/media/test.jpg", "Image", 23, "Shannon", "Shannon", "-1,1234", DateTime.Parse("2012-07-17T10:34:09"), DateTime.Parse("2012-07-16T10:34:09"), 2);
|
||||
Assert.AreEqual(null, doc.Parent);
|
||||
}
|
||||
|
||||
@@ -226,7 +229,7 @@ namespace Umbraco.Tests.Cache.PublishedCache
|
||||
var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null, null, null, null, HostingEnvironment), ServiceContext.MediaService, ServiceContext.UserService, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance<IEntityXmlSerializer>(), Factory.GetInstance<IUmbracoContextAccessor>(),VariationContextAccessor);
|
||||
var doc = cache.CreateFromCacheValues(cache.ConvertFromXPathNavigator(navigator, true));
|
||||
|
||||
DoAssert(doc, 2000, key, null, 2, "image1", "Image", 23, "Shannon", "Shannon", 33, 33, "-1,2000", DateTime.Parse("2012-06-12T14:13:17"), DateTime.Parse("2012-07-20T18:50:43"), 1);
|
||||
DoAssert(doc, 2000, key, null, 2, "image1", "Image", 23, "Shannon", "Shannon", "-1,2000", DateTime.Parse("2012-06-12T14:13:17"), DateTime.Parse("2012-07-20T18:50:43"), 1);
|
||||
Assert.AreEqual(null, doc.Parent);
|
||||
Assert.AreEqual(2, doc.Children.Count());
|
||||
Assert.AreEqual(2001, doc.Children.ElementAt(0).Id);
|
||||
@@ -243,16 +246,18 @@ namespace Umbraco.Tests.Cache.PublishedCache
|
||||
<!ATTLIST CustomDocument id ID #REQUIRED>
|
||||
]>
|
||||
<root id=""-1"">
|
||||
<Image id=""2000"" parentID=""-1"" level=""1"" writerID=""33"" creatorID=""33"" nodeType=""2044"" template=""0"" sortOrder=""2"" createDate=""2012-06-12T14:13:17"" updateDate=""2012-07-20T18:50:43"" nodeName=""Image1"" urlName=""image1"" writerName=""Shannon"" creatorName=""Shannon"" path=""-1,2000"" isDoc="""">
|
||||
<Image id=""2000"" parentID=""-1"" level=""1"" writerID=""[WriterId]"" creatorID=""[CreatorId]"" nodeType=""2044"" template=""0"" sortOrder=""2"" createDate=""2012-06-12T14:13:17"" updateDate=""2012-07-20T18:50:43"" nodeName=""Image1"" urlName=""image1"" path=""-1,2000"" isDoc="""">
|
||||
<file><![CDATA[/media/1234/image1.png]]></file>
|
||||
<Image id=""2001"" parentID=""2000"" level=""2"" writerID=""33"" creatorID=""33"" nodeType=""2044"" template=""0"" sortOrder=""2"" createDate=""2012-06-12T14:13:17"" updateDate=""2012-07-20T18:50:43"" nodeName=""Image1"" urlName=""image1"" writerName=""Shannon"" creatorName=""Shannon"" path=""-1,2000,2001"" isDoc="""">
|
||||
<Image id=""2001"" parentID=""2000"" level=""2"" writerID=""[WriterId]"" creatorID=""[CreatorId]"" nodeType=""2044"" template=""0"" sortOrder=""2"" createDate=""2012-06-12T14:13:17"" updateDate=""2012-07-20T18:50:43"" nodeName=""Image1"" urlName=""image1"" path=""-1,2000,2001"" isDoc="""">
|
||||
<file><![CDATA[/media/1234/image1.png]]></file>
|
||||
</Image>
|
||||
<Image id=""2002"" parentID=""2000"" level=""2"" writerID=""33"" creatorID=""33"" nodeType=""2044"" template=""0"" sortOrder=""2"" createDate=""2012-06-12T14:13:17"" updateDate=""2012-07-20T18:50:43"" nodeName=""Image1"" urlName=""image1"" writerName=""Shannon"" creatorName=""Shannon"" path=""-1,2000,2002"" isDoc="""">
|
||||
<Image id=""2002"" parentID=""2000"" level=""2"" writerID=""[WriterId]"" creatorID=""[CreatorId]"" nodeType=""2044"" template=""0"" sortOrder=""2"" createDate=""2012-06-12T14:13:17"" updateDate=""2012-07-20T18:50:43"" nodeName=""Image1"" urlName=""image1"" path=""-1,2000,2002"" isDoc="""">
|
||||
<file><![CDATA[/media/1234/image1.png]]></file>
|
||||
</Image>
|
||||
</Image>
|
||||
</root>";
|
||||
xml = xml.Replace("[WriterId]", _testWriterAndCreatorId.ToString());
|
||||
xml = xml.Replace("[CreatorId]", _testWriterAndCreatorId.ToString());
|
||||
|
||||
var xmlDoc = new XmlDocument();
|
||||
xmlDoc.LoadXml(xml);
|
||||
@@ -279,10 +284,8 @@ namespace Umbraco.Tests.Cache.PublishedCache
|
||||
{"urlName", "testing"},
|
||||
{nodeTypeAliasKey, "myType"},
|
||||
{"nodeType", "22"},
|
||||
{"writerName", "Shannon"},
|
||||
{"creatorName", "Shannon"},
|
||||
{"writerID", "33"},
|
||||
{"creatorID", "33"},
|
||||
{"writerID", _testWriterAndCreatorId.ToString()},
|
||||
{"creatorID", _testWriterAndCreatorId.ToString()},
|
||||
{pathKey, "1,2,3,4,5"},
|
||||
{"createDate", "2012-01-02"},
|
||||
{"updateDate", "2012-01-02"},
|
||||
@@ -349,8 +352,6 @@ namespace Umbraco.Tests.Cache.PublishedCache
|
||||
int nodeTypeIdVal = 22,
|
||||
string writerNameVal = "Shannon",
|
||||
string creatorNameVal = "Shannon",
|
||||
int writerIdVal = 33,
|
||||
int creatorIdVal = 33,
|
||||
string pathVal = "1,2,3,4,5",
|
||||
DateTime? createDateVal = null,
|
||||
DateTime? updateDateVal = null,
|
||||
@@ -363,7 +364,7 @@ namespace Umbraco.Tests.Cache.PublishedCache
|
||||
updateDateVal = DateTime.Parse("2012-01-02");
|
||||
|
||||
DoAssert((IPublishedContent)dicDoc, idVal, keyVal, templateIdVal, sortOrderVal, urlNameVal, nodeTypeAliasVal, nodeTypeIdVal, writerNameVal,
|
||||
creatorNameVal, writerIdVal, creatorIdVal, pathVal, createDateVal, updateDateVal, levelVal);
|
||||
creatorNameVal, pathVal, createDateVal, updateDateVal, levelVal);
|
||||
|
||||
//now validate the parentId that has been parsed, this doesn't exist on the IPublishedContent
|
||||
Assert.AreEqual(parentIdVal, dicDoc.ParentId);
|
||||
@@ -380,8 +381,6 @@ namespace Umbraco.Tests.Cache.PublishedCache
|
||||
int nodeTypeIdVal = 22,
|
||||
string writerNameVal = "Shannon",
|
||||
string creatorNameVal = "Shannon",
|
||||
int writerIdVal = 33,
|
||||
int creatorIdVal = 33,
|
||||
string pathVal = "1,2,3,4,5",
|
||||
DateTime? createDateVal = null,
|
||||
DateTime? updateDateVal = null,
|
||||
@@ -399,10 +398,10 @@ namespace Umbraco.Tests.Cache.PublishedCache
|
||||
Assert.AreEqual(urlNameVal, doc.UrlSegment);
|
||||
Assert.AreEqual(nodeTypeAliasVal, doc.ContentType.Alias);
|
||||
Assert.AreEqual(nodeTypeIdVal, doc.ContentType.Id);
|
||||
Assert.AreEqual(writerNameVal, doc.WriterName);
|
||||
Assert.AreEqual(creatorNameVal, doc.CreatorName);
|
||||
Assert.AreEqual(writerIdVal, doc.WriterId);
|
||||
Assert.AreEqual(creatorIdVal, doc.CreatorId);
|
||||
Assert.AreEqual(writerNameVal, doc.GetWriterName(ServiceContext.UserService));
|
||||
Assert.AreEqual(creatorNameVal, doc.GetCreatorName(ServiceContext.UserService));
|
||||
Assert.AreEqual(_testWriterAndCreatorId, doc.WriterId);
|
||||
Assert.AreEqual(_testWriterAndCreatorId, doc.CreatorId);
|
||||
Assert.AreEqual(pathVal, doc.Path);
|
||||
Assert.AreEqual(createDateVal.Value, doc.CreateDate);
|
||||
Assert.AreEqual(updateDateVal.Value, doc.UpdateDate);
|
||||
|
||||
@@ -5,7 +5,6 @@ using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Scoping;
|
||||
using Umbraco.Web.PublishedCache.NuCache;
|
||||
using Umbraco.Web.PublishedCache.NuCache.Snap;
|
||||
|
||||
namespace Umbraco.Tests.Cache
|
||||
{
|
||||
@@ -223,7 +222,7 @@ namespace Umbraco.Tests.Cache
|
||||
{
|
||||
var d = new SnapDictionary<int, string>();
|
||||
d.Test.CollectAuto = false;
|
||||
|
||||
|
||||
// gen 1
|
||||
d.Set(1, "one");
|
||||
Assert.AreEqual(1, d.Test.GetValues(1).Length);
|
||||
@@ -321,7 +320,7 @@ namespace Umbraco.Tests.Cache
|
||||
{
|
||||
var d = new SnapDictionary<int, string>();
|
||||
d.Test.CollectAuto = false;
|
||||
|
||||
|
||||
Assert.AreEqual(0, d.Test.GetValues(1).Length);
|
||||
|
||||
// gen 1
|
||||
@@ -416,7 +415,7 @@ namespace Umbraco.Tests.Cache
|
||||
{
|
||||
var d = new SnapDictionary<int, string>();
|
||||
d.Test.CollectAuto = false;
|
||||
|
||||
|
||||
// gen 1
|
||||
d.Set(1, "one");
|
||||
Assert.AreEqual(1, d.Test.GetValues(1).Length);
|
||||
@@ -578,7 +577,7 @@ namespace Umbraco.Tests.Cache
|
||||
{
|
||||
var d = new SnapDictionary<int, string>();
|
||||
d.Test.CollectAuto = false;
|
||||
|
||||
|
||||
d.Set(1, "one");
|
||||
d.Set(2, "two");
|
||||
|
||||
@@ -875,7 +874,7 @@ namespace Umbraco.Tests.Cache
|
||||
{
|
||||
var d = new SnapDictionary<int, string>();
|
||||
d.Test.CollectAuto = false;
|
||||
|
||||
|
||||
|
||||
// gen 1
|
||||
d.Set(1, "one");
|
||||
@@ -960,7 +959,7 @@ namespace Umbraco.Tests.Cache
|
||||
var d = new SnapDictionary<int, string>();
|
||||
var t = d.Test;
|
||||
t.CollectAuto = false;
|
||||
|
||||
|
||||
// gen 1
|
||||
d.Set(1, "one");
|
||||
var s1 = d.CreateSnapshot();
|
||||
|
||||
@@ -61,8 +61,6 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
|
||||
ValidateAndSetProperty(valueDictionary, val => _urlName = val, "urlName");
|
||||
ValidateAndSetProperty(valueDictionary, val => _documentTypeAlias = val, "nodeTypeAlias", ExamineFieldNames.ItemTypeFieldName);
|
||||
ValidateAndSetProperty(valueDictionary, val => _documentTypeId = Int32.Parse(val), "nodeType");
|
||||
//ValidateAndSetProperty(valueDictionary, val => _writerName = val, "writerName");
|
||||
ValidateAndSetProperty(valueDictionary, val => _creatorName = val, "creatorName", "writerName"); //this is a bit of a hack fix for: U4-1132
|
||||
//ValidateAndSetProperty(valueDictionary, val => _writerId = int.Parse(val), "writerID");
|
||||
ValidateAndSetProperty(valueDictionary, val => _creatorId = Int32.Parse(val), "creatorID", "writerID"); //this is a bit of a hack fix for: U4-1132
|
||||
ValidateAndSetProperty(valueDictionary, val => _path = val, "path", "__Path");
|
||||
@@ -161,10 +159,6 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
|
||||
|
||||
public override string UrlSegment => _urlName;
|
||||
|
||||
public override string WriterName => _creatorName;
|
||||
|
||||
public override string CreatorName => _creatorName;
|
||||
|
||||
public override int WriterId => _creatorId;
|
||||
|
||||
public override int CreatorId => _creatorId;
|
||||
@@ -203,8 +197,6 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
|
||||
private string _urlName;
|
||||
private string _documentTypeAlias;
|
||||
private int _documentTypeId;
|
||||
//private string _writerName;
|
||||
private string _creatorName;
|
||||
//private int _writerId;
|
||||
private int _creatorId;
|
||||
private string _path;
|
||||
|
||||
@@ -61,8 +61,6 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
|
||||
private string _name;
|
||||
private string _docTypeAlias;
|
||||
private int _docTypeId;
|
||||
private string _writerName;
|
||||
private string _creatorName;
|
||||
private int _writerId;
|
||||
private int _creatorId;
|
||||
private string _urlName;
|
||||
@@ -158,24 +156,6 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
|
||||
|
||||
public override IReadOnlyDictionary<string, PublishedCultureInfo> Cultures => _cultures ?? (_cultures = GetCultures());
|
||||
|
||||
public override string WriterName
|
||||
{
|
||||
get
|
||||
{
|
||||
EnsureNodeInitialized();
|
||||
return _writerName;
|
||||
}
|
||||
}
|
||||
|
||||
public override string CreatorName
|
||||
{
|
||||
get
|
||||
{
|
||||
EnsureNodeInitialized();
|
||||
return _creatorName;
|
||||
}
|
||||
}
|
||||
|
||||
public override int WriterId
|
||||
{
|
||||
get
|
||||
@@ -301,8 +281,8 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
|
||||
private void InitializeNode()
|
||||
{
|
||||
InitializeNode(this, _xmlNode, _isPreviewing,
|
||||
out _id, out _key, out _template, out _sortOrder, out _name, out _writerName,
|
||||
out _urlName, out _creatorName, out _creatorId, out _writerId, out _docTypeAlias, out _docTypeId, out _path,
|
||||
out _id, out _key, out _template, out _sortOrder, out _name,
|
||||
out _urlName, out _creatorId, out _writerId, out _docTypeAlias, out _docTypeId, out _path,
|
||||
out _createDate, out _updateDate, out _level, out _isDraft, out _contentType, out _properties,
|
||||
_contentTypeCache.Get);
|
||||
|
||||
@@ -311,18 +291,17 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
|
||||
|
||||
// internal for some benchmarks
|
||||
internal static void InitializeNode(XmlPublishedContent node, XmlNode xmlNode, bool isPreviewing,
|
||||
out int id, out Guid key, out int template, out int sortOrder, out string name, out string writerName, out string urlName,
|
||||
out string creatorName, out int creatorId, out int writerId, out string docTypeAlias, out int docTypeId, out string path,
|
||||
out int id, out Guid key, out int template, out int sortOrder, out string name, out string urlName,
|
||||
out int creatorId, out int writerId, out string docTypeAlias, out int docTypeId, out string path,
|
||||
out DateTime createDate, out DateTime updateDate, out int level, out bool isDraft,
|
||||
out IPublishedContentType contentType, out Dictionary<string, IPublishedProperty> properties,
|
||||
Func<PublishedItemType, string, IPublishedContentType> getPublishedContentType)
|
||||
{
|
||||
//initialize the out params with defaults:
|
||||
writerName = null;
|
||||
docTypeAlias = null;
|
||||
id = template = sortOrder = template = creatorId = writerId = docTypeId = level = default(int);
|
||||
key = default(Guid);
|
||||
name = writerName = urlName = creatorName = docTypeAlias = path = null;
|
||||
name = docTypeAlias = urlName = path = null;
|
||||
createDate = updateDate = default(DateTime);
|
||||
isDraft = false;
|
||||
contentType = null;
|
||||
@@ -341,12 +320,8 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
|
||||
sortOrder = int.Parse(xmlNode.Attributes.GetNamedItem("sortOrder").Value);
|
||||
if (xmlNode.Attributes.GetNamedItem("nodeName") != null)
|
||||
name = xmlNode.Attributes.GetNamedItem("nodeName").Value;
|
||||
if (xmlNode.Attributes.GetNamedItem("writerName") != null)
|
||||
writerName = xmlNode.Attributes.GetNamedItem("writerName").Value;
|
||||
if (xmlNode.Attributes.GetNamedItem("urlName") != null)
|
||||
urlName = xmlNode.Attributes.GetNamedItem("urlName").Value;
|
||||
if (xmlNode.Attributes.GetNamedItem("creatorName") != null)
|
||||
creatorName = xmlNode.Attributes.GetNamedItem("creatorName").Value;
|
||||
|
||||
//Added the actual userID, as a user cannot be looked up via full name only...
|
||||
if (xmlNode.Attributes.GetNamedItem("creatorID") != null)
|
||||
|
||||
@@ -268,5 +268,10 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public override string GetStatus()
|
||||
{
|
||||
return "Test status";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,8 +52,8 @@ namespace Umbraco.Tests.PublishedContent
|
||||
{"NodeTypeAlias", "NodeTypeAlias"},
|
||||
{"CreateDate", "CreateDate"},
|
||||
{"UpdateDate", "UpdateDate"},
|
||||
{"CreatorName", "CreatorName"},
|
||||
{"WriterName", "WriterName"},
|
||||
{"CreatorId", "CreatorId"},
|
||||
{"WriterId", "WriterId"},
|
||||
{"Url", "Url"}
|
||||
};
|
||||
foreach (var f in userFields.Where(f => !allFields.ContainsKey(f.Key)))
|
||||
@@ -135,7 +135,6 @@ namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
CreateDate = DateTime.Now,
|
||||
CreatorId = 1,
|
||||
CreatorName = "Shannon",
|
||||
Id = 3,
|
||||
SortOrder = 4,
|
||||
TemplateId = 5,
|
||||
@@ -145,7 +144,6 @@ namespace Umbraco.Tests.PublishedContent
|
||||
Name = "Page" + Guid.NewGuid(),
|
||||
Version = Guid.NewGuid(),
|
||||
WriterId = 1,
|
||||
WriterName = "Shannon",
|
||||
Parent = null,
|
||||
Level = 1,
|
||||
Children = new List<IPublishedContent>()
|
||||
|
||||
@@ -128,7 +128,6 @@ namespace Umbraco.Tests.PublishedContent
|
||||
UrlSegment = "content-1",
|
||||
Path = "/1",
|
||||
Level = 1,
|
||||
Url = "/content-1",
|
||||
ParentId = -1,
|
||||
ChildIds = new[] { 2 },
|
||||
Properties = new Collection<IPublishedProperty>
|
||||
@@ -145,7 +144,6 @@ namespace Umbraco.Tests.PublishedContent
|
||||
UrlSegment = "content-2",
|
||||
Path = "/1/2",
|
||||
Level = 2,
|
||||
Url = "/content-1/content-2",
|
||||
ParentId = 1,
|
||||
ChildIds = new int[] { 3 },
|
||||
Properties = new Collection<IPublishedProperty>
|
||||
@@ -170,7 +168,6 @@ namespace Umbraco.Tests.PublishedContent
|
||||
UrlSegment = "content-3",
|
||||
Path = "/1/2/3",
|
||||
Level = 3,
|
||||
Url = "/content-1/content-2/content-3",
|
||||
ParentId = 2,
|
||||
ChildIds = new int[] { },
|
||||
Properties = new Collection<IPublishedProperty>
|
||||
|
||||
@@ -35,7 +35,6 @@ namespace Umbraco.Tests.PublishedContent
|
||||
UrlSegment = "content-1",
|
||||
Path = "/1",
|
||||
Level = 1,
|
||||
Url = "/content-1",
|
||||
ParentId = -1,
|
||||
ChildIds = new int[] { },
|
||||
Properties = new Collection<IPublishedProperty>
|
||||
@@ -59,7 +58,6 @@ namespace Umbraco.Tests.PublishedContent
|
||||
UrlSegment = "content-2",
|
||||
Path = "/2",
|
||||
Level = 1,
|
||||
Url = "/content-2",
|
||||
ParentId = -1,
|
||||
ChildIds = new int[] { },
|
||||
Properties = new Collection<IPublishedProperty>
|
||||
@@ -83,7 +81,6 @@ namespace Umbraco.Tests.PublishedContent
|
||||
UrlSegment = "content-2sub",
|
||||
Path = "/3",
|
||||
Level = 1,
|
||||
Url = "/content-2sub",
|
||||
ParentId = -1,
|
||||
ChildIds = new int[] { },
|
||||
Properties = new Collection<IPublishedProperty>
|
||||
|
||||
@@ -59,8 +59,6 @@ namespace Umbraco.Tests.PublishedContent
|
||||
var pc = new Mock<IPublishedContent>();
|
||||
pc.Setup(content => content.Id).Returns(1);
|
||||
pc.Setup(content => content.Name).Returns("test");
|
||||
pc.Setup(content => content.WriterName).Returns("admin");
|
||||
pc.Setup(content => content.CreatorName).Returns("admin");
|
||||
pc.Setup(content => content.CreateDate).Returns(DateTime.Now);
|
||||
pc.Setup(content => content.UpdateDate).Returns(DateTime.Now);
|
||||
pc.Setup(content => content.Path).Returns("-1,1");
|
||||
|
||||
@@ -167,7 +167,6 @@ namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
// initialize boring stuff
|
||||
TemplateId = 0;
|
||||
WriterName = CreatorName = string.Empty;
|
||||
WriterId = CreatorId = 0;
|
||||
CreateDate = UpdateDate = DateTime.Now;
|
||||
Version = Guid.Empty;
|
||||
@@ -193,8 +192,6 @@ namespace Umbraco.Tests.PublishedContent
|
||||
public string Name { get; set; }
|
||||
public IReadOnlyDictionary<string, PublishedCultureInfo> Cultures => _cultures ?? (_cultures = GetCultures());
|
||||
public string UrlSegment { get; set; }
|
||||
public string WriterName { get; set; }
|
||||
public string CreatorName { get; set; }
|
||||
public int WriterId { get; set; }
|
||||
public int CreatorId { get; set; }
|
||||
public string Path { get; set; }
|
||||
@@ -202,7 +199,6 @@ namespace Umbraco.Tests.PublishedContent
|
||||
public DateTime UpdateDate { get; set; }
|
||||
public Guid Version { get; set; }
|
||||
public int Level { get; set; }
|
||||
public string Url { get; set; }
|
||||
|
||||
public PublishedItemType ItemType => PublishedItemType.Content;
|
||||
public bool IsDraft(string culture = null) => false;
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace Umbraco.Tests.Scoping
|
||||
ScopeProvider,
|
||||
documentRepository, mediaRepository, memberRepository,
|
||||
DefaultCultureAccessor,
|
||||
new DatabaseDataSource(),
|
||||
new DatabaseDataSource(Mock.Of<ILogger>()),
|
||||
Factory.GetInstance<IGlobalSettings>(),
|
||||
Factory.GetInstance<IEntityXmlSerializer>(),
|
||||
new NoopPublishedModelFactory(),
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace Umbraco.Tests.Services
|
||||
ScopeProvider,
|
||||
documentRepository, mediaRepository, memberRepository,
|
||||
DefaultCultureAccessor,
|
||||
new DatabaseDataSource(),
|
||||
new DatabaseDataSource(Mock.Of<ILogger>()),
|
||||
Factory.GetInstance<IGlobalSettings>(),
|
||||
Factory.GetInstance<IEntityXmlSerializer>(),
|
||||
Mock.Of<IPublishedModelFactory>(),
|
||||
|
||||
@@ -101,7 +101,8 @@ namespace Umbraco.Tests.TestHelpers
|
||||
new TestVariationContextAccessor(),
|
||||
container?.TryGetInstance<ServiceContext>() ?? ServiceContext.CreatePartial(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()),
|
||||
container?.TryGetInstance<IUmbracoSettingsSection>() ?? Current.Factory.GetInstance<IUmbracoSettingsSection>());
|
||||
container?.TryGetInstance<IUmbracoSettingsSection>() ?? Current.Factory.GetInstance<IUmbracoSettingsSection>(),
|
||||
Mock.Of<IUserService>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -584,6 +584,10 @@
|
||||
<Project>{33085570-9bf2-4065-a9b0-a29d920d13ba}</Project>
|
||||
<Name>Umbraco.Persistance.SqlCe</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Umbraco.PublishedCache.NuCache\Umbraco.PublishedCache.NuCache.csproj">
|
||||
<Project>{f6de8da0-07cc-4ef2-8a59-2bc81dbb3830}</Project>
|
||||
<Name>Umbraco.PublishedCache.NuCache</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Umbraco.Web\Umbraco.Web.csproj">
|
||||
<Project>{651E1350-91B6-44B7-BD60-7207006D7003}</Project>
|
||||
<Name>Umbraco.Web</Name>
|
||||
|
||||
+6
-6
@@ -1,4 +1,4 @@
|
||||
function nuCacheController($scope, $http, umbRequestHelper, localizationService, overlayService) {
|
||||
function publishedSnapshotCacheController($scope, $http, umbRequestHelper, localizationService, overlayService) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
if (vm.working) return;
|
||||
vm.working = true;
|
||||
umbRequestHelper.resourcePromise(
|
||||
$http.get(umbRequestHelper.getApiUrl("nuCacheStatusBaseUrl", "Collect")),
|
||||
$http.get(umbRequestHelper.getApiUrl("publishedSnapshotCacheStatusBaseUrl", "Collect")),
|
||||
'Failed to verify the cache.')
|
||||
.then(function (result) {
|
||||
vm.working = false;
|
||||
@@ -47,7 +47,7 @@
|
||||
if (vm.working) return;
|
||||
vm.working = true;
|
||||
umbRequestHelper.resourcePromise(
|
||||
$http.get(umbRequestHelper.getApiUrl("nuCacheStatusBaseUrl", "GetStatus")),
|
||||
$http.get(umbRequestHelper.getApiUrl("publishedSnapshotCacheStatusBaseUrl", "GetStatus")),
|
||||
'Failed to verify the cache.')
|
||||
.then(function (result) {
|
||||
vm.working = false;
|
||||
@@ -83,7 +83,7 @@
|
||||
vm.working = true;
|
||||
|
||||
umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl("nuCacheStatusBaseUrl", "ReloadCache")),
|
||||
$http.post(umbRequestHelper.getApiUrl("publishedSnapshotCacheStatusBaseUrl", "ReloadCache")),
|
||||
'Failed to trigger a cache reload')
|
||||
.then(function (result) {
|
||||
vm.working = false;
|
||||
@@ -94,7 +94,7 @@
|
||||
vm.working = true;
|
||||
|
||||
umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl("nuCacheStatusBaseUrl", "RebuildDbCache")),
|
||||
$http.post(umbRequestHelper.getApiUrl("publishedSnapshotCacheStatusBaseUrl", "RebuildDbCache")),
|
||||
'Failed to rebuild the cache.')
|
||||
.then(function (result) {
|
||||
vm.working = false;
|
||||
@@ -109,4 +109,4 @@
|
||||
|
||||
init();
|
||||
}
|
||||
angular.module("umbraco").controller("Umbraco.Dashboard.NuCacheController", nuCacheController);
|
||||
angular.module("umbraco").controller("Umbraco.Dashboard.PublishedSnapshotCacheController", publishedSnapshotCacheController);
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
<div id="nuCache" style="position: relative;" ng-controller="Umbraco.Dashboard.NuCacheController as vm">
|
||||
<div id="nuCache" style="position: relative;" ng-controller="Umbraco.Dashboard.PublishedSnapshotCacheController as vm">
|
||||
|
||||
<div ng-show="vm.loading || vm.working" style="background: rgba(255, 255, 255, 0.60); position: absolute; left: 0; right: 0; top: 0; bottom: 0;">
|
||||
<umb-load-indicator></umb-load-indicator>
|
||||
@@ -7,8 +7,6 @@
|
||||
$http.get(umbRequestHelper.getApiUrl('publishedStatusBaseUrl', 'GetPublishedStatusUrl')),
|
||||
'Failed to get published status url')
|
||||
.then(function (result) {
|
||||
|
||||
//result = 'views/dashboard/developer/nucache.html'
|
||||
vm.includeUrl = result;
|
||||
});
|
||||
|
||||
|
||||
@@ -124,6 +124,10 @@
|
||||
<Project>{52ac0ba8-a60e-4e36-897b-e8b97a54ed1c}</Project>
|
||||
<Name>Umbraco.ModelsBuilder.Embedded</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Umbraco.PublishedCache.NuCache\Umbraco.PublishedCache.NuCache.csproj">
|
||||
<Project>{f6de8da0-07cc-4ef2-8a59-2bc81dbb3830}</Project>
|
||||
<Name>Umbraco.PublishedCache.NuCache</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Umbraco.Web\Umbraco.Web.csproj">
|
||||
<Project>{651e1350-91b6-44b7-bd60-7207006d7003}</Project>
|
||||
<Name>Umbraco.Web</Name>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@using Umbraco.Web
|
||||
@using Umbraco.Core
|
||||
@using Umbraco.Web
|
||||
@inherits Umbraco.Web.Macros.PartialViewMacroPage
|
||||
|
||||
@*
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
@using Umbraco.Core
|
||||
@using Umbraco.Web
|
||||
@inherits Umbraco.Web.Macros.PartialViewMacroPage
|
||||
|
||||
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
@using Umbraco.Web
|
||||
@inherits Umbraco.Web.Macros.PartialViewMacroPage
|
||||
|
||||
@*
|
||||
@@ -26,7 +27,7 @@
|
||||
@foreach (var item in selection)
|
||||
{
|
||||
<li>
|
||||
<img src="@item.Url" alt="@item.Name" />
|
||||
<img src="@item.Url()" alt="@item.Name" />
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
@using Umbraco.Core
|
||||
@using Umbraco.Web
|
||||
@inherits Umbraco.Web.Macros.PartialViewMacroPage
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
@using Umbraco.Core
|
||||
@using Umbraco.Core.Models.PublishedContent
|
||||
@using Umbraco.Web
|
||||
@inherits Umbraco.Web.Macros.PartialViewMacroPage
|
||||
|
||||
@@ -169,37 +169,6 @@ namespace Umbraco.Web
|
||||
composition.RegisterUnique(_ => finder);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the published snapshot service.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the published snapshot service.</typeparam>
|
||||
/// <param name="composition">The composition.</param>
|
||||
public static void SetPublishedSnapshotService<T>(this Composition composition)
|
||||
where T : IPublishedSnapshotService
|
||||
{
|
||||
composition.RegisterUnique<IPublishedSnapshotService, T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the published snapshot service.
|
||||
/// </summary>
|
||||
/// <param name="composition">The composition.</param>
|
||||
/// <param name="factory">A function creating a published snapshot service.</param>
|
||||
public static void SetPublishedSnapshotService(this Composition composition, Func<IFactory, IPublishedSnapshotService> factory)
|
||||
{
|
||||
composition.RegisterUnique(factory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the published snapshot service.
|
||||
/// </summary>
|
||||
/// <param name="composition">The composition.</param>
|
||||
/// <param name="service">A published snapshot service.</param>
|
||||
public static void SetPublishedSnapshotService(this Composition composition, IPublishedSnapshotService service)
|
||||
{
|
||||
composition.RegisterUnique(_ => service);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the site domain helper.
|
||||
/// </summary>
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace Umbraco.Web.Controllers
|
||||
// if it's not a local url we'll redirect to the root of the current site
|
||||
return Redirect(Url.IsLocalUrl(model.RedirectUrl)
|
||||
? model.RedirectUrl
|
||||
: CurrentPage.AncestorOrSelf(1).Url);
|
||||
: CurrentPage.AncestorOrSelf(1).Url());
|
||||
}
|
||||
|
||||
//redirect to current page by default
|
||||
|
||||
@@ -286,7 +286,7 @@ namespace Umbraco.Web.Editors
|
||||
controller => controller.DeleteById(int.MaxValue))
|
||||
},
|
||||
{
|
||||
"nuCacheStatusBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<NuCacheStatusController>(
|
||||
"publishedSnapshotCacheStatusBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<PublishedSnapshotCacheStatusController>(
|
||||
controller => controller.GetStatus())
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
using System;
|
||||
using System.Web.Http;
|
||||
using Umbraco.Web.Cache;
|
||||
using Umbraco.Web.Composing;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
using Umbraco.Web.PublishedCache.NuCache;
|
||||
using Umbraco.Web.WebApi;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
public class NuCacheStatusController : UmbracoAuthorizedApiController
|
||||
{
|
||||
private readonly IPublishedSnapshotService _publishedSnapshotService;
|
||||
|
||||
public NuCacheStatusController(IPublishedSnapshotService publishedSnapshotService)
|
||||
{
|
||||
_publishedSnapshotService = publishedSnapshotService ?? throw new ArgumentNullException(nameof(publishedSnapshotService));
|
||||
}
|
||||
|
||||
private PublishedSnapshotService PublishedSnapshotService
|
||||
{
|
||||
get
|
||||
{
|
||||
var svc = _publishedSnapshotService as PublishedSnapshotService;
|
||||
if (svc == null)
|
||||
throw new NotSupportedException("Not running NuCache.");
|
||||
return svc;
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public string RebuildDbCache()
|
||||
{
|
||||
var service = PublishedSnapshotService;
|
||||
service.RebuildContentDbCache();
|
||||
service.RebuildMediaDbCache();
|
||||
service.RebuildMemberDbCache();
|
||||
return service.GetStatus();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public string GetStatus()
|
||||
{
|
||||
var service = PublishedSnapshotService;
|
||||
return service.GetStatus();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public string Collect()
|
||||
{
|
||||
var service = PublishedSnapshotService;
|
||||
GC.Collect();
|
||||
service.Collect();
|
||||
return service.GetStatus();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public void ReloadCache()
|
||||
{
|
||||
Current.DistributedCache.RefreshAllPublishedSnapshot();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Web.Http;
|
||||
using Umbraco.Web.Cache;
|
||||
using Umbraco.Web.Composing;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
using Umbraco.Web.WebApi;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
public class PublishedSnapshotCacheStatusController : UmbracoAuthorizedApiController
|
||||
{
|
||||
private readonly IPublishedSnapshotService _publishedSnapshotService;
|
||||
|
||||
public PublishedSnapshotCacheStatusController(IPublishedSnapshotService publishedSnapshotService)
|
||||
{
|
||||
_publishedSnapshotService = publishedSnapshotService ?? throw new ArgumentNullException(nameof(publishedSnapshotService));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public string RebuildDbCache()
|
||||
{
|
||||
_publishedSnapshotService.Rebuild();
|
||||
return _publishedSnapshotService.GetStatus();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public string GetStatus()
|
||||
{
|
||||
return _publishedSnapshotService.GetStatus();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public string Collect()
|
||||
{
|
||||
GC.Collect();
|
||||
_publishedSnapshotService.Collect();
|
||||
return _publishedSnapshotService.GetStatus();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public void ReloadCache()
|
||||
{
|
||||
Current.DistributedCache.RefreshAllPublishedSnapshot();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,11 +17,10 @@ namespace Umbraco.Web.Editors
|
||||
[HttpGet]
|
||||
public string GetPublishedStatusUrl()
|
||||
{
|
||||
//if (service is PublishedCache.PublishedNoCache.PublishedSnapshotService)
|
||||
// return "views/dashboard/developer/nocache.html";
|
||||
|
||||
if (_publishedSnapshotService is PublishedCache.NuCache.PublishedSnapshotService)
|
||||
return "views/dashboard/settings/nucache.html";
|
||||
if (!string.IsNullOrWhiteSpace(_publishedSnapshotService.StatusUrl))
|
||||
{
|
||||
return _publishedSnapshotService.StatusUrl;
|
||||
}
|
||||
|
||||
throw new NotSupportedException("Not supported: " + _publishedSnapshotService.GetType().FullName);
|
||||
}
|
||||
|
||||
@@ -26,8 +26,9 @@ namespace Umbraco.Web.Macros
|
||||
private readonly ILocalizedTextService _textService;
|
||||
private readonly AppCaches _appCaches;
|
||||
private readonly IMacroService _macroService;
|
||||
private readonly IUserService _userService;
|
||||
|
||||
public MacroRenderer(IProfilingLogger plogger, IUmbracoContextAccessor umbracoContextAccessor, IContentSection contentSection, ILocalizedTextService textService, AppCaches appCaches, IMacroService macroService)
|
||||
public MacroRenderer(IProfilingLogger plogger, IUmbracoContextAccessor umbracoContextAccessor, IContentSection contentSection, ILocalizedTextService textService, AppCaches appCaches, IMacroService macroService, IUserService userService)
|
||||
{
|
||||
_plogger = plogger ?? throw new ArgumentNullException(nameof(plogger));
|
||||
_umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor));
|
||||
@@ -35,6 +36,7 @@ namespace Umbraco.Web.Macros
|
||||
_textService = textService;
|
||||
_appCaches = appCaches ?? throw new ArgumentNullException(nameof(appCaches));
|
||||
_macroService = macroService ?? throw new ArgumentNullException(nameof(macroService));
|
||||
_userService = userService ?? throw new ArgumentNullException(nameof(userService));
|
||||
}
|
||||
|
||||
#region MacroContent cache
|
||||
@@ -201,7 +203,7 @@ namespace Umbraco.Web.Macros
|
||||
if (m == null)
|
||||
throw new InvalidOperationException("No macro found by alias " + macroAlias);
|
||||
|
||||
var page = new PublishedContentHashtableConverter(content);
|
||||
var page = new PublishedContentHashtableConverter(content, _userService);
|
||||
|
||||
var macro = new MacroModel(m);
|
||||
|
||||
|
||||
@@ -25,19 +25,20 @@ namespace Umbraco.Web.Macros
|
||||
/// Initializes a new instance of the <see cref="PublishedContentHashtableConverter"/> class for a published document request.
|
||||
/// </summary>
|
||||
/// <param name="frequest">The <see cref="PublishedRequest"/> pointing to the document.</param>
|
||||
/// <param name="userService">The <see cref="IUserService"/>.</param>
|
||||
/// <remarks>
|
||||
/// The difference between creating the page with PublishedRequest vs an IPublishedContent item is
|
||||
/// that the PublishedRequest takes into account how a template is assigned during the routing process whereas
|
||||
/// with an IPublishedContent item, the template id is assigned purely based on the default.
|
||||
/// </remarks>
|
||||
internal PublishedContentHashtableConverter(PublishedRequest frequest)
|
||||
internal PublishedContentHashtableConverter(PublishedRequest frequest, IUserService userService)
|
||||
{
|
||||
if (!frequest.HasPublishedContent)
|
||||
throw new ArgumentException("Document request has no node.", nameof(frequest));
|
||||
|
||||
PopulatePageData(frequest.PublishedContent.Id,
|
||||
frequest.PublishedContent.Name, frequest.PublishedContent.ContentType.Id, frequest.PublishedContent.ContentType.Alias,
|
||||
frequest.PublishedContent.WriterName, frequest.PublishedContent.CreatorName, frequest.PublishedContent.CreateDate, frequest.PublishedContent.UpdateDate,
|
||||
frequest.PublishedContent.GetWriterName(userService), frequest.PublishedContent.GetCreatorName(userService), frequest.PublishedContent.CreateDate, frequest.PublishedContent.UpdateDate,
|
||||
frequest.PublishedContent.Path, frequest.PublishedContent.Parent?.Id ?? -1);
|
||||
|
||||
if (frequest.HasTemplate)
|
||||
@@ -53,13 +54,13 @@ namespace Umbraco.Web.Macros
|
||||
/// Initializes a new instance of the page for a published document
|
||||
/// </summary>
|
||||
/// <param name="doc"></param>
|
||||
internal PublishedContentHashtableConverter(IPublishedContent doc)
|
||||
internal PublishedContentHashtableConverter(IPublishedContent doc, IUserService userService)
|
||||
{
|
||||
if (doc == null) throw new ArgumentNullException(nameof(doc));
|
||||
|
||||
PopulatePageData(doc.Id,
|
||||
doc.Name, doc.ContentType.Id, doc.ContentType.Alias,
|
||||
doc.WriterName, doc.CreatorName, doc.CreateDate, doc.UpdateDate,
|
||||
doc.GetWriterName(userService), doc.GetCreatorName(userService), doc.CreateDate, doc.UpdateDate,
|
||||
doc.Path, doc.Parent?.Id ?? -1);
|
||||
|
||||
if (doc.TemplateId.HasValue)
|
||||
@@ -78,7 +79,7 @@ namespace Umbraco.Web.Macros
|
||||
/// <param name="variationContextAccessor"></param>
|
||||
/// <remarks>This is for <see cref="MacroRenderingController"/> usage only.</remarks>
|
||||
internal PublishedContentHashtableConverter(IContent content, IVariationContextAccessor variationContextAccessor, IUserService userService, IShortStringHelper shortStringHelper, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, IPublishedContentTypeFactory publishedContentTypeFactory, UrlSegmentProviderCollection urlSegmentProviders)
|
||||
: this(new PagePublishedContent(content, variationContextAccessor, userService, shortStringHelper, contentTypeBaseServiceProvider, publishedContentTypeFactory, urlSegmentProviders))
|
||||
: this(new PagePublishedContent(content, variationContextAccessor, userService, shortStringHelper, contentTypeBaseServiceProvider, publishedContentTypeFactory, urlSegmentProviders), userService)
|
||||
{ }
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
if (mediaTyped == null)
|
||||
throw new PanicException($"Could not find media by id {udi.Guid} or there was no UmbracoContext available.");
|
||||
|
||||
var location = mediaTyped.Url;
|
||||
var location = mediaTyped.Url();
|
||||
|
||||
// Find the width & height attributes as we need to set the imageprocessor QueryString
|
||||
var width = img.GetAttributeValue("width", int.MinValue);
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace Umbraco.Web
|
||||
private static ISiteDomainHelper SiteDomainHelper => Current.Factory.GetInstance<ISiteDomainHelper>();
|
||||
private static IVariationContextAccessor VariationContextAccessor => Current.VariationContextAccessor;
|
||||
private static IExamineManager ExamineManager => Current.Factory.GetInstance<IExamineManager>();
|
||||
private static IUserService UserService => Current.Services.UserService;
|
||||
|
||||
#region IsComposedOf
|
||||
|
||||
@@ -366,305 +367,6 @@ namespace Umbraco.Web
|
||||
|
||||
#endregion
|
||||
|
||||
#region Axes: ancestors, ancestors-or-self
|
||||
|
||||
// as per XPath 1.0 specs �2.2,
|
||||
// - the ancestor axis contains the ancestors of the context node; the ancestors of the context node consist
|
||||
// of the parent of context node and the parent's parent and so on; thus, the ancestor axis will always
|
||||
// include the root node, unless the context node is the root node.
|
||||
// - the ancestor-or-self axis contains the context node and the ancestors of the context node; thus,
|
||||
// the ancestor axis will always include the root node.
|
||||
//
|
||||
// as per XPath 2.0 specs �3.2.1.1,
|
||||
// - the ancestor axis is defined as the transitive closure of the parent axis; it contains the ancestors
|
||||
// of the context node (the parent, the parent of the parent, and so on) - The ancestor axis includes the
|
||||
// root node of the tree in which the context node is found, unless the context node is the root node.
|
||||
// - the ancestor-or-self axis contains the context node and the ancestors of the context node; thus,
|
||||
// the ancestor-or-self axis will always include the root node.
|
||||
//
|
||||
// the ancestor and ancestor-or-self axis are reverse axes ie they contain the context node or nodes that
|
||||
// are before the context node in document order.
|
||||
//
|
||||
// document order is defined by �2.4.1 as:
|
||||
// - the root node is the first node.
|
||||
// - every node occurs before all of its children and descendants.
|
||||
// - the relative order of siblings is the order in which they occur in the children property of their parent node.
|
||||
// - children and descendants occur before following siblings.
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ancestors of the content.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The ancestors of the content, in down-top order.</returns>
|
||||
/// <remarks>Does not consider the content itself.</remarks>
|
||||
public static IEnumerable<IPublishedContent> Ancestors(this IPublishedContent content)
|
||||
{
|
||||
return content.AncestorsOrSelf(false, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ancestors of the content, at a level lesser or equal to a specified level.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="maxLevel">The level.</param>
|
||||
/// <returns>The ancestors of the content, at a level lesser or equal to the specified level, in down-top order.</returns>
|
||||
/// <remarks>Does not consider the content itself. Only content that are "high enough" in the tree are returned.</remarks>
|
||||
public static IEnumerable<IPublishedContent> Ancestors(this IPublishedContent content, int maxLevel)
|
||||
{
|
||||
return content.AncestorsOrSelf(false, n => n.Level <= maxLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ancestors of the content, of a specified content type.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="contentTypeAlias">The content type.</param>
|
||||
/// <returns>The ancestors of the content, of the specified content type, in down-top order.</returns>
|
||||
/// <remarks>Does not consider the content itself. Returns all ancestors, of the specified content type.</remarks>
|
||||
public static IEnumerable<IPublishedContent> Ancestors(this IPublishedContent content, string contentTypeAlias)
|
||||
{
|
||||
return content.AncestorsOrSelf(false, n => n.ContentType.Alias.InvariantEquals(contentTypeAlias));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ancestors of the content, of a specified content type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The ancestors of the content, of the specified content type, in down-top order.</returns>
|
||||
/// <remarks>Does not consider the content itself. Returns all ancestors, of the specified content type.</remarks>
|
||||
public static IEnumerable<T> Ancestors<T>(this IPublishedContent content)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Ancestors().OfType<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ancestors of the content, at a level lesser or equal to a specified level, and of a specified content type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="maxLevel">The level.</param>
|
||||
/// <returns>The ancestors of the content, at a level lesser or equal to the specified level, and of the specified
|
||||
/// content type, in down-top order.</returns>
|
||||
/// <remarks>Does not consider the content itself. Only content that are "high enough" in the trees, and of the
|
||||
/// specified content type, are returned.</remarks>
|
||||
public static IEnumerable<T> Ancestors<T>(this IPublishedContent content, int maxLevel)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Ancestors(maxLevel).OfType<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content and its ancestors.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The content and its ancestors, in down-top order.</returns>
|
||||
public static IEnumerable<IPublishedContent> AncestorsOrSelf(this IPublishedContent content)
|
||||
{
|
||||
return content.AncestorsOrSelf(true, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content and its ancestors, at a level lesser or equal to a specified level.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="maxLevel">The level.</param>
|
||||
/// <returns>The content and its ancestors, at a level lesser or equal to the specified level,
|
||||
/// in down-top order.</returns>
|
||||
/// <remarks>Only content that are "high enough" in the tree are returned. So it may or may not begin
|
||||
/// with the content itself, depending on its level.</remarks>
|
||||
public static IEnumerable<IPublishedContent> AncestorsOrSelf(this IPublishedContent content, int maxLevel)
|
||||
{
|
||||
return content.AncestorsOrSelf(true, n => n.Level <= maxLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content and its ancestors, of a specified content type.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="contentTypeAlias">The content type.</param>
|
||||
/// <returns>The content and its ancestors, of the specified content type, in down-top order.</returns>
|
||||
/// <remarks>May or may not begin with the content itself, depending on its content type.</remarks>
|
||||
public static IEnumerable<IPublishedContent> AncestorsOrSelf(this IPublishedContent content, string contentTypeAlias)
|
||||
{
|
||||
return content.AncestorsOrSelf(true, n => n.ContentType.Alias.InvariantEquals(contentTypeAlias));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content and its ancestors, of a specified content type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The content and its ancestors, of the specified content type, in down-top order.</returns>
|
||||
/// <remarks>May or may not begin with the content itself, depending on its content type.</remarks>
|
||||
public static IEnumerable<T> AncestorsOrSelf<T>(this IPublishedContent content)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.AncestorsOrSelf().OfType<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content and its ancestor, at a lever lesser or equal to a specified level, and of a specified content type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="maxLevel">The level.</param>
|
||||
/// <returns>The content and its ancestors, at a level lesser or equal to the specified level, and of the specified
|
||||
/// content type, in down-top order.</returns>
|
||||
/// <remarks>May or may not begin with the content itself, depending on its level and content type.</remarks>
|
||||
public static IEnumerable<T> AncestorsOrSelf<T>(this IPublishedContent content, int maxLevel)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.AncestorsOrSelf(maxLevel).OfType<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ancestor of the content, ie its parent.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The ancestor of the content.</returns>
|
||||
/// <remarks>This method is here for consistency purposes but does not make much sense.</remarks>
|
||||
public static IPublishedContent Ancestor(this IPublishedContent content)
|
||||
{
|
||||
return content.Parent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the nearest ancestor of the content, at a lever lesser or equal to a specified level.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="maxLevel">The level.</param>
|
||||
/// <returns>The nearest (in down-top order) ancestor of the content, at a level lesser or equal to the specified level.</returns>
|
||||
/// <remarks>Does not consider the content itself. May return <c>null</c>.</remarks>
|
||||
public static IPublishedContent Ancestor(this IPublishedContent content, int maxLevel)
|
||||
{
|
||||
return content.EnumerateAncestors(false).FirstOrDefault(x => x.Level <= maxLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the nearest ancestor of the content, of a specified content type.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="contentTypeAlias">The content type alias.</param>
|
||||
/// <returns>The nearest (in down-top order) ancestor of the content, of the specified content type.</returns>
|
||||
/// <remarks>Does not consider the content itself. May return <c>null</c>.</remarks>
|
||||
public static IPublishedContent Ancestor(this IPublishedContent content, string contentTypeAlias)
|
||||
{
|
||||
return content.EnumerateAncestors(false).FirstOrDefault(x => x.ContentType.Alias.InvariantEquals(contentTypeAlias));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the nearest ancestor of the content, of a specified content type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The nearest (in down-top order) ancestor of the content, of the specified content type.</returns>
|
||||
/// <remarks>Does not consider the content itself. May return <c>null</c>.</remarks>
|
||||
public static T Ancestor<T>(this IPublishedContent content)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Ancestors<T>().FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the nearest ancestor of the content, at the specified level and of the specified content type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="maxLevel">The level.</param>
|
||||
/// <returns>The ancestor of the content, at the specified level and of the specified content type.</returns>
|
||||
/// <remarks>Does not consider the content itself. If the ancestor at the specified level is
|
||||
/// not of the specified type, returns <c>null</c>.</remarks>
|
||||
public static T Ancestor<T>(this IPublishedContent content, int maxLevel)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Ancestors<T>(maxLevel).FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content or its nearest ancestor.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The content.</returns>
|
||||
/// <remarks>This method is here for consistency purposes but does not make much sense.</remarks>
|
||||
public static IPublishedContent AncestorOrSelf(this IPublishedContent content)
|
||||
{
|
||||
return content;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content or its nearest ancestor, at a lever lesser or equal to a specified level.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="maxLevel">The level.</param>
|
||||
/// <returns>The content or its nearest (in down-top order) ancestor, at a level lesser or equal to the specified level.</returns>
|
||||
/// <remarks>May or may not return the content itself depending on its level. May return <c>null</c>.</remarks>
|
||||
public static IPublishedContent AncestorOrSelf(this IPublishedContent content, int maxLevel)
|
||||
{
|
||||
return content.EnumerateAncestors(true).FirstOrDefault(x => x.Level <= maxLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content or its nearest ancestor, of a specified content type.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="contentTypeAlias">The content type.</param>
|
||||
/// <returns>The content or its nearest (in down-top order) ancestor, of the specified content type.</returns>
|
||||
/// <remarks>May or may not return the content itself depending on its content type. May return <c>null</c>.</remarks>
|
||||
public static IPublishedContent AncestorOrSelf(this IPublishedContent content, string contentTypeAlias)
|
||||
{
|
||||
return content.EnumerateAncestors(true).FirstOrDefault(x => x.ContentType.Alias.InvariantEquals(contentTypeAlias));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content or its nearest ancestor, of a specified content type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The content or its nearest (in down-top order) ancestor, of the specified content type.</returns>
|
||||
/// <remarks>May or may not return the content itself depending on its content type. May return <c>null</c>.</remarks>
|
||||
public static T AncestorOrSelf<T>(this IPublishedContent content)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.AncestorsOrSelf<T>().FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content or its nearest ancestor, at a lever lesser or equal to a specified level, and of a specified content type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="maxLevel">The level.</param>
|
||||
/// <returns></returns>
|
||||
public static T AncestorOrSelf<T>(this IPublishedContent content, int maxLevel)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.AncestorsOrSelf<T>(maxLevel).FirstOrDefault();
|
||||
}
|
||||
|
||||
public static IEnumerable<IPublishedContent> AncestorsOrSelf(this IPublishedContent content, bool orSelf, Func<IPublishedContent, bool> func)
|
||||
{
|
||||
var ancestorsOrSelf = content.EnumerateAncestors(orSelf);
|
||||
return func == null ? ancestorsOrSelf : ancestorsOrSelf.Where(func);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enumerates ancestors of the content, bottom-up.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="orSelf">Indicates whether the content should be included.</param>
|
||||
/// <returns>Enumerates bottom-up ie walking up the tree (parent, grand-parent, etc).</returns>
|
||||
internal static IEnumerable<IPublishedContent> EnumerateAncestors(this IPublishedContent content, bool orSelf)
|
||||
{
|
||||
if (content == null) throw new ArgumentNullException(nameof(content));
|
||||
if (orSelf) yield return content;
|
||||
while ((content = content.Parent) != null)
|
||||
yield return content;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Axes: descendants, descendants-or-self
|
||||
|
||||
/// <summary>
|
||||
@@ -679,7 +381,7 @@ namespace Umbraco.Web
|
||||
/// </remarks>
|
||||
public static IEnumerable<IPublishedContent> DescendantsOrSelfOfType(this IEnumerable<IPublishedContent> parentNodes, string docTypeAlias, string culture = null)
|
||||
{
|
||||
return parentNodes.SelectMany(x => x.DescendantsOrSelfOfType(docTypeAlias, culture));
|
||||
return parentNodes.DescendantsOrSelfOfType(VariationContextAccessor, docTypeAlias, culture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -694,176 +396,110 @@ namespace Umbraco.Web
|
||||
public static IEnumerable<T> DescendantsOrSelf<T>(this IEnumerable<IPublishedContent> parentNodes, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return parentNodes.SelectMany(x => x.DescendantsOrSelf<T>(culture));
|
||||
return parentNodes.DescendantsOrSelf<T>(VariationContextAccessor, culture);
|
||||
}
|
||||
|
||||
|
||||
// as per XPath 1.0 specs �2.2,
|
||||
// - the descendant axis contains the descendants of the context node; a descendant is a child or a child of a child and so on; thus
|
||||
// the descendant axis never contains attribute or namespace nodes.
|
||||
// - the descendant-or-self axis contains the context node and the descendants of the context node.
|
||||
//
|
||||
// as per XPath 2.0 specs �3.2.1.1,
|
||||
// - the descendant axis is defined as the transitive closure of the child axis; it contains the descendants of the context node (the
|
||||
// children, the children of the children, and so on).
|
||||
// - the descendant-or-self axis contains the context node and the descendants of the context node.
|
||||
//
|
||||
// the descendant and descendant-or-self axis are forward axes ie they contain the context node or nodes that are after the context
|
||||
// node in document order.
|
||||
//
|
||||
// document order is defined by �2.4.1 as:
|
||||
// - the root node is the first node.
|
||||
// - every node occurs before all of its children and descendants.
|
||||
// - the relative order of siblings is the order in which they occur in the children property of their parent node.
|
||||
// - children and descendants occur before following siblings.
|
||||
|
||||
|
||||
public static IEnumerable<IPublishedContent> Descendants(this IPublishedContent content, string culture = null)
|
||||
{
|
||||
return content.DescendantsOrSelf(false, null, culture);
|
||||
return content.Descendants(VariationContextAccessor, culture);
|
||||
}
|
||||
|
||||
public static IEnumerable<IPublishedContent> Descendants(this IPublishedContent content, int level, string culture = null)
|
||||
{
|
||||
return content.DescendantsOrSelf(false, p => p.Level >= level, culture);
|
||||
return content.Descendants(VariationContextAccessor, level, culture);
|
||||
}
|
||||
|
||||
public static IEnumerable<IPublishedContent> DescendantsOfType(this IPublishedContent content, string contentTypeAlias, string culture = null)
|
||||
{
|
||||
return content.DescendantsOrSelf(false, p => p.ContentType.Alias.InvariantEquals(contentTypeAlias), culture);
|
||||
return content.DescendantsOfType(VariationContextAccessor, contentTypeAlias, culture);
|
||||
}
|
||||
|
||||
public static IEnumerable<T> Descendants<T>(this IPublishedContent content, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Descendants(culture).OfType<T>();
|
||||
return content.Descendants<T>(VariationContextAccessor, culture);
|
||||
}
|
||||
|
||||
public static IEnumerable<T> Descendants<T>(this IPublishedContent content, int level, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Descendants(level, culture).OfType<T>();
|
||||
return content.Descendants<T>(VariationContextAccessor, level, culture);
|
||||
}
|
||||
|
||||
public static IEnumerable<IPublishedContent> DescendantsOrSelf(this IPublishedContent content, string culture = null)
|
||||
{
|
||||
return content.DescendantsOrSelf(true, null, culture);
|
||||
return content.DescendantsOrSelf(VariationContextAccessor, culture);
|
||||
}
|
||||
|
||||
public static IEnumerable<IPublishedContent> DescendantsOrSelf(this IPublishedContent content, int level, string culture = null)
|
||||
{
|
||||
return content.DescendantsOrSelf(true, p => p.Level >= level, culture);
|
||||
return content.DescendantsOrSelf(VariationContextAccessor, level, culture);
|
||||
}
|
||||
|
||||
public static IEnumerable<IPublishedContent> DescendantsOrSelfOfType(this IPublishedContent content, string contentTypeAlias, string culture = null)
|
||||
{
|
||||
return content.DescendantsOrSelf(true, p => p.ContentType.Alias.InvariantEquals(contentTypeAlias), culture);
|
||||
return content.DescendantsOrSelfOfType(VariationContextAccessor, contentTypeAlias, culture);
|
||||
}
|
||||
|
||||
public static IEnumerable<T> DescendantsOrSelf<T>(this IPublishedContent content, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.DescendantsOrSelf(culture).OfType<T>();
|
||||
return content.DescendantsOrSelf<T>(VariationContextAccessor, culture);
|
||||
}
|
||||
|
||||
public static IEnumerable<T> DescendantsOrSelf<T>(this IPublishedContent content, int level, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.DescendantsOrSelf(level, culture).OfType<T>();
|
||||
return content.DescendantsOrSelf<T>(VariationContextAccessor, level, culture);
|
||||
}
|
||||
|
||||
public static IPublishedContent Descendant(this IPublishedContent content, string culture = null)
|
||||
{
|
||||
return content.Children(VariationContextAccessor, culture).FirstOrDefault();
|
||||
return content.Descendant(VariationContextAccessor, culture);
|
||||
}
|
||||
|
||||
public static IPublishedContent Descendant(this IPublishedContent content, int level, string culture = null)
|
||||
{
|
||||
return content.EnumerateDescendants(false, culture).FirstOrDefault(x => x.Level == level);
|
||||
return content.Descendant(VariationContextAccessor, level, culture);
|
||||
}
|
||||
|
||||
public static IPublishedContent DescendantOfType(this IPublishedContent content, string contentTypeAlias, string culture = null)
|
||||
{
|
||||
return content.EnumerateDescendants(false, culture).FirstOrDefault(x => x.ContentType.Alias.InvariantEquals(contentTypeAlias));
|
||||
return content.DescendantOfType(VariationContextAccessor, contentTypeAlias, culture);
|
||||
}
|
||||
|
||||
public static T Descendant<T>(this IPublishedContent content, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.EnumerateDescendants(false, culture).FirstOrDefault(x => x is T) as T;
|
||||
return content.Descendant<T>(VariationContextAccessor, culture);
|
||||
}
|
||||
|
||||
public static T Descendant<T>(this IPublishedContent content, int level, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Descendant(level, culture) as T;
|
||||
}
|
||||
|
||||
public static IPublishedContent DescendantOrSelf(this IPublishedContent content, string culture = null)
|
||||
{
|
||||
return content;
|
||||
return content.Descendant<T>(VariationContextAccessor, level, culture);
|
||||
}
|
||||
|
||||
public static IPublishedContent DescendantOrSelf(this IPublishedContent content, int level, string culture = null)
|
||||
{
|
||||
return content.EnumerateDescendants(true, culture).FirstOrDefault(x => x.Level == level);
|
||||
return content.DescendantOrSelf(VariationContextAccessor, level, culture);
|
||||
}
|
||||
|
||||
public static IPublishedContent DescendantOrSelfOfType(this IPublishedContent content, string contentTypeAlias, string culture = null)
|
||||
{
|
||||
return content.EnumerateDescendants(true, culture).FirstOrDefault(x => x.ContentType.Alias.InvariantEquals(contentTypeAlias));
|
||||
return content.DescendantOrSelfOfType(VariationContextAccessor, contentTypeAlias, culture);
|
||||
}
|
||||
|
||||
public static T DescendantOrSelf<T>(this IPublishedContent content, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.EnumerateDescendants(true, culture).FirstOrDefault(x => x is T) as T;
|
||||
return content.DescendantOrSelf<T>(VariationContextAccessor, culture);
|
||||
}
|
||||
|
||||
public static T DescendantOrSelf<T>(this IPublishedContent content, int level, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.DescendantOrSelf(level, culture) as T;
|
||||
}
|
||||
|
||||
internal static IEnumerable<IPublishedContent> DescendantsOrSelf(this IPublishedContent content, bool orSelf, Func<IPublishedContent, bool> func, string culture = null)
|
||||
{
|
||||
return content.EnumerateDescendants(orSelf, culture).Where(x => func == null || func(x));
|
||||
}
|
||||
|
||||
internal static IEnumerable<IPublishedContent> EnumerateDescendants(this IPublishedContent content, bool orSelf, string culture = null)
|
||||
{
|
||||
if (content == null) throw new ArgumentNullException(nameof(content));
|
||||
if (orSelf) yield return content;
|
||||
|
||||
foreach (var desc in content.Children(VariationContextAccessor, culture).SelectMany(x => x.EnumerateDescendants(culture)))
|
||||
yield return desc;
|
||||
}
|
||||
|
||||
internal static IEnumerable<IPublishedContent> EnumerateDescendants(this IPublishedContent content, string culture = null)
|
||||
{
|
||||
yield return content;
|
||||
|
||||
foreach (var desc in content.Children(VariationContextAccessor, culture).SelectMany(x => x.EnumerateDescendants(culture)))
|
||||
yield return desc;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Axes: parent
|
||||
|
||||
// Parent is native
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parent of the content, of a given content type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The content type.</typeparam>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The parent of content, of the given content type, else null.</returns>
|
||||
public static T Parent<T>(this IPublishedContent content)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
if (content == null) throw new ArgumentNullException(nameof(content));
|
||||
return content.Parent as T;
|
||||
return content.DescendantOrSelf<T>(VariationContextAccessor, level, culture);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -894,7 +530,7 @@ namespace Umbraco.Web
|
||||
/// <returns>The children of the content, of any of the specified types.</returns>
|
||||
public static IEnumerable<IPublishedContent> ChildrenOfType(this IPublishedContent content, string contentTypeAlias, string culture = null)
|
||||
{
|
||||
return content.Children(x => x.ContentType.Alias.InvariantEquals(contentTypeAlias), culture);
|
||||
return content.Children(VariationContextAccessor, x => x.ContentType.Alias.InvariantEquals(contentTypeAlias), culture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -923,29 +559,29 @@ namespace Umbraco.Web
|
||||
/// </summary>
|
||||
public static IPublishedContent FirstChildOfType(this IPublishedContent content, string contentTypeAlias, string culture = null)
|
||||
{
|
||||
return content.ChildrenOfType(contentTypeAlias, culture).FirstOrDefault();
|
||||
return content.ChildrenOfType(VariationContextAccessor, contentTypeAlias, culture).FirstOrDefault();
|
||||
}
|
||||
|
||||
public static IPublishedContent FirstChild(this IPublishedContent content, Func<IPublishedContent, bool> predicate, string culture = null)
|
||||
{
|
||||
return content.Children(predicate, culture).FirstOrDefault();
|
||||
return content.Children(VariationContextAccessor, predicate, culture).FirstOrDefault();
|
||||
}
|
||||
|
||||
public static IPublishedContent FirstChild(this IPublishedContent content, Guid uniqueId, string culture = null)
|
||||
{
|
||||
return content.Children(x=>x.Key == uniqueId, culture).FirstOrDefault();
|
||||
return content.Children(VariationContextAccessor, x => x.Key == uniqueId, culture).FirstOrDefault();
|
||||
}
|
||||
|
||||
public static T FirstChild<T>(this IPublishedContent content, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Children<T>(culture).FirstOrDefault();
|
||||
return content.Children<T>(VariationContextAccessor, culture).FirstOrDefault();
|
||||
}
|
||||
|
||||
public static T FirstChild<T>(this IPublishedContent content, Func<T, bool> predicate, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Children<T>(culture).FirstOrDefault(predicate);
|
||||
return content.Children<T>(VariationContextAccessor, culture).FirstOrDefault(predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1001,15 +637,15 @@ namespace Umbraco.Web
|
||||
|
||||
var standardVals = new Dictionary<string, object>
|
||||
{
|
||||
{ "Id", n.Id },
|
||||
{ "NodeName", n.Name(VariationContextAccessor) },
|
||||
{ "NodeTypeAlias", n.ContentType.Alias },
|
||||
{ "CreateDate", n.CreateDate },
|
||||
{ "UpdateDate", n.UpdateDate },
|
||||
{ "CreatorName", n.CreatorName },
|
||||
{ "WriterName", n.WriterName },
|
||||
{ "Url", n.Url() }
|
||||
};
|
||||
{ "Id", n.Id },
|
||||
{ "NodeName", n.Name(VariationContextAccessor) },
|
||||
{ "NodeTypeAlias", n.ContentType.Alias },
|
||||
{ "CreateDate", n.CreateDate },
|
||||
{ "UpdateDate", n.UpdateDate },
|
||||
{ "CreatorId", n.CreatorId},
|
||||
{ "WriterId", n.WriterId },
|
||||
{ "Url", n.Url() }
|
||||
};
|
||||
|
||||
var userVals = new Dictionary<string, object>();
|
||||
foreach (var p in from IPublishedProperty p in n.Properties where p.GetSourceValue() != null select p)
|
||||
@@ -1041,7 +677,7 @@ namespace Umbraco.Web
|
||||
/// </remarks>
|
||||
public static IEnumerable<IPublishedContent> Siblings(this IPublishedContent content, string culture = null)
|
||||
{
|
||||
return SiblingsAndSelf(content, culture).Where(x => x.Id != content.Id);
|
||||
return content.Siblings(PublishedSnapshot, VariationContextAccessor, culture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1056,7 +692,7 @@ namespace Umbraco.Web
|
||||
/// </remarks>
|
||||
public static IEnumerable<IPublishedContent> SiblingsOfType(this IPublishedContent content, string contentTypeAlias, string culture = null)
|
||||
{
|
||||
return SiblingsAndSelfOfType(content, contentTypeAlias, culture).Where(x => x.Id != content.Id);
|
||||
return content.SiblingsOfType(PublishedSnapshot, VariationContextAccessor, contentTypeAlias, culture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1072,7 +708,7 @@ namespace Umbraco.Web
|
||||
public static IEnumerable<T> Siblings<T>(this IPublishedContent content, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return SiblingsAndSelf<T>(content, culture).Where(x => x.Id != content.Id);
|
||||
return content.Siblings<T>(PublishedSnapshot, VariationContextAccessor, culture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1083,9 +719,7 @@ namespace Umbraco.Web
|
||||
/// <returns>The siblings of the content including the node itself.</returns>
|
||||
public static IEnumerable<IPublishedContent> SiblingsAndSelf(this IPublishedContent content, string culture = null)
|
||||
{
|
||||
return content.Parent != null
|
||||
? content.Parent.Children(VariationContextAccessor, culture)
|
||||
: PublishedSnapshot.Content.GetAtRoot().WhereIsInvariantOrHasCulture(VariationContextAccessor, culture);
|
||||
return content.SiblingsAndSelf(PublishedSnapshot, VariationContextAccessor, culture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1097,9 +731,7 @@ namespace Umbraco.Web
|
||||
/// <returns>The siblings of the content including the node itself, of the given content type.</returns>
|
||||
public static IEnumerable<IPublishedContent> SiblingsAndSelfOfType(this IPublishedContent content, string contentTypeAlias, string culture = null)
|
||||
{
|
||||
return content.Parent != null
|
||||
? content.Parent.ChildrenOfType(contentTypeAlias, culture)
|
||||
: PublishedSnapshot.Content.GetAtRoot().OfTypes(contentTypeAlias).WhereIsInvariantOrHasCulture(VariationContextAccessor, culture);
|
||||
return content.SiblingsAndSelfOfType(PublishedSnapshot, VariationContextAccessor, contentTypeAlias, culture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1112,23 +744,7 @@ namespace Umbraco.Web
|
||||
public static IEnumerable<T> SiblingsAndSelf<T>(this IPublishedContent content, string culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Parent != null
|
||||
? content.Parent.Children<T>(culture)
|
||||
: PublishedSnapshot.Content.GetAtRoot().OfType<T>().WhereIsInvariantOrHasCulture(VariationContextAccessor, culture);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Axes: custom
|
||||
|
||||
/// <summary>
|
||||
/// Gets the root content for this content.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The 'site' content ie AncestorOrSelf(1).</returns>
|
||||
public static IPublishedContent Root(this IPublishedContent content)
|
||||
{
|
||||
return content.AncestorOrSelf(1);
|
||||
return content.SiblingsAndSelf<T>(PublishedSnapshot, VariationContextAccessor, culture);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -1181,6 +797,20 @@ namespace Umbraco.Web
|
||||
|
||||
#endregion
|
||||
|
||||
#region Writer and creator
|
||||
|
||||
public static string CreatorName(this IPublishedContent content)
|
||||
{
|
||||
return content.GetCreatorName(UserService);
|
||||
}
|
||||
|
||||
public static string WriterName(this IPublishedContent content)
|
||||
{
|
||||
return content.GetWriterName(UserService);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Url
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -157,20 +157,6 @@ namespace Umbraco.Web
|
||||
|
||||
#endregion
|
||||
|
||||
#region OfTypes
|
||||
|
||||
// the .OfType<T>() filter is nice when there's only one type
|
||||
// this is to support filtering with multiple types
|
||||
public static IEnumerable<T> OfTypes<T>(this IEnumerable<T> contents, params string[] types)
|
||||
where T : IPublishedElement
|
||||
{
|
||||
if (types == null || types.Length == 0) return Enumerable.Empty<T>();
|
||||
|
||||
return contents.Where(x => types.InvariantContains(x.ContentType.Alias));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsSomething
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace Umbraco.Web.Routing
|
||||
private readonly IVariationContextAccessor _variationContextAccessor;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IUmbracoSettingsSection _umbracoSettingsSection;
|
||||
private readonly IUserService _userService;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PublishedRouter"/> class.
|
||||
@@ -39,7 +40,8 @@ namespace Umbraco.Web.Routing
|
||||
IVariationContextAccessor variationContextAccessor,
|
||||
ServiceContext services,
|
||||
IProfilingLogger proflog,
|
||||
IUmbracoSettingsSection umbracoSettingsSection)
|
||||
IUmbracoSettingsSection umbracoSettingsSection,
|
||||
IUserService userService)
|
||||
{
|
||||
_webRoutingSection = webRoutingSection ?? throw new ArgumentNullException(nameof(webRoutingSection));
|
||||
_contentFinders = contentFinders ?? throw new ArgumentNullException(nameof(contentFinders));
|
||||
@@ -49,6 +51,7 @@ namespace Umbraco.Web.Routing
|
||||
_variationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor));
|
||||
_logger = proflog;
|
||||
_umbracoSettingsSection = umbracoSettingsSection ?? throw new ArgumentNullException(nameof(umbracoSettingsSection));
|
||||
_userService = userService ?? throw new ArgumentNullException(nameof(userService));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -194,7 +197,7 @@ namespace Umbraco.Web.Routing
|
||||
|
||||
// assign the legacy page back to the request
|
||||
// handlers like default.aspx will want it and most macros currently need it
|
||||
frequest.LegacyContentHashTable = new PublishedContentHashtableConverter(frequest);
|
||||
frequest.LegacyContentHashTable = new PublishedContentHashtableConverter(frequest, _userService);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -234,8 +237,7 @@ namespace Umbraco.Web.Routing
|
||||
|
||||
// assign the legacy page back to the docrequest
|
||||
// handlers like default.aspx will want it and most macros currently need it
|
||||
request.LegacyContentHashTable = new PublishedContentHashtableConverter(request);
|
||||
|
||||
request.LegacyContentHashTable = new PublishedContentHashtableConverter(request, _userService);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Events;
|
||||
|
||||
@@ -214,10 +214,7 @@
|
||||
<Compile Include="Net\AspNetSessionIdResolver.cs" />
|
||||
<Compile Include="Profiling\WebProfilingController.cs" />
|
||||
<Compile Include="PropertyEditors\RichTextEditorPastedImages.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\PublishedSnapshotServiceOptions.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\Snap\GenObj.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\Snap\GenRef.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\Snap\LinkedNode.cs" />
|
||||
<Compile Include="PublishedCache\UmbracoContextPublishedSnapshotAccessor.cs" />
|
||||
<Compile Include="RoutableDocumentFilter.cs" />
|
||||
<Compile Include="Routing\DefaultMediaUrlProvider.cs" />
|
||||
<Compile Include="Routing\IMediaUrlProvider.cs" />
|
||||
@@ -262,7 +259,6 @@
|
||||
<Compile Include="PropertyEditors\ValueConverters\MultiUrlPickerValueConverter.cs" />
|
||||
<Compile Include="Templates\ITemplateRenderer.cs" />
|
||||
<Compile Include="PropertyEditors\GridPropertyIndexValueFactory.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\NuCacheComposer.cs" />
|
||||
<Compile Include="Routing\RedirectTrackingComposer.cs" />
|
||||
<Compile Include="Runtime\WebInitialComposer.cs" />
|
||||
<Compile Include="Scheduling\SchedulerComposer.cs" />
|
||||
@@ -361,48 +357,7 @@
|
||||
<Compile Include="PropertyEditors\ValueConverters\MediaPickerValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\MemberPickerValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\MultiNodeTreePickerValueConverter.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\DataSource\BTree.ContentDataSerializer.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\DataSource\BTree.ContentNodeKitSerializer.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\DataSource\BTree.DictionaryOfCultureVariationSerializer.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\DataSource\BTree.DictionaryOfPropertyDataSerializer.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\DataSource\ContentNestedData.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\DataSource\CultureVariation.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\DataSource\IDataSource.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\DataSource\PropertyData.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\DataSource\SerializerBase.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\NuCacheComponent.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\PublishedSnapshot.cs" />
|
||||
<Compile Include="PublishedCache\PublishedElement.cs" />
|
||||
<Compile Include="PublishedCache\PublishedElementPropertyBase.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\ContentPickerValueConverter.cs" />
|
||||
<Compile Include="PublishedCache\PublishedSnapshotServiceBase.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\CacheKeys.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\ContentCache.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\ContentNode.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\ContentNodeKit.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\ContentStore.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\DataSource\BTree.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\DataSource\ContentData.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\DataSource\ContentSourceDto.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\DataSource\DatabaseDataSource.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\DomainCache.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\PublishedSnapshotService.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\MediaCache.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\MemberCache.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\Navigable\INavigableData.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\Navigable\NavigableContent.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\Navigable\NavigableContentType.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\Navigable\NavigablePropertyType.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\Navigable\RootContent.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\Navigable\Source.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\Property.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\PublishedContent.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\PublishedMember.cs" />
|
||||
<Compile Include="PublishedCache\NuCache\SnapDictionary.cs" />
|
||||
<Compile Include="PublishedCache\PublishedCacheBase.cs" />
|
||||
<Compile Include="PublishedCache\PublishedContentTypeCache.cs" />
|
||||
<Compile Include="PublishedCache\DefaultCultureAccessor.cs" />
|
||||
<Compile Include="PublishedCache\UmbracoContextPublishedSnapshotAccessor.cs" />
|
||||
<Compile Include="PublishedElementExtensions.cs" />
|
||||
<Compile Include="PublishedModels\DummyClassSoThatPublishedModelsNamespaceExists.cs" />
|
||||
<Compile Include="Routing\ContentFinderByUrl.cs" />
|
||||
@@ -447,7 +402,7 @@
|
||||
<Compile Include="WebApi\UnhandledExceptionLogger.cs" />
|
||||
<Compile Include="Runtime\WebInitialComponent.cs" />
|
||||
<Compile Include="Editors\PublishedStatusController.cs" />
|
||||
<Compile Include="Editors\NuCacheStatusController.cs" />
|
||||
<Compile Include="Editors\PublishedSnapshotCacheStatusController.cs" />
|
||||
<Compile Include="Trees\TreeAttribute.cs" />
|
||||
<Compile Include="Routing\NotFoundHandlerHelper.cs" />
|
||||
<Compile Include="Models\LocalPackageInstallModel.cs" />
|
||||
@@ -536,7 +491,6 @@
|
||||
<Compile Include="PropertyEditors\GridPropertyEditor.cs" />
|
||||
<Compile Include="Mvc\UmbracoVirtualNodeByIdRouteHandler.cs" />
|
||||
<Compile Include="PropertyEditors\TagsDataController.cs" />
|
||||
<Compile Include="PublishedCache\PublishedMember.cs" />
|
||||
<Compile Include="Mvc\JsonNetResult.cs" />
|
||||
<Compile Include="Mvc\MinifyJavaScriptResultAttribute.cs" />
|
||||
<Compile Include="Mvc\EnsurePublishedContentRequestAttribute.cs" />
|
||||
@@ -639,7 +593,6 @@
|
||||
<Compile Include="Macros\PartialViewMacroController.cs" />
|
||||
<Compile Include="Macros\PartialViewMacroEngine.cs" />
|
||||
<Compile Include="Macros\PartialViewMacroPage.cs" />
|
||||
<Compile Include="Models\PublishedContentBase.cs" />
|
||||
<Compile Include="Mvc\AreaRegistrationExtensions.cs" />
|
||||
<Compile Include="Mvc\QueryStringFilterAttribute.cs" />
|
||||
<Compile Include="Mvc\MemberAuthorizeAttribute.cs" />
|
||||
@@ -808,7 +761,6 @@
|
||||
<EmbeddedResource Include="JavaScript\PreviewInitialize.js" />
|
||||
<None Include="JavaScript\TinyMceInitialize.js" />
|
||||
<!--<Content Include="umbraco.presentation\umbraco\users\PermissionEditor.aspx" />-->
|
||||
<None Include="PublishedCache\NuCache\readme.md" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Web References\org.umbraco.update\checkforupgrade.disco" />
|
||||
|
||||
@@ -111,6 +111,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Umbraco.Persistance.SqlCe",
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.TestData", "Umbraco.TestData\Umbraco.TestData.csproj", "{FB5676ED-7A69-492C-B802-E7B24144C0FC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.PublishedCache.NuCache", "Umbraco.PublishedCache.NuCache\Umbraco.PublishedCache.NuCache.csproj", "{F6DE8DA0-07CC-4EF2-8A59-2BC81DBB3830}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Umbraco.Examine", "Umbraco.Examine\Umbraco.Examine.csproj", "{F9B7FE05-0F93-4D0D-9C10-690B33ECBBD8}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Examine.Lucene", "Umbraco.Examine.Lucene\Umbraco.Examine.Lucene.csproj", "{0FAD7D2A-D7DD-45B1-91FD-488BB6CDACEA}"
|
||||
@@ -163,6 +165,10 @@ Global
|
||||
{FB5676ED-7A69-492C-B802-E7B24144C0FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FB5676ED-7A69-492C-B802-E7B24144C0FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FB5676ED-7A69-492C-B802-E7B24144C0FC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F6DE8DA0-07CC-4EF2-8A59-2BC81DBB3830}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F6DE8DA0-07CC-4EF2-8A59-2BC81DBB3830}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F6DE8DA0-07CC-4EF2-8A59-2BC81DBB3830}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F6DE8DA0-07CC-4EF2-8A59-2BC81DBB3830}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F9B7FE05-0F93-4D0D-9C10-690B33ECBBD8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F9B7FE05-0F93-4D0D-9C10-690B33ECBBD8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F9B7FE05-0F93-4D0D-9C10-690B33ECBBD8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
||||
Reference in New Issue
Block a user