Merge branch 'temp8-U4-11227' into temp8-U4-11282
# Conflicts: # src/Umbraco.Core/Models/ContentBase.cs # src/Umbraco.Core/Persistence/Repositories/Implement/EntityRepository.cs # src/Umbraco.Tests/Services/EntityServiceTests.cs # src/Umbraco.Web/PublishedCache/NuCache/ContentCache.cs # src/Umbraco.Web/PublishedContentExtensions.cs # src/Umbraco.Web/Trees/ContentTreeControllerBase.cs
This commit is contained in:
@@ -3,22 +3,22 @@
|
||||
namespace Umbraco.Web.PublishedCache
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides the default implementation of <see cref="ISystemDefaultCultureProvider"/>.
|
||||
/// Provides the default implementation of <see cref="IDefaultCultureAccessor"/>.
|
||||
/// </summary>
|
||||
public class SystemDefaultCultureProvider : ISystemDefaultCultureProvider
|
||||
public class DefaultCultureAccessor : IDefaultCultureAccessor
|
||||
{
|
||||
private readonly ILocalizationService _localizationService;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SystemDefaultCultureProvider"/> class.
|
||||
/// Initializes a new instance of the <see cref="DefaultCultureAccessor"/> class.
|
||||
/// </summary>
|
||||
/// <param name="localizationService"></param>
|
||||
public SystemDefaultCultureProvider(ILocalizationService localizationService)
|
||||
public DefaultCultureAccessor(ILocalizationService localizationService)
|
||||
{
|
||||
_localizationService = localizationService;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string DefaultCulture => _localizationService.GetDefaultLanguageIsoCode(); // capture - fast
|
||||
public string DefaultCulture => _localizationService.GetDefaultLanguageIsoCode() ?? ""; // fast
|
||||
}
|
||||
}
|
||||
}
|
||||
16
src/Umbraco.Web/PublishedCache/IDefaultCultureAccessor.cs
Normal file
16
src/Umbraco.Web/PublishedCache/IDefaultCultureAccessor.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace Umbraco.Web.PublishedCache
|
||||
{
|
||||
/// <summary>
|
||||
/// Gives access to the default culture.
|
||||
/// </summary>
|
||||
public interface IDefaultCultureAccessor
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the system default culture.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Implementations must NOT return a null value. Return an empty string for the invariant culture.</para>
|
||||
/// </remarks>
|
||||
string DefaultCulture { get; }
|
||||
}
|
||||
}
|
||||
@@ -33,11 +33,18 @@ namespace Umbraco.Web.PublishedCache
|
||||
/// <summary>
|
||||
/// Gets the snapshot-level cache.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The snapshot-level cache belongs to this snapshot only.</para>
|
||||
/// </remarks>
|
||||
ICacheProvider SnapshotCache { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the elements-level cache.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The elements-level cache is shared by all snapshots relying on the same elements,
|
||||
/// ie all snapshots built on top of unchanging content / media / etc.</para>
|
||||
/// </remarks>
|
||||
ICacheProvider ElementsCache { get; }
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace Umbraco.Web.PublishedCache
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides the system default culture.
|
||||
/// </summary>
|
||||
public interface ISystemDefaultCultureProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the system default culture.
|
||||
/// </summary>
|
||||
string DefaultCulture { get; }
|
||||
}
|
||||
}
|
||||
@@ -43,11 +43,6 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
return "NuCache.Profile.Name[" + userId + "]";
|
||||
}
|
||||
|
||||
public static string PropertyRecurse(Guid contentUid, string typeAlias, bool previewing)
|
||||
{
|
||||
return "NuCache.Property.Recurse[" + DraftOrPub(previewing) + contentUid + ":" + typeAlias + "]";
|
||||
}
|
||||
|
||||
public static string PropertyCacheValues(Guid contentUid, string typeAlias, bool previewing)
|
||||
{
|
||||
return "NuCache.Property.CacheValues[" + DraftOrPub(previewing) + contentUid + ":" + typeAlias + "]";
|
||||
|
||||
@@ -104,8 +104,8 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// hideTopLevelNode = support legacy stuff, look for /*/path/to/node
|
||||
// else normal, look for /path/to/node
|
||||
content = hideTopLevelNode.Value
|
||||
? GetAtRoot(preview).SelectMany(x => x.Children).FirstOrDefault(x => x.GetUrlName(_localizationService, culture) == parts[0])
|
||||
: GetAtRoot(preview).FirstOrDefault(x => x.GetUrlName(_localizationService, culture) == parts[0]);
|
||||
? GetAtRoot(preview).SelectMany(x => x.Children).FirstOrDefault(x => x.GetCulture(culture).UrlSegment == parts[0])
|
||||
: GetAtRoot(preview).FirstOrDefault(x => x.GetCulture(culture).UrlSegment == parts[0]);
|
||||
content = FollowRoute(content, parts, 1, culture);
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// have to look for /foo (see note in ApplyHideTopLevelNodeFromPath).
|
||||
if (content == null && hideTopLevelNode.Value && parts.Length == 1)
|
||||
{
|
||||
content = GetAtRoot(preview).FirstOrDefault(x => x.GetUrlName(_localizationService, culture) == parts[0]);
|
||||
content = GetAtRoot(preview).FirstOrDefault(x => x.GetCulture(culture).UrlSegment == parts[0]);
|
||||
}
|
||||
|
||||
return content;
|
||||
@@ -147,14 +147,20 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
var hasDomains = _domainHelper.NodeHasDomains(n.Id);
|
||||
while (hasDomains == false && n != null) // n is null at root
|
||||
{
|
||||
var urlName = n.GetUrlName(_localizationService, culture);
|
||||
if (urlName == null)
|
||||
var varies = n.ContentType.Variations.Has(ContentVariation.CultureNeutral);
|
||||
var urlSegment = varies ? n.GetCulture(culture)?.UrlSegment : n.UrlSegment;
|
||||
if (urlSegment.IsNullOrWhiteSpace())
|
||||
{
|
||||
//we cannot continue, it will be null if the item is not published
|
||||
return null;
|
||||
}
|
||||
|
||||
//// at that point we should have an urlSegment, unless something weird is happening
|
||||
//// at content level, such as n.GetCulture() returning null for some (weird) reason,
|
||||
//// and then what? fallback to the invariant segment... far from perfect but eh...
|
||||
//if (string.IsNullOrWhiteSpace(urlSegment)) urlSegment = n.UrlSegment;
|
||||
|
||||
pathParts.Add(urlName);
|
||||
pathParts.Add(urlSegment);
|
||||
|
||||
// move to parent node
|
||||
n = n.Parent;
|
||||
@@ -183,8 +189,8 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
var part = parts[i++];
|
||||
content = content.Children.FirstOrDefault(x =>
|
||||
{
|
||||
var urlName = x.GetUrlName(_localizationService, culture);
|
||||
return urlName == part;
|
||||
var urlSegment = x.GetCulture(culture).UrlSegment;
|
||||
return urlSegment == part;
|
||||
});
|
||||
}
|
||||
return content;
|
||||
|
||||
@@ -33,10 +33,11 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
int parentContentId,
|
||||
DateTime createDate, int creatorId,
|
||||
ContentData draftData, ContentData publishedData,
|
||||
IPublishedSnapshotAccessor publishedSnapshotAccessor)
|
||||
IPublishedSnapshotAccessor publishedSnapshotAccessor,
|
||||
IVariationContextAccessor variationContextAccessor)
|
||||
: this(id, uid, level, path, sortOrder, parentContentId, createDate, creatorId)
|
||||
{
|
||||
SetContentTypeAndData(contentType, draftData, publishedData, publishedSnapshotAccessor);
|
||||
SetContentTypeAndData(contentType, draftData, publishedData, publishedSnapshotAccessor, variationContextAccessor);
|
||||
}
|
||||
|
||||
// 2-phases ctor, phase 1
|
||||
@@ -58,7 +59,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
}
|
||||
|
||||
// two-phase ctor, phase 2
|
||||
public void SetContentTypeAndData(PublishedContentType contentType, ContentData draftData, ContentData publishedData, IPublishedSnapshotAccessor publishedSnapshotAccessor)
|
||||
public void SetContentTypeAndData(PublishedContentType contentType, ContentData draftData, ContentData publishedData, IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor)
|
||||
{
|
||||
ContentType = contentType;
|
||||
|
||||
@@ -66,9 +67,9 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
throw new ArgumentException("Both draftData and publishedData cannot be null at the same time.");
|
||||
|
||||
if (draftData != null)
|
||||
Draft = new PublishedContent(this, draftData, publishedSnapshotAccessor).CreateModel();
|
||||
Draft = new PublishedContent(this, draftData, publishedSnapshotAccessor, variationContextAccessor).CreateModel();
|
||||
if (publishedData != null)
|
||||
Published = new PublishedContent(this, publishedData, publishedSnapshotAccessor).CreateModel();
|
||||
Published = new PublishedContent(this, publishedData, publishedSnapshotAccessor, variationContextAccessor).CreateModel();
|
||||
}
|
||||
|
||||
// clone parent
|
||||
@@ -97,7 +98,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
}
|
||||
|
||||
// clone with new content type
|
||||
public ContentNode(ContentNode origin, PublishedContentType contentType, IPublishedSnapshotAccessor publishedSnapshotAccessor)
|
||||
public ContentNode(ContentNode origin, PublishedContentType contentType, IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor)
|
||||
{
|
||||
Id = origin.Id;
|
||||
Uid = origin.Uid;
|
||||
@@ -112,8 +113,8 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
var originDraft = origin.Draft == null ? null : PublishedContent.UnwrapIPublishedContent(origin.Draft);
|
||||
var originPublished = origin.Published == null ? null : PublishedContent.UnwrapIPublishedContent(origin.Published);
|
||||
|
||||
Draft = originDraft == null ? null : new PublishedContent(this, originDraft._contentData, publishedSnapshotAccessor).CreateModel();
|
||||
Published = originPublished == null ? null : new PublishedContent(this, originPublished._contentData, publishedSnapshotAccessor).CreateModel();
|
||||
Draft = originDraft == null ? null : new PublishedContent(this, originDraft._contentData, publishedSnapshotAccessor, variationContextAccessor).CreateModel();
|
||||
Published = originPublished == null ? null : new PublishedContent(this, originPublished._contentData, publishedSnapshotAccessor, variationContextAccessor).CreateModel();
|
||||
|
||||
ChildContentIds = origin.ChildContentIds; // can be the *same* list FIXME oh really?
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
public static ContentNodeKit Null { get; } = new ContentNodeKit { ContentTypeId = -1 };
|
||||
|
||||
public void Build(PublishedContentType contentType, IPublishedSnapshotAccessor publishedSnapshotAccessor)
|
||||
public void Build(PublishedContentType contentType, IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor)
|
||||
{
|
||||
Node.SetContentTypeAndData(contentType, DraftData, PublishedData, publishedSnapshotAccessor);
|
||||
Node.SetContentTypeAndData(contentType, DraftData, PublishedData, publishedSnapshotAccessor, variationContextAccessor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// SnapDictionary has unit tests to ensure it all works correctly
|
||||
|
||||
private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
|
||||
private readonly IVariationContextAccessor _variationContextAccessor;
|
||||
private readonly ConcurrentDictionary<int, LinkedNode<ContentNode>> _contentNodes;
|
||||
private readonly ConcurrentDictionary<int, LinkedNode<object>> _contentRootNodes;
|
||||
private readonly ConcurrentDictionary<int, LinkedNode<PublishedContentType>> _contentTypesById;
|
||||
@@ -43,9 +44,10 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
#region Ctor
|
||||
|
||||
public ContentStore(IPublishedSnapshotAccessor publishedSnapshotAccessor, ILogger logger, BPlusTree<int, ContentNodeKit> localDb = null)
|
||||
public ContentStore(IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor, ILogger logger, BPlusTree<int, ContentNodeKit> localDb = null)
|
||||
{
|
||||
_publishedSnapshotAccessor = publishedSnapshotAccessor;
|
||||
_variationContextAccessor = variationContextAccessor;
|
||||
_logger = logger;
|
||||
_localDb = localDb;
|
||||
|
||||
@@ -277,7 +279,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
if (node == null) continue;
|
||||
var contentTypeId = node.ContentType.Id;
|
||||
if (index.TryGetValue(contentTypeId, out PublishedContentType contentType) == false) continue;
|
||||
SetValueLocked(_contentNodes, node.Id, new ContentNode(node, contentType, _publishedSnapshotAccessor));
|
||||
SetValueLocked(_contentNodes, node.Id, new ContentNode(node, contentType, _publishedSnapshotAccessor, _variationContextAccessor));
|
||||
}
|
||||
}
|
||||
finally
|
||||
@@ -391,7 +393,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
_contentNodes.TryGetValue(id, out LinkedNode<ContentNode> link);
|
||||
if (link?.Value == null)
|
||||
continue;
|
||||
var node = new ContentNode(link.Value, contentType, _publishedSnapshotAccessor);
|
||||
var node = new ContentNode(link.Value, contentType, _publishedSnapshotAccessor, _variationContextAccessor);
|
||||
SetValueLocked(_contentNodes, id, node);
|
||||
if (_localDb != null) RegisterChange(id, node.ToKit());
|
||||
}
|
||||
@@ -414,7 +416,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
return false;
|
||||
|
||||
// and use
|
||||
kit.Build(link.Value, _publishedSnapshotAccessor);
|
||||
kit.Build(link.Value, _publishedSnapshotAccessor, _variationContextAccessor);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -9,16 +9,16 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
|
||||
{
|
||||
public IReadOnlyDictionary<string, CultureVariation> ReadFrom(Stream stream)
|
||||
{
|
||||
var dict = new Dictionary<string, CultureVariation>();
|
||||
|
||||
// read variations count
|
||||
var pcount = PrimitiveSerializer.Int32.ReadFrom(stream);
|
||||
if (pcount == 0) return Empty;
|
||||
|
||||
// read each variation
|
||||
var dict = new Dictionary<string, CultureVariation>();
|
||||
for (var i = 0; i < pcount; i++)
|
||||
{
|
||||
var languageId = PrimitiveSerializer.String.ReadFrom(stream);
|
||||
var cultureVariation = new CultureVariation { Name = ReadStringObject(stream) };
|
||||
var cultureVariation = new CultureVariation { Name = ReadStringObject(stream), Date = ReadDateTime(stream) };
|
||||
dict[languageId] = cultureVariation;
|
||||
}
|
||||
return dict;
|
||||
@@ -40,6 +40,7 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
|
||||
|
||||
PrimitiveSerializer.String.WriteTo(culture, stream); // should never be null
|
||||
WriteObject(variation.Name, stream); // write an object in case it's null (though... should not happen)
|
||||
PrimitiveSerializer.DateTime.WriteTo(variation.Date, stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,20 +6,18 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
|
||||
// represents everything that is specific to edited or published version
|
||||
internal class ContentData
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int VersionId { get; set; }
|
||||
public DateTime VersionDate { get; set; }
|
||||
public int WriterId { get; set; }
|
||||
public int TemplateId { get; set; }
|
||||
public bool Published { get; set; }
|
||||
|
||||
public IDictionary<string, PropertyData[]> Properties { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The collection of language Id to name for the content item
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, CultureVariation> CultureInfos { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
public int VersionId { get; set; }
|
||||
//TODO: This will not make a lot of sense since we'll have dates for each variant publishing, need to wait on Stephane
|
||||
public DateTime VersionDate { get; set; }
|
||||
public int WriterId { get; set; }
|
||||
public int TemplateId { get; set; }
|
||||
|
||||
public IDictionary<string, PropertyData[]> Properties { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache.NuCache.DataSource
|
||||
{
|
||||
@@ -10,6 +11,7 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
//TODO: We may want some date stamps here
|
||||
[JsonProperty("date")]
|
||||
public DateTime Date { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource
|
||||
// fixme - use SqlTemplate for these queries else it's going to be horribly slow!
|
||||
|
||||
// provides efficient database access for NuCache
|
||||
internal class Database
|
||||
internal class DatabaseDataSource : IDataSource
|
||||
{
|
||||
// we want arrays, we want them all loaded, not an enumerable
|
||||
|
||||
@@ -186,7 +186,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<Database>("Missing cmsContentNu edited content for node " + dto.Id + ", consider rebuilding.");
|
||||
Current.Logger.Warn<DatabaseDataSource>("Missing cmsContentNu edited content for node " + dto.Id + ", consider rebuilding.");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -211,7 +211,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<Database>("Missing cmsContentNu published content for node " + dto.Id + ", consider rebuilding.");
|
||||
Current.Logger.Warn<DatabaseDataSource>("Missing cmsContentNu published content for node " + dto.Id + ", consider rebuilding.");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Scoping;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache.NuCache.DataSource
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a data source for NuCache.
|
||||
/// </summary>
|
||||
internal interface IDataSource
|
||||
{
|
||||
ContentNodeKit GetContentSource(IScope scope, int id);
|
||||
IEnumerable<ContentNodeKit> GetAllContentSources(IScope scope);
|
||||
IEnumerable<ContentNodeKit> GetBranchContentSources(IScope scope, int id);
|
||||
IEnumerable<ContentNodeKit> GetTypeContentSources(IScope scope, IEnumerable<int> ids);
|
||||
|
||||
ContentNodeKit GetMediaSource(IScope scope, int id);
|
||||
IEnumerable<ContentNodeKit> GetAllMediaSources(IScope scope);
|
||||
IEnumerable<ContentNodeKit> GetBranchMediaSources(IScope scope, int id);
|
||||
IEnumerable<ContentNodeKit> GetTypeMediaSources(IScope scope, IEnumerable<int> ids);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,26 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache.NuCache.DataSource
|
||||
{
|
||||
internal class PropertyData
|
||||
{
|
||||
private string _culture;
|
||||
private string _segment;
|
||||
|
||||
[JsonProperty("culture")]
|
||||
public string Culture { get; set; }
|
||||
public string Culture
|
||||
{
|
||||
get => _culture;
|
||||
set => _culture = value ?? throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
|
||||
[JsonProperty("seg")]
|
||||
public string Segment { get; set; }
|
||||
public string Segment
|
||||
{
|
||||
get => _segment;
|
||||
set => _segment = value ?? throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
|
||||
[JsonProperty("val")]
|
||||
public object Value { get; set; }
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
class MemberCache : IPublishedMemberCache, INavigableData
|
||||
{
|
||||
private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
|
||||
public readonly IVariationContextAccessor VariationContextAccessor;
|
||||
private readonly ICacheProvider _snapshotCache;
|
||||
private readonly IMemberService _memberService;
|
||||
private readonly IDataTypeService _dataTypeService;
|
||||
@@ -23,10 +24,11 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
private readonly PublishedContentTypeCache _contentTypeCache;
|
||||
private readonly bool _previewDefault;
|
||||
|
||||
public MemberCache(bool previewDefault, ICacheProvider snapshotCache, IMemberService memberService, IDataTypeService dataTypeService, ILocalizationService localizationService, PublishedContentTypeCache contentTypeCache, IPublishedSnapshotAccessor publishedSnapshotAccessor)
|
||||
public MemberCache(bool previewDefault, ICacheProvider snapshotCache, IMemberService memberService, IDataTypeService dataTypeService, ILocalizationService localizationService, PublishedContentTypeCache contentTypeCache, IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor)
|
||||
{
|
||||
_snapshotCache = snapshotCache;
|
||||
_publishedSnapshotAccessor = publishedSnapshotAccessor;
|
||||
VariationContextAccessor = variationContextAccessor;
|
||||
_memberService = memberService;
|
||||
_dataTypeService = dataTypeService;
|
||||
_localizationService = localizationService;
|
||||
@@ -63,14 +65,14 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
var member = _memberService.GetById(memberId);
|
||||
return member == null
|
||||
? null
|
||||
: PublishedMember.Create(member, GetContentType(member.ContentTypeId), _previewDefault, _publishedSnapshotAccessor);
|
||||
: PublishedMember.Create(member, GetContentType(member.ContentTypeId), _previewDefault, _publishedSnapshotAccessor, VariationContextAccessor);
|
||||
});
|
||||
}
|
||||
|
||||
private IPublishedContent /*IPublishedMember*/ GetById(IMember member, bool previewing)
|
||||
{
|
||||
return GetCacheItem(CacheKeys.MemberCacheMember("ById", _previewDefault, member.Id), () =>
|
||||
PublishedMember.Create(member, GetContentType(member.ContentTypeId), previewing, _publishedSnapshotAccessor));
|
||||
PublishedMember.Create(member, GetContentType(member.ContentTypeId), previewing, _publishedSnapshotAccessor, VariationContextAccessor));
|
||||
}
|
||||
|
||||
public IPublishedContent /*IPublishedMember*/ GetByProviderKey(object key)
|
||||
@@ -105,7 +107,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
public IPublishedContent /*IPublishedMember*/ GetByMember(IMember member)
|
||||
{
|
||||
return PublishedMember.Create(member, GetContentType(member.ContentTypeId), _previewDefault, _publishedSnapshotAccessor);
|
||||
return PublishedMember.Create(member, GetContentType(member.ContentTypeId), _previewDefault, _publishedSnapshotAccessor, VariationContextAccessor);
|
||||
}
|
||||
|
||||
public IEnumerable<IPublishedContent> GetAtRoot(bool preview)
|
||||
@@ -113,7 +115,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// because members are flat (not a tree) everything is at root
|
||||
// because we're loading everything... let's just not cache?
|
||||
var members = _memberService.GetAllMembers();
|
||||
return members.Select(m => PublishedMember.Create(m, GetContentType(m.ContentTypeId), preview, _publishedSnapshotAccessor));
|
||||
return members.Select(m => PublishedMember.Create(m, GetContentType(m.ContentTypeId), preview, _publishedSnapshotAccessor, VariationContextAccessor));
|
||||
}
|
||||
|
||||
public XPathNavigator CreateNavigator()
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Umbraco.Web.PublishedCache.NuCache.Navigable
|
||||
XmlString(i++, _content.TemplateId),
|
||||
XmlString(i++, _content.WriterId),
|
||||
XmlString(i++, _content.CreatorId),
|
||||
XmlString(i++, _content.UrlName),
|
||||
XmlString(i++, _content.UrlSegment),
|
||||
XmlString(i, _content.IsDraft)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Components;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Scoping;
|
||||
using Umbraco.Core.Services;
|
||||
using LightInject;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Components;
|
||||
using Umbraco.Web.PublishedCache.NuCache.DataSource;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache.NuCache
|
||||
{
|
||||
@@ -15,6 +9,9 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
{
|
||||
base.Compose(composition);
|
||||
|
||||
// register the NuCache database data source
|
||||
composition.Container.Register<IDataSource, DatabaseDataSource>();
|
||||
|
||||
// register the NuCache published snapshot service
|
||||
// must register default options, required in the service ctor
|
||||
composition.Container.Register(factory => new PublishedSnapshotService.Options());
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Serialization;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Collections;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Web.PublishedCache.NuCache.DataSource;
|
||||
@@ -18,7 +19,8 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
private readonly Guid _contentUid;
|
||||
private readonly bool _isPreviewing;
|
||||
private readonly bool _isMember;
|
||||
private readonly IPublishedContent _content;
|
||||
private readonly PublishedContent _content;
|
||||
private readonly ContentVariation _variations;
|
||||
|
||||
private readonly object _locko = new object();
|
||||
|
||||
@@ -34,7 +36,6 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
private CacheValues _cacheValues;
|
||||
|
||||
private string _valuesCacheKey;
|
||||
private string _recurseCacheKey;
|
||||
|
||||
// initializes a published content property with no value
|
||||
public Property(PublishedPropertyType propertyType, PublishedContent content, IPublishedSnapshotAccessor publishedSnapshotAccessor, PropertyCacheLevel referenceCacheLevel = PropertyCacheLevel.Element)
|
||||
@@ -49,7 +50,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
{
|
||||
foreach (var sourceValue in sourceValues)
|
||||
{
|
||||
if (sourceValue.Culture == null && sourceValue.Segment == null)
|
||||
if (sourceValue.Culture == "" && sourceValue.Segment == "")
|
||||
{
|
||||
_sourceValue = sourceValue.Value;
|
||||
}
|
||||
@@ -68,10 +69,11 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
_isPreviewing = content.IsPreviewing;
|
||||
_isMember = content.ContentType.ItemType == PublishedItemType.Member;
|
||||
_publishedSnapshotAccessor = publishedSnapshotAccessor;
|
||||
_variations = propertyType.Variations;
|
||||
}
|
||||
|
||||
// clone for previewing as draft a published content that is published and has no draft
|
||||
public Property(Property origin, IPublishedContent content)
|
||||
public Property(Property origin, PublishedContent content)
|
||||
: base(origin.PropertyType, origin.ReferenceCacheLevel)
|
||||
{
|
||||
_sourceValue = origin._sourceValue;
|
||||
@@ -82,15 +84,12 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
_isPreviewing = true;
|
||||
_isMember = origin._isMember;
|
||||
_publishedSnapshotAccessor = origin._publishedSnapshotAccessor;
|
||||
_variations = origin._variations;
|
||||
}
|
||||
|
||||
public override bool HasValue(string culture = null, string segment = null) => _sourceValue != null
|
||||
&& (!(_sourceValue is string) || string.IsNullOrWhiteSpace((string) _sourceValue) == false);
|
||||
|
||||
// used to cache the recursive *property* for this property
|
||||
internal string RecurseCacheKey => _recurseCacheKey
|
||||
?? (_recurseCacheKey = CacheKeys.PropertyRecurse(_contentUid, Alias, _isPreviewing));
|
||||
|
||||
// used to cache the CacheValues of this property
|
||||
internal string ValuesCacheKey => _valuesCacheKey
|
||||
?? (_valuesCacheKey = CacheKeys.PropertyCacheValues(_contentUid, Alias, _isPreviewing));
|
||||
@@ -145,7 +144,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// this is always invoked from within a lock, so does not require its own lock
|
||||
private object GetInterValue(string culture, string segment)
|
||||
{
|
||||
if (culture == null && segment == null)
|
||||
if (culture == "" && segment == "")
|
||||
{
|
||||
if (_interInitialized) return _interValue;
|
||||
_interValue = PropertyType.ConvertSourceToInter(_content, _sourceValue, _isPreviewing);
|
||||
@@ -158,7 +157,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
var k = new CompositeStringStringKey(culture, segment);
|
||||
if (!_sourceValues.TryGetValue(k, out var vvalue))
|
||||
_sourceValues[k] = vvalue = new SourceInterValue { Culture = culture, Segment = segment };
|
||||
_sourceValues[k] = vvalue = new SourceInterValue { Culture = culture, Segment = segment, SourceValue = GetSourceValue(culture, segment) };
|
||||
|
||||
if (vvalue.InterInitialized) return vvalue.InterValue;
|
||||
vvalue.InterValue = PropertyType.ConvertSourceToInter(_content, vvalue.SourceValue, _isPreviewing);
|
||||
@@ -168,7 +167,9 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
public override object GetSourceValue(string culture = null, string segment = null)
|
||||
{
|
||||
if (culture == null && segment == null)
|
||||
ContextualizeVariation(ref culture, ref segment);
|
||||
|
||||
if (culture == "" && segment == "")
|
||||
return _sourceValue;
|
||||
|
||||
lock (_locko)
|
||||
@@ -178,8 +179,22 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
}
|
||||
}
|
||||
|
||||
private void ContextualizeVariation(ref string culture, ref string segment)
|
||||
{
|
||||
if (culture != null && segment != null) return;
|
||||
|
||||
// use context values
|
||||
// fixme CultureSegment?
|
||||
var publishedVariationContext = _content.VariationContextAccessor?.VariationContext;
|
||||
if (culture == null) culture = _variations.Has(ContentVariation.CultureNeutral) ? publishedVariationContext?.Culture : "";
|
||||
if (segment == null) segment = _variations.Has(ContentVariation.CultureNeutral) ? publishedVariationContext?.Segment : "";
|
||||
}
|
||||
|
||||
public override object GetValue(string culture = null, string segment = null)
|
||||
{
|
||||
ContextualizeVariation(ref culture, ref segment);
|
||||
|
||||
object value;
|
||||
lock (_locko)
|
||||
{
|
||||
var cacheValues = GetCacheValues(PropertyType.CacheLevel).For(culture, segment);
|
||||
@@ -190,12 +205,16 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
if (cacheValues.ObjectInitialized) return cacheValues.ObjectValue;
|
||||
cacheValues.ObjectValue = PropertyType.ConvertInterToObject(_content, initialCacheLevel, GetInterValue(culture, segment), _isPreviewing);
|
||||
cacheValues.ObjectInitialized = true;
|
||||
return cacheValues.ObjectValue;
|
||||
value = cacheValues.ObjectValue;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public override object GetXPathValue(string culture = null, string segment = null)
|
||||
{
|
||||
ContextualizeVariation(ref culture, ref segment);
|
||||
|
||||
lock (_locko)
|
||||
{
|
||||
var cacheValues = GetCacheValues(PropertyType.CacheLevel).For(culture, segment);
|
||||
@@ -227,7 +246,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// this is always invoked from within a lock, so does not require its own lock
|
||||
public CacheValue For(string culture, string segment)
|
||||
{
|
||||
if (culture == null && segment == null)
|
||||
if (culture == "" && segment == "")
|
||||
return this;
|
||||
|
||||
if (_values == null)
|
||||
|
||||
@@ -18,18 +18,18 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal readonly ContentData _contentData; // internal for ContentNode cloning
|
||||
|
||||
private readonly string _urlName;
|
||||
private IReadOnlyDictionary<string, PublishedCultureName> _cultureNames;
|
||||
private readonly string _urlSegment;
|
||||
|
||||
#region Constructors
|
||||
|
||||
public PublishedContent(ContentNode contentNode, ContentData contentData, IPublishedSnapshotAccessor publishedSnapshotAccessor)
|
||||
public PublishedContent(ContentNode contentNode, ContentData contentData, IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor)
|
||||
{
|
||||
_contentNode = contentNode;
|
||||
_contentData = contentData;
|
||||
_publishedSnapshotAccessor = publishedSnapshotAccessor;
|
||||
VariationContextAccessor = variationContextAccessor;
|
||||
|
||||
_urlName = _contentData.Name.ToUrlSegment();
|
||||
_urlSegment = _contentData.Name.ToUrlSegment();
|
||||
IsPreviewing = _contentData.Published == false;
|
||||
|
||||
var properties = new List<IPublishedProperty>();
|
||||
@@ -70,9 +70,10 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
{
|
||||
_contentNode = contentNode;
|
||||
_publishedSnapshotAccessor = origin._publishedSnapshotAccessor;
|
||||
VariationContextAccessor = origin.VariationContextAccessor;
|
||||
_contentData = origin._contentData;
|
||||
|
||||
_urlName = origin._urlName;
|
||||
_urlSegment = origin._urlSegment;
|
||||
IsPreviewing = origin.IsPreviewing;
|
||||
|
||||
// here is the main benefit: we do not re-create properties so if anything
|
||||
@@ -85,10 +86,11 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
private PublishedContent(PublishedContent origin)
|
||||
{
|
||||
_publishedSnapshotAccessor = origin._publishedSnapshotAccessor;
|
||||
VariationContextAccessor = origin.VariationContextAccessor;
|
||||
_contentNode = origin._contentNode;
|
||||
_contentData = origin._contentData;
|
||||
|
||||
_urlName = origin._urlName;
|
||||
_urlSegment = origin._urlSegment;
|
||||
IsPreviewing = true;
|
||||
|
||||
// clone properties so _isPreviewing is true
|
||||
@@ -152,51 +154,133 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
#endregion
|
||||
|
||||
#region IPublishedContent
|
||||
#region Content Type
|
||||
|
||||
public override int Id => _contentNode.Id;
|
||||
/// <inheritdoc />
|
||||
public override PublishedContentType ContentType => _contentNode.ContentType;
|
||||
|
||||
#endregion
|
||||
|
||||
#region PublishedElement
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Guid Key => _contentNode.Uid;
|
||||
public override int DocumentTypeId => _contentNode.ContentType.Id;
|
||||
public override string DocumentTypeAlias => _contentNode.ContentType.Alias;
|
||||
public override PublishedItemType ItemType => _contentNode.ContentType.ItemType;
|
||||
|
||||
public override string Name => _contentData.Name;
|
||||
public override IReadOnlyDictionary<string, PublishedCultureName> CultureNames
|
||||
#endregion
|
||||
|
||||
#region PublishedContent
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int Id => _contentNode.Id;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!ContentType.Variations.HasFlag(ContentVariation.CultureNeutral))
|
||||
return null;
|
||||
if (!ContentType.Variations.Has(ContentVariation.CultureNeutral)) // fixme CultureSegment?
|
||||
return _contentData.Name;
|
||||
|
||||
if (_cultureNames == null)
|
||||
{
|
||||
var d = new Dictionary<string, PublishedCultureName>(StringComparer.InvariantCultureIgnoreCase);
|
||||
foreach(var c in _contentData.CultureInfos)
|
||||
{
|
||||
d[c.Key] = new PublishedCultureName(c.Value.Name, c.Value.Name.ToUrlSegment());
|
||||
}
|
||||
_cultureNames = d;
|
||||
}
|
||||
return _cultureNames;
|
||||
var culture = VariationContextAccessor.VariationContext.Culture;
|
||||
if (culture == "")
|
||||
return _contentData.Name;
|
||||
|
||||
return Cultures.TryGetValue(culture, out var cultureInfos) ? cultureInfos.Name : null;
|
||||
}
|
||||
}
|
||||
public override int Level => _contentNode.Level;
|
||||
public override string Path => _contentNode.Path;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string UrlSegment
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!ContentType.Variations.Has(ContentVariation.CultureNeutral)) // fixme CultureSegment?
|
||||
return _urlSegment;
|
||||
|
||||
var culture = VariationContextAccessor.VariationContext.Culture;
|
||||
if (culture == "")
|
||||
return _urlSegment;
|
||||
|
||||
return Cultures.TryGetValue(culture, out var cultureInfos) ? cultureInfos.UrlSegment : null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int SortOrder => _contentNode.SortOrder;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int Level => _contentNode.Level;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Path => _contentNode.Path;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int TemplateId => _contentData.TemplateId;
|
||||
|
||||
public override string UrlName => _urlName;
|
||||
|
||||
public override DateTime CreateDate => _contentNode.CreateDate;
|
||||
public override DateTime UpdateDate => _contentData.VersionDate;
|
||||
|
||||
/// <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;
|
||||
|
||||
private IReadOnlyDictionary<string, PublishedCultureInfos> _cultureInfos;
|
||||
|
||||
private static readonly IReadOnlyDictionary<string, PublishedCultureInfos> NoCultureInfos = new Dictionary<string, PublishedCultureInfos>();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override PublishedCultureInfos GetCulture(string culture = null)
|
||||
{
|
||||
// handle context culture
|
||||
if (culture == null)
|
||||
culture = VariationContextAccessor.VariationContext.Culture;
|
||||
|
||||
// no invariant culture infos
|
||||
if (culture == "") return null;
|
||||
|
||||
// get
|
||||
return Cultures.TryGetValue(culture, out var cultureInfos) ? cultureInfos : null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IReadOnlyDictionary<string, PublishedCultureInfos> Cultures
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!ContentType.Variations.Has(ContentVariation.CultureNeutral)) // fixme CultureSegment?
|
||||
return NoCultureInfos;
|
||||
|
||||
if (_cultureInfos != null) return _cultureInfos;
|
||||
|
||||
if (_contentData.CultureInfos == null)
|
||||
throw new Exception("oops: _contentDate.CultureInfos is null.");
|
||||
return _cultureInfos = _contentData.CultureInfos
|
||||
.ToDictionary(x => x.Key, x => new PublishedCultureInfos(x.Key, x.Value.Name, x.Value.Date));
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override PublishedItemType ItemType => _contentNode.ContentType.ItemType;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsDraft => _contentData.Published == false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Tree
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IPublishedContent Parent
|
||||
{
|
||||
get
|
||||
@@ -215,10 +299,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
}
|
||||
}
|
||||
|
||||
private string _childrenCacheKey;
|
||||
|
||||
private string ChildrenCacheKey => _childrenCacheKey ?? (_childrenCacheKey = CacheKeys.PublishedContentChildren(Key, IsPreviewing));
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEnumerable<IPublishedContent> Children
|
||||
{
|
||||
get
|
||||
@@ -232,6 +313,10 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
}
|
||||
}
|
||||
|
||||
private string _childrenCacheKey;
|
||||
|
||||
private string ChildrenCacheKey => _childrenCacheKey ?? (_childrenCacheKey = CacheKeys.PublishedContentChildren(Key, IsPreviewing));
|
||||
|
||||
private IEnumerable<IPublishedContent> GetChildren()
|
||||
{
|
||||
IEnumerable<IPublishedContent> c;
|
||||
@@ -255,8 +340,15 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// Q: perfs-wise, is it better than having the store managed an ordered list
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
|
||||
/// <inheritdoc cref="IPublishedElement.Properties"/>
|
||||
public override IEnumerable<IPublishedProperty> Properties => PropertiesArray;
|
||||
|
||||
/// <inheritdoc cref="IPublishedElement.GetProperty(string)"/>
|
||||
public override IPublishedProperty GetProperty(string alias)
|
||||
{
|
||||
var index = _contentNode.ContentType.GetPropertyIndex(alias);
|
||||
@@ -267,21 +359,6 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
return property;
|
||||
}
|
||||
|
||||
public override IPublishedProperty GetProperty(string alias, bool recurse)
|
||||
{
|
||||
var property = GetProperty(alias);
|
||||
if (recurse == false) return property;
|
||||
|
||||
var cache = GetAppropriateCache();
|
||||
if (cache == null)
|
||||
return base.GetProperty(alias, true);
|
||||
|
||||
var key = ((Property)property).RecurseCacheKey;
|
||||
return (Property)cache.GetCacheItem(key, () => base.GetProperty(alias, true));
|
||||
}
|
||||
|
||||
public override PublishedContentType ContentType => _contentNode.ContentType;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Caching
|
||||
@@ -308,6 +385,9 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
#region Internal
|
||||
|
||||
// used by property
|
||||
internal IVariationContextAccessor VariationContextAccessor { get; }
|
||||
|
||||
// used by navigable content
|
||||
internal IPublishedProperty[] PropertiesArray { get; }
|
||||
|
||||
|
||||
@@ -15,13 +15,13 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
{
|
||||
private readonly IMember _member;
|
||||
|
||||
private PublishedMember(IMember member, ContentNode contentNode, ContentData contentData, IPublishedSnapshotAccessor publishedSnapshotAccessor)
|
||||
: base(contentNode, contentData, publishedSnapshotAccessor)
|
||||
private PublishedMember(IMember member, ContentNode contentNode, ContentData contentData, IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor)
|
||||
: base(contentNode, contentData, publishedSnapshotAccessor, variationContextAccessor)
|
||||
{
|
||||
_member = member;
|
||||
}
|
||||
|
||||
public static IPublishedContent Create(IMember member, PublishedContentType contentType, bool previewing, IPublishedSnapshotAccessor publishedSnapshotAccessor)
|
||||
public static IPublishedContent Create(IMember member, PublishedContentType contentType, bool previewing, IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor)
|
||||
{
|
||||
var d = new ContentData
|
||||
{
|
||||
@@ -37,7 +37,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
member.Level, member.Path, member.SortOrder,
|
||||
member.ParentId,
|
||||
member.CreateDate, member.CreatorId);
|
||||
return new PublishedMember(member, n, d, publishedSnapshotAccessor).CreateModel();
|
||||
return new PublishedMember(member, n, d, publishedSnapshotAccessor, variationContextAccessor).CreateModel();
|
||||
}
|
||||
|
||||
private static Dictionary<string, PropertyData[]> GetPropertyValues(PublishedContentType contentType, IMember member)
|
||||
|
||||
@@ -17,7 +17,6 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
{
|
||||
_service = service;
|
||||
_defaultPreview = defaultPreview;
|
||||
SnapshotCache = new ObjectCacheRuntimeCacheProvider();
|
||||
}
|
||||
|
||||
public class PublishedSnapshotElements : IDisposable
|
||||
@@ -49,7 +48,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
#region Caches
|
||||
|
||||
public ICacheProvider SnapshotCache { get; }
|
||||
public ICacheProvider SnapshotCache => Elements.SnapshotCache;
|
||||
|
||||
public ICacheProvider ElementsCache => Elements.ElementsCache;
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ using Umbraco.Web.Install;
|
||||
using Umbraco.Web.PublishedCache.NuCache.DataSource;
|
||||
using Umbraco.Web.PublishedCache.XmlPublishedCache;
|
||||
using Umbraco.Web.Routing;
|
||||
using Database = Umbraco.Web.PublishedCache.NuCache.DataSource.Database;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache.NuCache
|
||||
{
|
||||
@@ -37,14 +36,14 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
private readonly ServiceContext _serviceContext;
|
||||
private readonly IPublishedContentTypeFactory _publishedContentTypeFactory;
|
||||
private readonly IScopeProvider _scopeProvider;
|
||||
private readonly Database _dataSource;
|
||||
private readonly IDataSource _dataSource;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IDocumentRepository _documentRepository;
|
||||
private readonly IMediaRepository _mediaRepository;
|
||||
private readonly IMemberRepository _memberRepository;
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
private readonly ISiteDomainHelper _siteDomainHelper;
|
||||
private readonly ISystemDefaultCultureProvider _systemDefaultCultureProvider;
|
||||
private readonly IDefaultCultureAccessor _defaultCultureAccessor;
|
||||
|
||||
// volatile because we read it with no lock
|
||||
private volatile bool _isReady;
|
||||
@@ -82,24 +81,25 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
public PublishedSnapshotService(Options options, MainDom mainDom, IRuntimeState runtime,
|
||||
ServiceContext serviceContext, IPublishedContentTypeFactory publishedContentTypeFactory, IdkMap idkMap,
|
||||
IPublishedSnapshotAccessor publishedSnapshotAccessor, ILogger logger, IScopeProvider scopeProvider,
|
||||
IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor,
|
||||
ILogger logger, IScopeProvider scopeProvider,
|
||||
IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository,
|
||||
ISystemDefaultCultureProvider systemDefaultCultureProvider,
|
||||
IGlobalSettings globalSettings, ISiteDomainHelper siteDomainHelper)
|
||||
: base(publishedSnapshotAccessor)
|
||||
IDefaultCultureAccessor defaultCultureAccessor,
|
||||
IDataSource dataSource, IGlobalSettings globalSettings, ISiteDomainHelper siteDomainHelper)
|
||||
: base(publishedSnapshotAccessor, variationContextAccessor)
|
||||
{
|
||||
//if (Interlocked.Increment(ref _singletonCheck) > 1)
|
||||
// throw new Exception("Singleton must be instancianted only once!");
|
||||
|
||||
_serviceContext = serviceContext;
|
||||
_publishedContentTypeFactory = publishedContentTypeFactory;
|
||||
_dataSource = new Database();
|
||||
_dataSource = dataSource;
|
||||
_logger = logger;
|
||||
_scopeProvider = scopeProvider;
|
||||
_documentRepository = documentRepository;
|
||||
_mediaRepository = mediaRepository;
|
||||
_memberRepository = memberRepository;
|
||||
_systemDefaultCultureProvider = systemDefaultCultureProvider;
|
||||
_defaultCultureAccessor = defaultCultureAccessor;
|
||||
_globalSettings = globalSettings;
|
||||
_siteDomainHelper = siteDomainHelper;
|
||||
|
||||
@@ -145,13 +145,13 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// stores are created with a db so they can write to it, but they do not read from it,
|
||||
// stores need to be populated, happens in OnResolutionFrozen which uses _localDbExists to
|
||||
// figure out whether it can read the dbs or it should populate them from sql
|
||||
_contentStore = new ContentStore(publishedSnapshotAccessor, logger, _localContentDb);
|
||||
_mediaStore = new ContentStore(publishedSnapshotAccessor, logger, _localMediaDb);
|
||||
_contentStore = new ContentStore(publishedSnapshotAccessor, variationContextAccessor, logger, _localContentDb);
|
||||
_mediaStore = new ContentStore(publishedSnapshotAccessor, variationContextAccessor, logger, _localMediaDb);
|
||||
}
|
||||
else
|
||||
{
|
||||
_contentStore = new ContentStore(publishedSnapshotAccessor, logger);
|
||||
_mediaStore = new ContentStore(publishedSnapshotAccessor, logger);
|
||||
_contentStore = new ContentStore(publishedSnapshotAccessor, variationContextAccessor, logger);
|
||||
_mediaStore = new ContentStore(publishedSnapshotAccessor, variationContextAccessor, logger);
|
||||
}
|
||||
|
||||
_domainStore = new SnapDictionary<int, Domain>();
|
||||
@@ -173,7 +173,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
try
|
||||
{
|
||||
if (_localDbExists) // fixme?
|
||||
if (_localDbExists)
|
||||
{
|
||||
LockAndLoadContent(LoadContentFromLocalDbLocked);
|
||||
LockAndLoadMedia(LoadMediaFromLocalDbLocked);
|
||||
@@ -333,7 +333,6 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
//private void LoadContent(IContent content)
|
||||
//{
|
||||
// var contentService = _serviceContext.ContentService as ContentService;
|
||||
// if (contentService == null) throw new Exception("oops");
|
||||
// var newest = content;
|
||||
// var published = newest.Published
|
||||
// ? newest
|
||||
@@ -536,7 +535,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
}
|
||||
|
||||
if (draftChanged || publishedChanged)
|
||||
((PublishedSnapshot)CurrentPublishedSnapshot).Resync();
|
||||
((PublishedSnapshot)CurrentPublishedSnapshot)?.Resync();
|
||||
}
|
||||
|
||||
private void NotifyLocked(IEnumerable<ContentCacheRefresher.JsonPayload> payloads, out bool draftChanged, out bool publishedChanged)
|
||||
@@ -544,9 +543,6 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
publishedChanged = false;
|
||||
draftChanged = false;
|
||||
|
||||
if (!(_serviceContext.ContentService is ContentService))
|
||||
throw new Exception("oops");
|
||||
|
||||
// locks:
|
||||
// content (and content types) are read-locked while reading content
|
||||
// contentStore is wlocked (so readable, only no new views)
|
||||
@@ -633,16 +629,13 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
}
|
||||
|
||||
if (anythingChanged)
|
||||
((PublishedSnapshot)CurrentPublishedSnapshot).Resync();
|
||||
((PublishedSnapshot)CurrentPublishedSnapshot)?.Resync();
|
||||
}
|
||||
|
||||
private void NotifyLocked(IEnumerable<MediaCacheRefresher.JsonPayload> payloads, out bool anythingChanged)
|
||||
{
|
||||
anythingChanged = false;
|
||||
|
||||
if (!(_serviceContext.MediaService is MediaService))
|
||||
throw new Exception("oops");
|
||||
|
||||
// locks:
|
||||
// see notes for content cache refresher
|
||||
|
||||
@@ -722,7 +715,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
Notify<IContentType>(_contentStore, payloads, RefreshContentTypesLocked);
|
||||
Notify<IMediaType>(_mediaStore, payloads, RefreshMediaTypesLocked);
|
||||
|
||||
((PublishedSnapshot)CurrentPublishedSnapshot).Resync();
|
||||
((PublishedSnapshot)CurrentPublishedSnapshot)?.Resync();
|
||||
}
|
||||
|
||||
private void Notify<T>(ContentStore store, ContentTypeCacheRefresher.JsonPayload[] payloads, Action<IEnumerable<int>, IEnumerable<int>, IEnumerable<int>, IEnumerable<int>> action)
|
||||
@@ -778,9 +771,6 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// some locking on datatypes
|
||||
_publishedContentTypeFactory.NotifyDataTypeChanges(idsA);
|
||||
|
||||
if (!(_serviceContext.ContentService is ContentService))
|
||||
throw new Exception("oops");
|
||||
|
||||
using (var scope = _scopeProvider.CreateScope())
|
||||
{
|
||||
scope.ReadLock(Constants.Locks.ContentTree);
|
||||
@@ -788,9 +778,6 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
scope.Complete();
|
||||
}
|
||||
|
||||
if (!(_serviceContext.MediaService is MediaService))
|
||||
throw new Exception("oops");
|
||||
|
||||
using (var scope = _scopeProvider.CreateScope())
|
||||
{
|
||||
scope.ReadLock(Constants.Locks.MediaTree);
|
||||
@@ -799,7 +786,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
}
|
||||
}
|
||||
|
||||
((PublishedSnapshot)CurrentPublishedSnapshot).Resync();
|
||||
((PublishedSnapshot)CurrentPublishedSnapshot)?.Resync();
|
||||
}
|
||||
|
||||
public override void Notify(DomainCacheRefresher.JsonPayload[] payloads)
|
||||
@@ -897,9 +884,6 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// contentStore is wlocked (so readable, only no new views)
|
||||
// and it can be wlocked by 1 thread only at a time
|
||||
|
||||
if (!(_serviceContext.ContentService is ContentService))
|
||||
throw new Exception("oops");
|
||||
|
||||
var refreshedIdsA = refreshedIds.ToArray();
|
||||
|
||||
using (var scope = _scopeProvider.CreateScope())
|
||||
@@ -921,9 +905,6 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// mediaStore is wlocked (so readable, only no new views)
|
||||
// and it can be wlocked by 1 thread only at a time
|
||||
|
||||
if (!(_serviceContext.MediaService is MediaService))
|
||||
throw new Exception("oops");
|
||||
|
||||
var refreshedIdsA = refreshedIds.ToArray();
|
||||
|
||||
using (var scope = _scopeProvider.CreateScope())
|
||||
@@ -955,6 +936,9 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
return new PublishedSnapshot(this, preview);
|
||||
}
|
||||
|
||||
// gets a new set of elements
|
||||
// always creates a new set of elements,
|
||||
// even though the underlying elements may not change (store snapshots)
|
||||
public PublishedSnapshot.PublishedSnapshotElements GetElements(bool previewDefault)
|
||||
{
|
||||
// note: using ObjectCacheRuntimeCacheProvider for elements and snapshot caches
|
||||
@@ -996,7 +980,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// a MaxValue to make sure this one runs last, and it should be ok
|
||||
scopeContext.Enlist("Umbraco.Web.PublishedCache.NuCache.PublishedSnapshotService.Resync", () => this, (completed, svc) =>
|
||||
{
|
||||
((PublishedSnapshot)svc.CurrentPublishedSnapshot).Resync();
|
||||
((PublishedSnapshot)svc.CurrentPublishedSnapshot)?.Resync();
|
||||
}, int.MaxValue);
|
||||
}
|
||||
|
||||
@@ -1014,7 +998,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
var memberTypeCache = new PublishedContentTypeCache(null, null, _serviceContext.MemberTypeService, _publishedContentTypeFactory, _logger);
|
||||
|
||||
var defaultCulture = _systemDefaultCultureProvider.DefaultCulture;
|
||||
var defaultCulture = _defaultCultureAccessor.DefaultCulture;
|
||||
var domainCache = new DomainCache(domainSnap, defaultCulture);
|
||||
var domainHelper = new DomainHelper(domainCache, _siteDomainHelper);
|
||||
|
||||
@@ -1022,7 +1006,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
{
|
||||
ContentCache = new ContentCache(previewDefault, contentSnap, snapshotCache, elementsCache, domainHelper, _globalSettings, _serviceContext.LocalizationService),
|
||||
MediaCache = new MediaCache(previewDefault, mediaSnap, snapshotCache, elementsCache),
|
||||
MemberCache = new MemberCache(previewDefault, snapshotCache, _serviceContext.MemberService, _serviceContext.DataTypeService, _serviceContext.LocalizationService, memberTypeCache, PublishedSnapshotAccessor),
|
||||
MemberCache = new MemberCache(previewDefault, snapshotCache, _serviceContext.MemberService, _serviceContext.DataTypeService, _serviceContext.LocalizationService, memberTypeCache, PublishedSnapshotAccessor, VariationContextAccessor),
|
||||
DomainCache = domainCache,
|
||||
SnapshotCache = snapshotCache,
|
||||
ElementsCache = elementsCache
|
||||
@@ -1080,21 +1064,6 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
db.Execute("DELETE FROM cmsContentNu WHERE nodeId=@id", new { id = item.Id });
|
||||
}
|
||||
|
||||
private static readonly string[] PropertiesImpactingAllVersions = { "SortOrder", "ParentId", "Level", "Path", "Trashed" };
|
||||
|
||||
private static bool HasChangesImpactingAllVersions(IContent icontent)
|
||||
{
|
||||
var content = (Content)icontent;
|
||||
|
||||
// UpdateDate will be dirty
|
||||
// Published may be dirty if saving a Published entity
|
||||
// so cannot do this (would always be true):
|
||||
//return content.IsEntityDirty();
|
||||
|
||||
// have to be more precise & specify properties
|
||||
return PropertiesImpactingAllVersions.Any(content.IsPropertyDirty);
|
||||
}
|
||||
|
||||
private void OnContentRefreshedEntity(DocumentRepository sender, DocumentRepository.ScopedEntityEventArgs args)
|
||||
{
|
||||
var db = args.Scope.Database;
|
||||
@@ -1216,7 +1185,6 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
var cultureData = new Dictionary<string, CultureVariation>();
|
||||
|
||||
// fixme refactor!!!
|
||||
var names = content is IContent document
|
||||
? (published
|
||||
? document.PublishNames
|
||||
@@ -1225,7 +1193,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
foreach (var (culture, name) in names)
|
||||
{
|
||||
cultureData[culture] = new CultureVariation { Name = name };
|
||||
cultureData[culture] = new CultureVariation { Name = name, Date = content.GetCultureDate(culture) };
|
||||
}
|
||||
|
||||
//the dictionary that will be serialized
|
||||
|
||||
@@ -87,15 +87,6 @@ namespace Umbraco.Web.PublishedCache
|
||||
|
||||
public override IEnumerable<IPublishedProperty> Properties => _properties;
|
||||
|
||||
public override IPublishedProperty GetProperty(string alias, bool recurse)
|
||||
{
|
||||
if (recurse)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
return GetProperty(alias);
|
||||
}
|
||||
|
||||
public override IPublishedProperty GetProperty(string alias)
|
||||
{
|
||||
return _properties.FirstOrDefault(x => x.Alias.InvariantEquals(alias));
|
||||
@@ -144,13 +135,11 @@ namespace Umbraco.Web.PublishedCache
|
||||
|
||||
public override string Name => _member.Name;
|
||||
|
||||
public override IReadOnlyDictionary<string, PublishedCultureName> CultureNames => throw new NotSupportedException();
|
||||
public override PublishedCultureInfos GetCulture(string culture = null) => throw new NotSupportedException();
|
||||
|
||||
public override string UrlName => throw new NotSupportedException();
|
||||
public override IReadOnlyDictionary<string, PublishedCultureInfos> Cultures => throw new NotSupportedException();
|
||||
|
||||
public override string DocumentTypeAlias => _member.ContentTypeAlias;
|
||||
|
||||
public override int DocumentTypeId => _member.ContentType.Id;
|
||||
public override string UrlSegment => throw new NotSupportedException();
|
||||
|
||||
//TODO: ARGH! need to fix this - this is not good because it uses ApplicationContext.Current
|
||||
public override string WriterName => _member.GetCreatorProfile().Name;
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Web.Cache;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache
|
||||
{
|
||||
abstract class PublishedSnapshotServiceBase : IPublishedSnapshotService
|
||||
{
|
||||
protected PublishedSnapshotServiceBase(IPublishedSnapshotAccessor publishedSnapshotAccessor)
|
||||
protected PublishedSnapshotServiceBase(IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor)
|
||||
{
|
||||
PublishedSnapshotAccessor = publishedSnapshotAccessor;
|
||||
VariationContextAccessor = variationContextAccessor;
|
||||
}
|
||||
|
||||
public IPublishedSnapshotAccessor PublishedSnapshotAccessor { get; }
|
||||
public IVariationContextAccessor VariationContextAccessor { get; }
|
||||
|
||||
// note: NOT setting _publishedSnapshotAccessor.PublishedSnapshot here because it is the
|
||||
// responsibility of the caller to manage what the 'current' facade is
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Xml.XPath;
|
||||
using Examine.LuceneEngine.Providers;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Web.Composing;
|
||||
using Umbraco.Web.Models;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
/// <summary>
|
||||
/// An IPublishedContent that is represented all by a dictionary.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a helper class and definitely not intended for public use, it expects that all of the values required
|
||||
/// to create an IPublishedContent exist in the dictionary by specific aliases.
|
||||
/// </remarks>
|
||||
internal class DictionaryPublishedContent : PublishedContentBase
|
||||
{
|
||||
// note: I'm not sure this class fully complies with IPublishedContent rules especially
|
||||
// I'm not sure that _properties contains all properties including those without a value,
|
||||
// neither that GetProperty will return a property without a value vs. null... @zpqrtbnk
|
||||
|
||||
// List of properties that will appear in the XML and do not match
|
||||
// anything in the ContentType, so they must be ignored.
|
||||
private static readonly string[] IgnoredKeys = { "version", "isDoc" };
|
||||
|
||||
public DictionaryPublishedContent(
|
||||
IReadOnlyDictionary<string, string> valueDictionary,
|
||||
Func<int, IPublishedContent> getParent,
|
||||
Func<int, XPathNavigator, IEnumerable<IPublishedContent>> getChildren,
|
||||
Func<DictionaryPublishedContent, string, IPublishedProperty> getProperty,
|
||||
ICacheProvider cacheProvider,
|
||||
PublishedContentTypeCache contentTypeCache,
|
||||
XPathNavigator nav,
|
||||
bool fromExamine)
|
||||
{
|
||||
if (valueDictionary == null) throw new ArgumentNullException(nameof(valueDictionary));
|
||||
if (getParent == null) throw new ArgumentNullException(nameof(getParent));
|
||||
if (getProperty == null) throw new ArgumentNullException(nameof(getProperty));
|
||||
|
||||
_getParent = new Lazy<IPublishedContent>(() => getParent(ParentId));
|
||||
_getChildren = new Lazy<IEnumerable<IPublishedContent>>(() => getChildren(Id, nav));
|
||||
_getProperty = getProperty;
|
||||
_cacheProvider = cacheProvider;
|
||||
|
||||
LoadedFromExamine = fromExamine;
|
||||
|
||||
ValidateAndSetProperty(valueDictionary, val => _id = Int32.Parse(val), "id", "nodeId", "__NodeId"); //should validate the int!
|
||||
ValidateAndSetProperty(valueDictionary, val => _key = Guid.Parse(val), "key");
|
||||
//ValidateAndSetProperty(valueDictionary, val => _templateId = int.Parse(val), "template", "templateId");
|
||||
ValidateAndSetProperty(valueDictionary, val => _sortOrder = Int32.Parse(val), "sortOrder");
|
||||
ValidateAndSetProperty(valueDictionary, val => _name = val, "nodeName", "__nodeName");
|
||||
ValidateAndSetProperty(valueDictionary, val => _urlName = val, "urlName");
|
||||
ValidateAndSetProperty(valueDictionary, val => _documentTypeAlias = val, "nodeTypeAlias", LuceneIndexer.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");
|
||||
ValidateAndSetProperty(valueDictionary, val => _createDate = ParseDateTimeValue(val), "createDate");
|
||||
ValidateAndSetProperty(valueDictionary, val => _updateDate = ParseDateTimeValue(val), "updateDate");
|
||||
ValidateAndSetProperty(valueDictionary, val => _level = Int32.Parse(val), "level");
|
||||
ValidateAndSetProperty(valueDictionary, val =>
|
||||
{
|
||||
int pId;
|
||||
ParentId = -1;
|
||||
if (Int32.TryParse(val, out pId))
|
||||
{
|
||||
ParentId = pId;
|
||||
}
|
||||
}, "parentID");
|
||||
|
||||
_contentType = contentTypeCache.Get(PublishedItemType.Media, _documentTypeAlias);
|
||||
_properties = new Collection<IPublishedProperty>();
|
||||
|
||||
//handle content type properties
|
||||
//make sure we create them even if there's no value
|
||||
foreach (var propertyType in _contentType.PropertyTypes)
|
||||
{
|
||||
var alias = propertyType.Alias;
|
||||
_keysAdded.Add(alias);
|
||||
string value;
|
||||
const bool isPreviewing = false; // false :: never preview a media
|
||||
var property = valueDictionary.TryGetValue(alias, out value) == false || value == null
|
||||
? new XmlPublishedProperty(propertyType, this, isPreviewing)
|
||||
: new XmlPublishedProperty(propertyType, this, isPreviewing, value);
|
||||
_properties.Add(property);
|
||||
}
|
||||
|
||||
//loop through remaining values that haven't been applied
|
||||
foreach (var i in valueDictionary.Where(x =>
|
||||
_keysAdded.Contains(x.Key) == false // not already processed
|
||||
&& IgnoredKeys.Contains(x.Key) == false)) // not ignorable
|
||||
{
|
||||
if (i.Key.InvariantStartsWith("__"))
|
||||
{
|
||||
// no type for that one, dunno how to convert, drop it
|
||||
//IPublishedProperty property = new PropertyResult(i.Key, i.Value, PropertyResultType.CustomProperty);
|
||||
//_properties.Add(property);
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is a property that does not correspond to anything, ignore and log
|
||||
Current.Logger.Warn<PublishedMediaCache>("Dropping property \"" + i.Key + "\" because it does not belong to the content type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DateTime ParseDateTimeValue(string val)
|
||||
{
|
||||
if (LoadedFromExamine == false)
|
||||
return DateTime.Parse(val);
|
||||
|
||||
//we need to parse the date time using Lucene converters
|
||||
var ticks = Int64.Parse(val);
|
||||
return new DateTime(ticks);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flag to get/set if this was laoded from examine cache
|
||||
/// </summary>
|
||||
internal bool LoadedFromExamine { get; }
|
||||
|
||||
//private readonly Func<DictionaryPublishedContent, IPublishedContent> _getParent;
|
||||
private readonly Lazy<IPublishedContent> _getParent;
|
||||
//private readonly Func<DictionaryPublishedContent, IEnumerable<IPublishedContent>> _getChildren;
|
||||
private readonly Lazy<IEnumerable<IPublishedContent>> _getChildren;
|
||||
private readonly Func<DictionaryPublishedContent, string, IPublishedProperty> _getProperty;
|
||||
private readonly ICacheProvider _cacheProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Returns 'Media' as the item type
|
||||
/// </summary>
|
||||
public override PublishedItemType ItemType => PublishedItemType.Media;
|
||||
|
||||
public override IPublishedContent Parent => _getParent.Value;
|
||||
|
||||
public int ParentId { get; private set; }
|
||||
|
||||
public override int Id => _id;
|
||||
|
||||
public override Guid Key => _key;
|
||||
|
||||
public override int TemplateId => 0;
|
||||
|
||||
public override int SortOrder => _sortOrder;
|
||||
|
||||
public override string Name => _name;
|
||||
|
||||
public override PublishedCultureInfos GetCulture(string culture = null) => throw new NotSupportedException();
|
||||
|
||||
public override IReadOnlyDictionary<string, PublishedCultureInfos> Cultures => throw new NotSupportedException();
|
||||
|
||||
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;
|
||||
|
||||
public override string Path => _path;
|
||||
|
||||
public override DateTime CreateDate => _createDate;
|
||||
|
||||
public override DateTime UpdateDate => _updateDate;
|
||||
|
||||
public override int Level => _level;
|
||||
|
||||
public override bool IsDraft => false;
|
||||
|
||||
public override IEnumerable<IPublishedProperty> Properties => _properties;
|
||||
|
||||
public override IEnumerable<IPublishedContent> Children => _getChildren.Value;
|
||||
|
||||
public override IPublishedProperty GetProperty(string alias)
|
||||
{
|
||||
return _getProperty(this, alias);
|
||||
}
|
||||
|
||||
public override PublishedContentType ContentType => _contentType;
|
||||
|
||||
private readonly List<string> _keysAdded = new List<string>();
|
||||
private int _id;
|
||||
private Guid _key;
|
||||
//private int _templateId;
|
||||
private int _sortOrder;
|
||||
private string _name;
|
||||
private string _urlName;
|
||||
private string _documentTypeAlias;
|
||||
private int _documentTypeId;
|
||||
//private string _writerName;
|
||||
private string _creatorName;
|
||||
//private int _writerId;
|
||||
private int _creatorId;
|
||||
private string _path;
|
||||
private DateTime _createDate;
|
||||
private DateTime _updateDate;
|
||||
//private Guid _version;
|
||||
private int _level;
|
||||
private readonly ICollection<IPublishedProperty> _properties;
|
||||
private readonly PublishedContentType _contentType;
|
||||
|
||||
private void ValidateAndSetProperty(IReadOnlyDictionary<string, string> valueDictionary, Action<string> setProperty, params string[] potentialKeys)
|
||||
{
|
||||
var key = potentialKeys.FirstOrDefault(x => valueDictionary.ContainsKey(x) && valueDictionary[x] != null);
|
||||
if (key == null)
|
||||
{
|
||||
throw new FormatException("The valueDictionary is not formatted correctly and is missing any of the '" + String.Join(",", potentialKeys) + "' elements");
|
||||
}
|
||||
|
||||
setProperty(valueDictionary[key]);
|
||||
_keysAdded.Add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,10 +11,10 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
private readonly IDomainService _domainService;
|
||||
|
||||
public DomainCache(IDomainService domainService, ISystemDefaultCultureProvider systemDefaultCultureProvider)
|
||||
public DomainCache(IDomainService domainService, IDefaultCultureAccessor defaultCultureAccessor)
|
||||
{
|
||||
_domainService = domainService;
|
||||
DefaultCulture = systemDefaultCultureProvider.DefaultCulture;
|
||||
DefaultCulture = defaultCultureAccessor.DefaultCulture;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -266,7 +266,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
while (hasDomains == false && n != null) // n is null at root
|
||||
{
|
||||
// get the url
|
||||
var urlName = n.UrlName;
|
||||
var urlName = n.UrlSegment;
|
||||
pathParts.Add(urlName);
|
||||
|
||||
// move to parent node
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Xml.XPath;
|
||||
using Examine;
|
||||
using Examine.LuceneEngine.Providers;
|
||||
using Examine.LuceneEngine.SearchCriteria;
|
||||
using Examine.Providers;
|
||||
using Lucene.Net.Store;
|
||||
@@ -16,7 +14,6 @@ using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Xml;
|
||||
using Umbraco.Web.Models;
|
||||
using Umbraco.Examine;
|
||||
using umbraco;
|
||||
using Umbraco.Core.Cache;
|
||||
@@ -607,230 +604,6 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
return mediaList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An IPublishedContent that is represented all by a dictionary.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a helper class and definitely not intended for public use, it expects that all of the values required
|
||||
/// to create an IPublishedContent exist in the dictionary by specific aliases.
|
||||
/// </remarks>
|
||||
internal class DictionaryPublishedContent : PublishedContentBase
|
||||
{
|
||||
// note: I'm not sure this class fully complies with IPublishedContent rules especially
|
||||
// I'm not sure that _properties contains all properties including those without a value,
|
||||
// neither that GetProperty will return a property without a value vs. null... @zpqrtbnk
|
||||
|
||||
// List of properties that will appear in the XML and do not match
|
||||
// anything in the ContentType, so they must be ignored.
|
||||
private static readonly string[] IgnoredKeys = { "version", "isDoc" };
|
||||
|
||||
public DictionaryPublishedContent(
|
||||
IReadOnlyDictionary<string, string> valueDictionary,
|
||||
Func<int, IPublishedContent> getParent,
|
||||
Func<int, XPathNavigator, IEnumerable<IPublishedContent>> getChildren,
|
||||
Func<DictionaryPublishedContent, string, IPublishedProperty> getProperty,
|
||||
ICacheProvider cacheProvider,
|
||||
PublishedContentTypeCache contentTypeCache,
|
||||
XPathNavigator nav,
|
||||
bool fromExamine)
|
||||
{
|
||||
if (valueDictionary == null) throw new ArgumentNullException(nameof(valueDictionary));
|
||||
if (getParent == null) throw new ArgumentNullException(nameof(getParent));
|
||||
if (getProperty == null) throw new ArgumentNullException(nameof(getProperty));
|
||||
|
||||
_getParent = new Lazy<IPublishedContent>(() => getParent(ParentId));
|
||||
_getChildren = new Lazy<IEnumerable<IPublishedContent>>(() => getChildren(Id, nav));
|
||||
_getProperty = getProperty;
|
||||
_cacheProvider = cacheProvider;
|
||||
|
||||
LoadedFromExamine = fromExamine;
|
||||
|
||||
ValidateAndSetProperty(valueDictionary, val => _id = int.Parse(val), "id", "nodeId", "__NodeId"); //should validate the int!
|
||||
ValidateAndSetProperty(valueDictionary, val => _key = Guid.Parse(val), "key");
|
||||
//ValidateAndSetProperty(valueDictionary, val => _templateId = int.Parse(val), "template", "templateId");
|
||||
ValidateAndSetProperty(valueDictionary, val => _sortOrder = int.Parse(val), "sortOrder");
|
||||
ValidateAndSetProperty(valueDictionary, val => _name = val, "nodeName", "__nodeName");
|
||||
ValidateAndSetProperty(valueDictionary, val => _urlName = val, "urlName");
|
||||
ValidateAndSetProperty(valueDictionary, val => _documentTypeAlias = val, "nodeTypeAlias", LuceneIndexer.ItemTypeFieldName);
|
||||
ValidateAndSetProperty(valueDictionary, val => _documentTypeId = int.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 = int.Parse(val), "creatorID", "writerID"); //this is a bit of a hack fix for: U4-1132
|
||||
ValidateAndSetProperty(valueDictionary, val => _path = val, "path", "__Path");
|
||||
ValidateAndSetProperty(valueDictionary, val => _createDate = ParseDateTimeValue(val), "createDate");
|
||||
ValidateAndSetProperty(valueDictionary, val => _updateDate = ParseDateTimeValue(val), "updateDate");
|
||||
ValidateAndSetProperty(valueDictionary, val => _level = int.Parse(val), "level");
|
||||
ValidateAndSetProperty(valueDictionary, val =>
|
||||
{
|
||||
int pId;
|
||||
ParentId = -1;
|
||||
if (int.TryParse(val, out pId))
|
||||
{
|
||||
ParentId = pId;
|
||||
}
|
||||
}, "parentID");
|
||||
|
||||
_contentType = contentTypeCache.Get(PublishedItemType.Media, _documentTypeAlias);
|
||||
_properties = new Collection<IPublishedProperty>();
|
||||
|
||||
//handle content type properties
|
||||
//make sure we create them even if there's no value
|
||||
foreach (var propertyType in _contentType.PropertyTypes)
|
||||
{
|
||||
var alias = propertyType.Alias;
|
||||
_keysAdded.Add(alias);
|
||||
string value;
|
||||
const bool isPreviewing = false; // false :: never preview a media
|
||||
var property = valueDictionary.TryGetValue(alias, out value) == false || value == null
|
||||
? new XmlPublishedProperty(propertyType, this, isPreviewing)
|
||||
: new XmlPublishedProperty(propertyType, this, isPreviewing, value);
|
||||
_properties.Add(property);
|
||||
}
|
||||
|
||||
//loop through remaining values that haven't been applied
|
||||
foreach (var i in valueDictionary.Where(x =>
|
||||
_keysAdded.Contains(x.Key) == false // not already processed
|
||||
&& IgnoredKeys.Contains(x.Key) == false)) // not ignorable
|
||||
{
|
||||
if (i.Key.InvariantStartsWith("__"))
|
||||
{
|
||||
// no type for that one, dunno how to convert, drop it
|
||||
//IPublishedProperty property = new PropertyResult(i.Key, i.Value, PropertyResultType.CustomProperty);
|
||||
//_properties.Add(property);
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is a property that does not correspond to anything, ignore and log
|
||||
Current.Logger.Warn<PublishedMediaCache>("Dropping property \"" + i.Key + "\" because it does not belong to the content type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DateTime ParseDateTimeValue(string val)
|
||||
{
|
||||
if (LoadedFromExamine == false)
|
||||
return DateTime.Parse(val);
|
||||
|
||||
//we need to parse the date time using Lucene converters
|
||||
var ticks = long.Parse(val);
|
||||
return new DateTime(ticks);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flag to get/set if this was laoded from examine cache
|
||||
/// </summary>
|
||||
internal bool LoadedFromExamine { get; }
|
||||
|
||||
//private readonly Func<DictionaryPublishedContent, IPublishedContent> _getParent;
|
||||
private readonly Lazy<IPublishedContent> _getParent;
|
||||
//private readonly Func<DictionaryPublishedContent, IEnumerable<IPublishedContent>> _getChildren;
|
||||
private readonly Lazy<IEnumerable<IPublishedContent>> _getChildren;
|
||||
private readonly Func<DictionaryPublishedContent, string, IPublishedProperty> _getProperty;
|
||||
private readonly ICacheProvider _cacheProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Returns 'Media' as the item type
|
||||
/// </summary>
|
||||
public override PublishedItemType ItemType => PublishedItemType.Media;
|
||||
|
||||
public override IPublishedContent Parent => _getParent.Value;
|
||||
|
||||
public int ParentId { get; private set; }
|
||||
|
||||
public override int Id => _id;
|
||||
|
||||
public override Guid Key => _key;
|
||||
|
||||
public override int TemplateId => 0;
|
||||
|
||||
public override int SortOrder => _sortOrder;
|
||||
|
||||
public override string Name => _name;
|
||||
|
||||
public override IReadOnlyDictionary<string, PublishedCultureName> CultureNames => throw new NotSupportedException();
|
||||
|
||||
public override string UrlName => _urlName;
|
||||
|
||||
public override string DocumentTypeAlias => _documentTypeAlias;
|
||||
|
||||
public override int DocumentTypeId => _documentTypeId;
|
||||
|
||||
public override string WriterName => _creatorName;
|
||||
|
||||
public override string CreatorName => _creatorName;
|
||||
|
||||
public override int WriterId => _creatorId;
|
||||
|
||||
public override int CreatorId => _creatorId;
|
||||
|
||||
public override string Path => _path;
|
||||
|
||||
public override DateTime CreateDate => _createDate;
|
||||
|
||||
public override DateTime UpdateDate => _updateDate;
|
||||
|
||||
public override int Level => _level;
|
||||
|
||||
public override bool IsDraft => false;
|
||||
|
||||
public override IEnumerable<IPublishedProperty> Properties => _properties;
|
||||
|
||||
public override IEnumerable<IPublishedContent> Children => _getChildren.Value;
|
||||
|
||||
public override IPublishedProperty GetProperty(string alias)
|
||||
{
|
||||
return _getProperty(this, alias);
|
||||
}
|
||||
|
||||
public override PublishedContentType ContentType => _contentType;
|
||||
|
||||
// override to implement cache
|
||||
// cache at context level, ie once for the whole request
|
||||
// but cache is not shared by requests because we wouldn't know how to clear it
|
||||
public override IPublishedProperty GetProperty(string alias, bool recurse)
|
||||
{
|
||||
if (recurse == false) return GetProperty(alias);
|
||||
|
||||
var key = $"XmlPublishedCache.PublishedMediaCache:RecursiveProperty-{Id}-{alias.ToLowerInvariant()}";
|
||||
var cacheProvider = _cacheProvider;
|
||||
return cacheProvider.GetCacheItem<IPublishedProperty>(key, () => base.GetProperty(alias, true));
|
||||
}
|
||||
|
||||
private readonly List<string> _keysAdded = new List<string>();
|
||||
private int _id;
|
||||
private Guid _key;
|
||||
//private int _templateId;
|
||||
private int _sortOrder;
|
||||
private string _name;
|
||||
private string _urlName;
|
||||
private string _documentTypeAlias;
|
||||
private int _documentTypeId;
|
||||
//private string _writerName;
|
||||
private string _creatorName;
|
||||
//private int _writerId;
|
||||
private int _creatorId;
|
||||
private string _path;
|
||||
private DateTime _createDate;
|
||||
private DateTime _updateDate;
|
||||
//private Guid _version;
|
||||
private int _level;
|
||||
private readonly ICollection<IPublishedProperty> _properties;
|
||||
private readonly PublishedContentType _contentType;
|
||||
|
||||
private void ValidateAndSetProperty(IReadOnlyDictionary<string, string> valueDictionary, Action<string> setProperty, params string[] potentialKeys)
|
||||
{
|
||||
var key = potentialKeys.FirstOrDefault(x => valueDictionary.ContainsKey(x) && valueDictionary[x] != null);
|
||||
if (key == null)
|
||||
{
|
||||
throw new FormatException("The valueDictionary is not formatted correctly and is missing any of the '" + string.Join(",", potentialKeys) + "' elements");
|
||||
}
|
||||
|
||||
setProperty(valueDictionary[key]);
|
||||
_keysAdded.Add(key);
|
||||
}
|
||||
}
|
||||
|
||||
internal void Resync()
|
||||
{
|
||||
// clear recursive properties cached by XmlPublishedContent.GetProperty
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
private readonly IUserService _userService;
|
||||
private readonly ICacheProvider _requestCache;
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
private readonly ISystemDefaultCultureProvider _systemDefaultCultureProvider;
|
||||
private readonly IDefaultCultureAccessor _defaultCultureAccessor;
|
||||
private readonly ISiteDomainHelper _siteDomainHelper;
|
||||
|
||||
#region Constructors
|
||||
@@ -43,17 +43,18 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
IScopeProvider scopeProvider,
|
||||
ICacheProvider requestCache,
|
||||
IEnumerable<IUrlSegmentProvider> segmentProviders,
|
||||
IPublishedSnapshotAccessor publishedSnapshotAccessor,
|
||||
IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor,
|
||||
IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository,
|
||||
ISystemDefaultCultureProvider systemDefaultCultureProvider,
|
||||
IDefaultCultureAccessor defaultCultureAccessor,
|
||||
ILogger logger,
|
||||
IGlobalSettings globalSettings,
|
||||
ISiteDomainHelper siteDomainHelper,
|
||||
MainDom mainDom,
|
||||
bool testing = false, bool enableRepositoryEvents = true)
|
||||
: this(serviceContext, publishedContentTypeFactory, scopeProvider, requestCache, segmentProviders, publishedSnapshotAccessor,
|
||||
: this(serviceContext, publishedContentTypeFactory, scopeProvider, requestCache, segmentProviders,
|
||||
publishedSnapshotAccessor, variationContextAccessor,
|
||||
documentRepository, mediaRepository, memberRepository,
|
||||
systemDefaultCultureProvider,
|
||||
defaultCultureAccessor,
|
||||
logger, globalSettings, siteDomainHelper, null, mainDom, testing, enableRepositoryEvents)
|
||||
{ }
|
||||
|
||||
@@ -62,18 +63,19 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
IPublishedContentTypeFactory publishedContentTypeFactory,
|
||||
IScopeProvider scopeProvider,
|
||||
ICacheProvider requestCache,
|
||||
IPublishedSnapshotAccessor publishedSnapshotAccessor,
|
||||
IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor,
|
||||
IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository,
|
||||
ISystemDefaultCultureProvider systemDefaultCultureProvider,
|
||||
IDefaultCultureAccessor defaultCultureAccessor,
|
||||
ILogger logger,
|
||||
IGlobalSettings globalSettings,
|
||||
ISiteDomainHelper siteDomainHelper,
|
||||
PublishedContentTypeCache contentTypeCache,
|
||||
MainDom mainDom,
|
||||
bool testing, bool enableRepositoryEvents)
|
||||
: this(serviceContext, publishedContentTypeFactory, scopeProvider, requestCache, Enumerable.Empty<IUrlSegmentProvider>(), publishedSnapshotAccessor,
|
||||
: this(serviceContext, publishedContentTypeFactory, scopeProvider, requestCache, Enumerable.Empty<IUrlSegmentProvider>(),
|
||||
publishedSnapshotAccessor, variationContextAccessor,
|
||||
documentRepository, mediaRepository, memberRepository,
|
||||
systemDefaultCultureProvider,
|
||||
defaultCultureAccessor,
|
||||
logger, globalSettings, siteDomainHelper, contentTypeCache, mainDom, testing, enableRepositoryEvents)
|
||||
{ }
|
||||
|
||||
@@ -82,16 +84,16 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
IScopeProvider scopeProvider,
|
||||
ICacheProvider requestCache,
|
||||
IEnumerable<IUrlSegmentProvider> segmentProviders,
|
||||
IPublishedSnapshotAccessor publishedSnapshotAccessor,
|
||||
IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor,
|
||||
IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository,
|
||||
ISystemDefaultCultureProvider systemDefaultCultureProvider,
|
||||
IDefaultCultureAccessor defaultCultureAccessor,
|
||||
ILogger logger,
|
||||
IGlobalSettings globalSettings,
|
||||
ISiteDomainHelper siteDomainHelper,
|
||||
PublishedContentTypeCache contentTypeCache,
|
||||
MainDom mainDom,
|
||||
bool testing, bool enableRepositoryEvents)
|
||||
: base(publishedSnapshotAccessor)
|
||||
: base(publishedSnapshotAccessor, variationContextAccessor)
|
||||
{
|
||||
_routesCache = new RoutesCache();
|
||||
_publishedContentTypeFactory = publishedContentTypeFactory;
|
||||
@@ -106,7 +108,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
_memberService = serviceContext.MemberService;
|
||||
_mediaService = serviceContext.MediaService;
|
||||
_userService = serviceContext.UserService;
|
||||
_systemDefaultCultureProvider = systemDefaultCultureProvider;
|
||||
_defaultCultureAccessor = defaultCultureAccessor;
|
||||
|
||||
_requestCache = requestCache;
|
||||
_globalSettings = globalSettings;
|
||||
@@ -151,7 +153,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
// the current caches, but that would mean creating an extra cache (StaticCache
|
||||
// probably) so better use RequestCache.
|
||||
|
||||
var domainCache = new DomainCache(_domainService, _systemDefaultCultureProvider);
|
||||
var domainCache = new DomainCache(_domainService, _defaultCultureAccessor);
|
||||
|
||||
return new PublishedSnapshot(
|
||||
new PublishedContentCache(_xmlStore, domainCache, _requestCache, _globalSettings, _siteDomainHelper, _contentTypeCache, _routesCache, previewToken),
|
||||
|
||||
@@ -29,10 +29,11 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
factory.GetInstance<CacheHelper>().RequestCache,
|
||||
factory.GetInstance<UrlSegmentProviderCollection>(),
|
||||
factory.GetInstance<IPublishedSnapshotAccessor>(),
|
||||
factory.GetInstance<IVariationContextAccessor>(),
|
||||
factory.GetInstance<IDocumentRepository>(),
|
||||
factory.GetInstance<IMediaRepository>(),
|
||||
factory.GetInstance<IMemberRepository>(),
|
||||
factory.GetInstance<ISystemDefaultCultureProvider>(),
|
||||
factory.GetInstance<IDefaultCultureAccessor>(),
|
||||
factory.GetInstance<ILogger>(),
|
||||
factory.GetInstance<IGlobalSettings>(),
|
||||
factory.GetInstance<ISiteDomainHelper>(),
|
||||
|
||||
@@ -79,20 +79,6 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
return _properties.TryGetValue(alias, out property) ? property : null;
|
||||
}
|
||||
|
||||
// override to implement cache
|
||||
// cache at context level, ie once for the whole request
|
||||
// but cache is not shared by requests because we wouldn't know how to clear it
|
||||
public override IPublishedProperty GetProperty(string alias, bool recurse)
|
||||
{
|
||||
if (recurse == false) return GetProperty(alias);
|
||||
|
||||
var key = $"XmlPublishedCache.PublishedContentCache:RecursiveProperty-{Id}-{alias.ToLowerInvariant()}";
|
||||
var cacheProvider = _cacheProvider;
|
||||
return cacheProvider.GetCacheItem<IPublishedProperty>(key, () => base.GetProperty(alias, true));
|
||||
|
||||
// note: cleared by PublishedContentCache.Resync - any change here must be applied there
|
||||
}
|
||||
|
||||
public override PublishedItemType ItemType => PublishedItemType.Content;
|
||||
|
||||
public override IPublishedContent Parent
|
||||
@@ -150,25 +136,9 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
}
|
||||
}
|
||||
|
||||
public override IReadOnlyDictionary<string, PublishedCultureName> CultureNames => throw new NotSupportedException();
|
||||
public override PublishedCultureInfos GetCulture(string culture = null) => throw new NotSupportedException();
|
||||
|
||||
public override string DocumentTypeAlias
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _docTypeAlias;
|
||||
}
|
||||
}
|
||||
|
||||
public override int DocumentTypeId
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _docTypeId;
|
||||
}
|
||||
}
|
||||
public override IReadOnlyDictionary<string, PublishedCultureInfos> Cultures => throw new NotSupportedException();
|
||||
|
||||
public override string WriterName
|
||||
{
|
||||
@@ -233,7 +203,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
}
|
||||
}
|
||||
|
||||
public override string UrlName
|
||||
public override string UrlSegment
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user