2017-10-17 17:43:15 +02:00
|
|
|
|
using System.Collections.Generic;
|
2016-05-26 19:20:33 +02:00
|
|
|
|
using System.Linq;
|
2016-05-26 17:12:04 +02:00
|
|
|
|
using Umbraco.Core;
|
|
|
|
|
|
using Umbraco.Core.Cache;
|
2018-04-06 13:51:54 +10:00
|
|
|
|
using Umbraco.Core.Configuration;
|
2016-06-30 10:30:43 +02:00
|
|
|
|
using Umbraco.Core.IO;
|
2016-09-11 19:57:33 +02:00
|
|
|
|
using Umbraco.Core.Logging;
|
2016-05-26 17:12:04 +02:00
|
|
|
|
using Umbraco.Core.Models;
|
|
|
|
|
|
using Umbraco.Core.Models.Membership;
|
2016-06-29 15:28:40 +02:00
|
|
|
|
using Umbraco.Core.Models.PublishedContent;
|
2017-12-14 17:04:44 +01:00
|
|
|
|
using Umbraco.Core.Persistence.Repositories;
|
2017-05-12 14:49:44 +02:00
|
|
|
|
using Umbraco.Core.Scoping;
|
2016-05-26 17:12:04 +02:00
|
|
|
|
using Umbraco.Core.Services;
|
|
|
|
|
|
using Umbraco.Core.Strings;
|
|
|
|
|
|
using Umbraco.Web.Cache;
|
2018-04-24 13:07:18 +10:00
|
|
|
|
using Umbraco.Web.Routing;
|
2016-05-26 17:12:04 +02:00
|
|
|
|
|
|
|
|
|
|
namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
2017-10-31 12:48:24 +01:00
|
|
|
|
/// Implements a published snapshot service.
|
2016-05-26 17:12:04 +02:00
|
|
|
|
/// </summary>
|
2017-10-31 12:48:24 +01:00
|
|
|
|
internal class PublishedSnapshotService : PublishedSnapshotServiceBase
|
2016-05-26 17:12:04 +02:00
|
|
|
|
{
|
|
|
|
|
|
private readonly XmlStore _xmlStore;
|
|
|
|
|
|
private readonly RoutesCache _routesCache;
|
2018-02-09 14:34:28 +01:00
|
|
|
|
private readonly IPublishedContentTypeFactory _publishedContentTypeFactory;
|
2016-05-26 17:12:04 +02:00
|
|
|
|
private readonly PublishedContentTypeCache _contentTypeCache;
|
|
|
|
|
|
private readonly IDomainService _domainService;
|
|
|
|
|
|
private readonly IMemberService _memberService;
|
|
|
|
|
|
private readonly IMediaService _mediaService;
|
2016-07-20 12:44:15 +02:00
|
|
|
|
private readonly IUserService _userService;
|
2016-05-26 17:12:04 +02:00
|
|
|
|
private readonly ICacheProvider _requestCache;
|
2018-04-06 13:51:54 +10:00
|
|
|
|
private readonly IGlobalSettings _globalSettings;
|
2018-04-30 21:29:49 +02:00
|
|
|
|
private readonly IDefaultCultureAccessor _defaultCultureAccessor;
|
2018-04-24 13:07:18 +10:00
|
|
|
|
private readonly ISiteDomainHelper _siteDomainHelper;
|
2016-05-26 17:12:04 +02:00
|
|
|
|
|
|
|
|
|
|
#region Constructors
|
|
|
|
|
|
|
2016-05-26 19:20:33 +02:00
|
|
|
|
// used in WebBootManager + tests
|
2017-10-31 12:48:24 +01:00
|
|
|
|
public PublishedSnapshotService(ServiceContext serviceContext,
|
2017-10-17 17:43:15 +02:00
|
|
|
|
IPublishedContentTypeFactory publishedContentTypeFactory,
|
2017-05-30 19:41:37 +02:00
|
|
|
|
IScopeProvider scopeProvider,
|
2017-07-20 11:21:28 +02:00
|
|
|
|
ICacheProvider requestCache,
|
2016-05-26 19:20:33 +02:00
|
|
|
|
IEnumerable<IUrlSegmentProvider> segmentProviders,
|
2018-04-30 21:29:49 +02:00
|
|
|
|
IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor,
|
2017-12-14 17:04:44 +01:00
|
|
|
|
IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository,
|
2018-04-30 21:29:49 +02:00
|
|
|
|
IDefaultCultureAccessor defaultCultureAccessor,
|
2016-09-11 19:57:33 +02:00
|
|
|
|
ILogger logger,
|
2018-04-06 13:51:54 +10:00
|
|
|
|
IGlobalSettings globalSettings,
|
2018-04-24 13:07:18 +10:00
|
|
|
|
ISiteDomainHelper siteDomainHelper,
|
2016-09-01 19:06:08 +02:00
|
|
|
|
MainDom mainDom,
|
2016-05-26 19:20:33 +02:00
|
|
|
|
bool testing = false, bool enableRepositoryEvents = true)
|
2018-04-18 19:46:47 +02:00
|
|
|
|
: this(serviceContext, publishedContentTypeFactory, scopeProvider, requestCache, segmentProviders,
|
2018-04-30 21:29:49 +02:00
|
|
|
|
publishedSnapshotAccessor, variationContextAccessor,
|
2017-12-14 17:04:44 +01:00
|
|
|
|
documentRepository, mediaRepository, memberRepository,
|
2018-04-30 21:29:49 +02:00
|
|
|
|
defaultCultureAccessor,
|
2018-04-24 13:07:18 +10:00
|
|
|
|
logger, globalSettings, siteDomainHelper, null, mainDom, testing, enableRepositoryEvents)
|
2016-05-26 17:12:04 +02:00
|
|
|
|
{ }
|
|
|
|
|
|
|
2016-05-26 19:20:33 +02:00
|
|
|
|
// used in some tests
|
2017-10-31 12:48:24 +01:00
|
|
|
|
internal PublishedSnapshotService(ServiceContext serviceContext,
|
2017-10-17 17:43:15 +02:00
|
|
|
|
IPublishedContentTypeFactory publishedContentTypeFactory,
|
2017-05-30 19:41:37 +02:00
|
|
|
|
IScopeProvider scopeProvider,
|
2016-05-26 19:20:33 +02:00
|
|
|
|
ICacheProvider requestCache,
|
2018-04-30 21:29:49 +02:00
|
|
|
|
IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor,
|
2017-12-14 17:04:44 +01:00
|
|
|
|
IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository,
|
2018-04-30 21:29:49 +02:00
|
|
|
|
IDefaultCultureAccessor defaultCultureAccessor,
|
2016-09-11 19:57:33 +02:00
|
|
|
|
ILogger logger,
|
2018-04-06 13:51:54 +10:00
|
|
|
|
IGlobalSettings globalSettings,
|
2018-04-24 13:07:18 +10:00
|
|
|
|
ISiteDomainHelper siteDomainHelper,
|
2017-07-20 11:21:28 +02:00
|
|
|
|
PublishedContentTypeCache contentTypeCache,
|
2016-09-01 19:06:08 +02:00
|
|
|
|
MainDom mainDom,
|
2016-05-26 17:12:04 +02:00
|
|
|
|
bool testing, bool enableRepositoryEvents)
|
2018-04-18 19:46:47 +02:00
|
|
|
|
: this(serviceContext, publishedContentTypeFactory, scopeProvider, requestCache, Enumerable.Empty<IUrlSegmentProvider>(),
|
2018-04-30 21:29:49 +02:00
|
|
|
|
publishedSnapshotAccessor, variationContextAccessor,
|
2017-12-14 17:04:44 +01:00
|
|
|
|
documentRepository, mediaRepository, memberRepository,
|
2018-04-30 21:29:49 +02:00
|
|
|
|
defaultCultureAccessor,
|
2018-04-24 13:07:18 +10:00
|
|
|
|
logger, globalSettings, siteDomainHelper, contentTypeCache, mainDom, testing, enableRepositoryEvents)
|
2016-05-26 17:12:04 +02:00
|
|
|
|
{ }
|
|
|
|
|
|
|
2017-10-31 12:48:24 +01:00
|
|
|
|
private PublishedSnapshotService(ServiceContext serviceContext,
|
2017-10-17 17:43:15 +02:00
|
|
|
|
IPublishedContentTypeFactory publishedContentTypeFactory,
|
2017-05-30 19:41:37 +02:00
|
|
|
|
IScopeProvider scopeProvider,
|
2016-05-26 19:20:33 +02:00
|
|
|
|
ICacheProvider requestCache,
|
|
|
|
|
|
IEnumerable<IUrlSegmentProvider> segmentProviders,
|
2018-04-30 21:29:49 +02:00
|
|
|
|
IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor,
|
2017-12-14 17:04:44 +01:00
|
|
|
|
IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository,
|
2018-04-30 21:29:49 +02:00
|
|
|
|
IDefaultCultureAccessor defaultCultureAccessor,
|
2016-09-11 19:57:33 +02:00
|
|
|
|
ILogger logger,
|
2018-04-06 13:51:54 +10:00
|
|
|
|
IGlobalSettings globalSettings,
|
2018-04-24 13:07:18 +10:00
|
|
|
|
ISiteDomainHelper siteDomainHelper,
|
2017-07-20 11:21:28 +02:00
|
|
|
|
PublishedContentTypeCache contentTypeCache,
|
2016-09-01 19:06:08 +02:00
|
|
|
|
MainDom mainDom,
|
2016-05-26 19:20:33 +02:00
|
|
|
|
bool testing, bool enableRepositoryEvents)
|
2018-04-30 21:29:49 +02:00
|
|
|
|
: base(publishedSnapshotAccessor, variationContextAccessor)
|
2016-05-26 17:12:04 +02:00
|
|
|
|
{
|
|
|
|
|
|
_routesCache = new RoutesCache();
|
2018-02-09 14:34:28 +01:00
|
|
|
|
_publishedContentTypeFactory = publishedContentTypeFactory;
|
2016-05-26 17:12:04 +02:00
|
|
|
|
_contentTypeCache = contentTypeCache
|
2017-10-17 17:43:15 +02:00
|
|
|
|
?? new PublishedContentTypeCache(serviceContext.ContentTypeService, serviceContext.MediaTypeService, serviceContext.MemberTypeService, publishedContentTypeFactory, logger);
|
2016-05-26 17:12:04 +02:00
|
|
|
|
|
2018-04-06 13:51:54 +10:00
|
|
|
|
_xmlStore = new XmlStore(serviceContext, scopeProvider, _routesCache,
|
|
|
|
|
|
_contentTypeCache, segmentProviders, publishedSnapshotAccessor, mainDom, testing, enableRepositoryEvents,
|
|
|
|
|
|
documentRepository, mediaRepository, memberRepository, globalSettings);
|
2016-05-26 17:12:04 +02:00
|
|
|
|
|
|
|
|
|
|
_domainService = serviceContext.DomainService;
|
|
|
|
|
|
_memberService = serviceContext.MemberService;
|
|
|
|
|
|
_mediaService = serviceContext.MediaService;
|
2016-07-20 12:44:15 +02:00
|
|
|
|
_userService = serviceContext.UserService;
|
2018-04-30 21:29:49 +02:00
|
|
|
|
_defaultCultureAccessor = defaultCultureAccessor;
|
2016-05-26 19:20:33 +02:00
|
|
|
|
|
2016-05-26 17:12:04 +02:00
|
|
|
|
_requestCache = requestCache;
|
2018-04-06 13:51:54 +10:00
|
|
|
|
_globalSettings = globalSettings;
|
2018-04-24 13:07:18 +10:00
|
|
|
|
_siteDomainHelper = siteDomainHelper;
|
2016-05-26 17:12:04 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override void Dispose()
|
|
|
|
|
|
{
|
|
|
|
|
|
_xmlStore.Dispose();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2016-06-30 10:30:43 +02:00
|
|
|
|
#region Environment
|
|
|
|
|
|
|
|
|
|
|
|
public override bool EnsureEnvironment(out IEnumerable<string> errors)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Test creating/saving/deleting a file in the same location as the content xml file
|
|
|
|
|
|
// NOTE: We cannot modify the xml file directly because a background thread is responsible for
|
|
|
|
|
|
// that and we might get lock issues.
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
XmlStore.EnsureFilePermission();
|
|
|
|
|
|
errors = Enumerable.Empty<string>();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch
|
|
|
|
|
|
{
|
2018-04-06 13:51:54 +10:00
|
|
|
|
errors = new[] { SystemFiles.GetContentCacheXml(_globalSettings) };
|
2016-06-30 10:30:43 +02:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Caches
|
2016-05-26 17:12:04 +02:00
|
|
|
|
|
2018-04-27 11:38:50 +10:00
|
|
|
|
public override IPublishedSnapshot CreatePublishedSnapshot(string previewToken)
|
2016-05-26 17:12:04 +02:00
|
|
|
|
{
|
|
|
|
|
|
// use _requestCache to store recursive properties lookup, etc. both in content
|
|
|
|
|
|
// and media cache. Life span should be the current request. Or, ideally
|
|
|
|
|
|
// the current caches, but that would mean creating an extra cache (StaticCache
|
|
|
|
|
|
// probably) so better use RequestCache.
|
|
|
|
|
|
|
2018-04-30 21:29:49 +02:00
|
|
|
|
var domainCache = new DomainCache(_domainService, _defaultCultureAccessor);
|
2016-05-26 17:12:04 +02:00
|
|
|
|
|
2018-04-27 11:38:50 +10:00
|
|
|
|
return new PublishedSnapshot(
|
2018-04-24 13:07:18 +10:00
|
|
|
|
new PublishedContentCache(_xmlStore, domainCache, _requestCache, _globalSettings, _siteDomainHelper, _contentTypeCache, _routesCache, previewToken),
|
2016-07-20 12:44:15 +02:00
|
|
|
|
new PublishedMediaCache(_xmlStore, _mediaService, _userService, _requestCache, _contentTypeCache),
|
2016-05-26 17:12:04 +02:00
|
|
|
|
new PublishedMemberCache(_xmlStore, _requestCache, _memberService, _contentTypeCache),
|
|
|
|
|
|
domainCache);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2016-06-30 10:30:43 +02:00
|
|
|
|
#region Preview
|
2016-05-26 17:12:04 +02:00
|
|
|
|
|
|
|
|
|
|
public override string EnterPreview(IUser user, int contentId)
|
|
|
|
|
|
{
|
|
|
|
|
|
var previewContent = new PreviewContent(_xmlStore, user.Id);
|
|
|
|
|
|
previewContent.CreatePreviewSet(contentId, true); // preview branch below that content
|
|
|
|
|
|
return previewContent.Token;
|
|
|
|
|
|
//previewContent.ActivatePreviewCookie();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override void RefreshPreview(string previewToken, int contentId)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (previewToken.IsNullOrWhiteSpace()) return;
|
|
|
|
|
|
var previewContent = new PreviewContent(_xmlStore, previewToken);
|
|
|
|
|
|
previewContent.CreatePreviewSet(contentId, true); // preview branch below that content
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override void ExitPreview(string previewToken)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (previewToken.IsNullOrWhiteSpace()) return;
|
|
|
|
|
|
var previewContent = new PreviewContent(_xmlStore, previewToken);
|
|
|
|
|
|
previewContent.ClearPreviewSet();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Xml specific
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Gets the underlying XML store.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public XmlStore XmlStore => _xmlStore;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Gets the underlying RoutesCache.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public RoutesCache RoutesCache => _routesCache;
|
|
|
|
|
|
|
|
|
|
|
|
public bool VerifyContentAndPreviewXml()
|
|
|
|
|
|
{
|
|
|
|
|
|
return XmlStore.VerifyContentAndPreviewXml();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void RebuildContentAndPreviewXml()
|
|
|
|
|
|
{
|
|
|
|
|
|
XmlStore.RebuildContentAndPreviewXml();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public bool VerifyMediaXml()
|
|
|
|
|
|
{
|
|
|
|
|
|
return XmlStore.VerifyMediaXml();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void RebuildMediaXml()
|
|
|
|
|
|
{
|
|
|
|
|
|
XmlStore.RebuildMediaXml();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public bool VerifyMemberXml()
|
|
|
|
|
|
{
|
|
|
|
|
|
return XmlStore.VerifyMemberXml();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void RebuildMemberXml()
|
|
|
|
|
|
{
|
|
|
|
|
|
XmlStore.RebuildMemberXml();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Change management
|
|
|
|
|
|
|
|
|
|
|
|
public override void Notify(ContentCacheRefresher.JsonPayload[] payloads, out bool draftChanged, out bool publishedChanged)
|
|
|
|
|
|
{
|
|
|
|
|
|
_xmlStore.Notify(payloads, out draftChanged, out publishedChanged);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override void Notify(MediaCacheRefresher.JsonPayload[] payloads, out bool anythingChanged)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var payload in payloads)
|
|
|
|
|
|
PublishedMediaCache.ClearCache(payload.Id);
|
|
|
|
|
|
|
|
|
|
|
|
anythingChanged = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override void Notify(ContentTypeCacheRefresher.JsonPayload[] payloads)
|
|
|
|
|
|
{
|
|
|
|
|
|
_xmlStore.Notify(payloads);
|
|
|
|
|
|
if (payloads.Any(x => x.ItemType == typeof(IContentType).Name))
|
|
|
|
|
|
_routesCache.Clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override void Notify(DataTypeCacheRefresher.JsonPayload[] payloads)
|
|
|
|
|
|
{
|
2018-02-09 14:34:28 +01:00
|
|
|
|
_publishedContentTypeFactory.NotifyDataTypeChanges(payloads.Select(x => x.Id).ToArray());
|
2016-05-26 17:12:04 +02:00
|
|
|
|
_xmlStore.Notify(payloads);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override void Notify(DomainCacheRefresher.JsonPayload[] payloads)
|
|
|
|
|
|
{
|
|
|
|
|
|
_routesCache.Clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|