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:
Bjarke Berg
2020-02-07 06:47:46 +01:00
committed by GitHub
96 changed files with 1080 additions and 807 deletions
@@ -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>
@@ -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();
}
}
@@ -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);
}
}
@@ -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)
@@ -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;
@@ -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
}
}
@@ -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
{
@@ -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;
@@ -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;
@@ -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)
@@ -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; }
@@ -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,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
{
@@ -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;
@@ -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;
@@ -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,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;
});
@@ -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;
@@ -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>(),
+2 -1
View File
@@ -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>());
}
}
}
+4
View File
@@ -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>
@@ -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,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;
});
+4
View File
@@ -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,3 +1,4 @@
@using Umbraco.Core
@using Umbraco.Web
@inherits Umbraco.Web.Macros.PartialViewMacroPage
@@ -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
-31
View File
@@ -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);
}
+4 -2
View File
@@ -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);
+58 -428
View File
@@ -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>
+6 -4
View File
@@ -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;
+2 -50
View File
@@ -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" />
+6
View File
@@ -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