Merge remote-tracking branch 'origin/6.2.0' into 7.1.0

Conflicts:
	src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs
	src/Umbraco.Core/Services/IMembershipUserService.cs
	src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs
	src/Umbraco.Web.UI/config/trees.config
	src/Umbraco.Web.UI/config/umbracoSettings.config
	src/Umbraco.Web.UI/umbraco/controls/ContentTypeControlNew.ascx
	src/Umbraco.Web.UI/umbraco/developer/DataTypes/editDatatype.aspx
	src/Umbraco.Web.UI/umbraco/plugins/uGoLive/Dashboard.ascx
	src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs
	src/Umbraco.Web/Search/ExamineEvents.cs
	src/Umbraco.Web/Umbraco.Web.csproj
	src/Umbraco.Web/umbraco.presentation/content.cs
	src/Umbraco.Web/umbraco.presentation/umbraco/cache/LegacyClasses.cs
This commit is contained in:
Shannon
2014-03-06 20:22:32 +11:00
50 changed files with 1418 additions and 313 deletions

View File

@@ -8,9 +8,13 @@ using Examine;
using Examine.LuceneEngine;
using Lucene.Net.Documents;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Services;
using Umbraco.Core.Sync;
using Umbraco.Web.Cache;
using UmbracoExamine;
using umbraco;
using umbraco.BusinessLogic;
@@ -51,26 +55,16 @@ namespace Umbraco.Web.Search
if (registeredProviders == 0)
return;
MediaService.Saved += MediaServiceSaved;
MediaService.Deleted += MediaServiceDeleted;
MediaService.Moved += MediaServiceMoved;
MediaService.Trashed += MediaServiceTrashed;
ContentService.Saved += ContentServiceSaved;
ContentService.Deleted += ContentServiceDeleted;
ContentService.Moved += ContentServiceMoved;
ContentService.Trashed += ContentServiceTrashed;
//These should only fire for providers that DONT have SupportUnpublishedContent set to true
content.AfterUpdateDocumentCache += ContentAfterUpdateDocumentCache;
content.AfterClearDocumentCache += ContentAfterClearDocumentCache;
//Bind to distributed cache events - this ensures that this logic occurs on ALL servers that are taking part
// in a load balanced environment.
CacheRefresherBase<UnpublishedPageCacheRefresher>.CacheUpdated += UnpublishedPageCacheRefresherCacheUpdated;
CacheRefresherBase<PageCacheRefresher>.CacheUpdated += PublishedPageCacheRefresherCacheUpdated;
CacheRefresherBase<MediaCacheRefresher>.CacheUpdated += MediaCacheRefresherCacheUpdated;
CacheRefresherBase<MemberCacheRefresher>.CacheUpdated += MemberCacheRefresherCacheUpdated;
//TODO: Remove the legacy event handlers once we proxy the legacy members stuff through the new services
Member.AfterSave += MemberAfterSave;
Member.AfterDelete += MemberAfterDelete;
MemberService.Saved += MemberServiceSaved;
MemberService.Deleted += MemberServiceDeleted;
var contentIndexer = ExamineManager.Instance.IndexProviderCollection["InternalIndexer"] as UmbracoContentIndexer;
if (contentIndexer != null)
{
@@ -83,136 +77,242 @@ namespace Umbraco.Web.Search
}
}
static void ContentServiceTrashed(IContentService sender, Core.Events.MoveEventArgs<IContent> e)
{
IndexConent(e.Entity);
}
static void MediaServiceTrashed(IMediaService sender, Core.Events.MoveEventArgs<IMedia> e)
{
IndexMedia(e.Entity);
}
static void ContentServiceMoved(IContentService sender, Umbraco.Core.Events.MoveEventArgs<IContent> e)
{
IndexConent(e.Entity);
}
static void ContentServiceDeleted(IContentService sender, Umbraco.Core.Events.DeleteEventArgs<IContent> e)
{
e.DeletedEntities.ForEach(
content =>
ExamineManager.Instance.DeleteFromIndex(
content.Id.ToString(),
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>().Where(x => x.EnableDefaultEventHandler)));
}
static void ContentServiceSaved(IContentService sender, Umbraco.Core.Events.SaveEventArgs<IContent> e)
{
e.SavedEntities.ForEach(IndexConent);
}
static void MediaServiceMoved(IMediaService sender, Umbraco.Core.Events.MoveEventArgs<IMedia> e)
{
IndexMedia(e.Entity);
}
static void MediaServiceDeleted(IMediaService sender, Umbraco.Core.Events.DeleteEventArgs<IMedia> e)
{
e.DeletedEntities.ForEach(
media =>
ExamineManager.Instance.DeleteFromIndex(
media.Id.ToString(),
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>().Where(x => x.EnableDefaultEventHandler)));
}
static void MediaServiceSaved(IMediaService sender, Umbraco.Core.Events.SaveEventArgs<IMedia> e)
{
e.SavedEntities.ForEach(IndexMedia);
}
static void MemberServiceSaved(IMemberService sender, Core.Events.SaveEventArgs<IMember> e)
{
foreach (var m in e.SavedEntities)
static void MemberCacheRefresherCacheUpdated(MemberCacheRefresher sender, CacheRefresherEventArgs e)
{
switch (e.MessageType)
{
var xml = m.ToXml();
//ensure that only the providers are flagged to listen execute
var providers = ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
.Where(x => x.EnableDefaultEventHandler);
ExamineManager.Instance.ReIndexNode(xml, IndexTypes.Member, providers);
case MessageType.RefreshById:
var c1 = ApplicationContext.Current.Services.MemberService.GetById((int)e.MessageObject);
if (c1 != null)
{
ReIndexForMember(c1);
}
break;
case MessageType.RemoveById:
// This is triggered when the item is permanently deleted
DeleteIndexForEntity((int)e.MessageObject, false);
break;
case MessageType.RefreshByInstance:
var c3 = e.MessageObject as IMember;
if (c3 != null)
{
ReIndexForMember(c3);
}
break;
case MessageType.RemoveByInstance:
// This is triggered when the item is permanently deleted
var c4 = e.MessageObject as IMember;
if (c4 != null)
{
DeleteIndexForEntity(c4.Id, false);
}
break;
case MessageType.RefreshAll:
case MessageType.RefreshByJson:
default:
//We don't support these, these message types will not fire for unpublished content
break;
}
}
/// <summary>
/// Handles index management for all media events - basically handling saving/copying/trashing/deleting
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static void MediaCacheRefresherCacheUpdated(MediaCacheRefresher sender, CacheRefresherEventArgs e)
{
switch (e.MessageType)
{
case MessageType.RefreshById:
var c1 = ApplicationContext.Current.Services.MediaService.GetById((int)e.MessageObject);
if (c1 != null)
{
ReIndexForMedia(c1, c1.Trashed == false);
}
break;
case MessageType.RemoveById:
var c2 = ApplicationContext.Current.Services.MediaService.GetById((int)e.MessageObject);
if (c2 != null)
{
//This is triggered when the item has trashed.
// So we need to delete the index from all indexes not supporting unpublished content.
DeleteIndexForEntity(c2.Id, true);
//We then need to re-index this item for all indexes supporting unpublished content
ReIndexForMedia(c2, false);
}
break;
case MessageType.RefreshByJson:
var jsonPayloads = MediaCacheRefresher.DeserializeFromJsonPayload((string)e.MessageObject);
if (jsonPayloads.Any())
{
foreach (var payload in jsonPayloads)
{
switch (payload.Operation)
{
case MediaCacheRefresher.OperationType.Saved:
var media = ApplicationContext.Current.Services.MediaService.GetById(payload.Id);
if (media != null)
{
ReIndexForMedia(media, media.Trashed == false);
}
break;
case MediaCacheRefresher.OperationType.Trashed:
//keep if trashed for indexes supporting unpublished
DeleteIndexForEntity(payload.Id, true);
break;
case MediaCacheRefresher.OperationType.Deleted:
//permanently remove from all indexes
DeleteIndexForEntity(payload.Id, false);
break;
default:
throw new ArgumentOutOfRangeException();
}
}
}
break;
case MessageType.RefreshByInstance:
case MessageType.RemoveByInstance:
case MessageType.RefreshAll:
default:
//We don't support these, these message types will not fire for media
break;
}
}
static void MemberServiceDeleted(IMemberService sender, Core.Events.DeleteEventArgs<IMember> e)
/// <summary>
/// Handles index management for all published content events - basically handling published/unpublished
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <remarks>
/// This will execute on all servers taking part in load balancing
/// </remarks>
static void PublishedPageCacheRefresherCacheUpdated(PageCacheRefresher sender, CacheRefresherEventArgs e)
{
foreach (var m in e.DeletedEntities)
switch (e.MessageType)
{
var nodeId = m.Id.ToString(CultureInfo.InvariantCulture);
//ensure that only the providers are flagged to listen execute
ExamineManager.Instance.DeleteFromIndex(nodeId,
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
.Where(x => x.EnableDefaultEventHandler));
case MessageType.RefreshById:
var c1 = ApplicationContext.Current.Services.ContentService.GetById((int)e.MessageObject);
if (c1 != null)
{
ReIndexForContent(c1, true);
}
break;
case MessageType.RemoveById:
//This is triggered when the item has been unpublished or trashed (which also performs an unpublish).
var c2 = ApplicationContext.Current.Services.ContentService.GetById((int)e.MessageObject);
if (c2 != null)
{
// So we need to delete the index from all indexes not supporting unpublished content.
DeleteIndexForEntity(c2.Id, true);
// We then need to re-index this item for all indexes supporting unpublished content
ReIndexForContent(c2, false);
}
break;
case MessageType.RefreshByInstance:
var c3 = e.MessageObject as IContent;
if (c3 != null)
{
ReIndexForContent(c3, true);
}
break;
case MessageType.RemoveByInstance:
//This is triggered when the item has been unpublished or trashed (which also performs an unpublish).
var c4 = e.MessageObject as IContent;
if (c4 != null)
{
// So we need to delete the index from all indexes not supporting unpublished content.
DeleteIndexForEntity(c4.Id, true);
// We then need to re-index this item for all indexes supporting unpublished content
ReIndexForContent(c4, false);
}
break;
case MessageType.RefreshAll:
case MessageType.RefreshByJson:
default:
//We don't support these for examine indexing
break;
}
}
private static void MemberAfterSave(Member sender, SaveEventArgs e)
{
//ensure that only the providers are flagged to listen execute
var xml = ExamineXmlExtensions.ToXElement(sender.ToXml(new System.Xml.XmlDocument(), false));
var providers = ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
.Where(x => x.EnableDefaultEventHandler);
ExamineManager.Instance.ReIndexNode(xml, IndexTypes.Member, providers);
}
/// <summary>
/// Handles index management for all unpublished content events - basically handling saving/copying/deleting
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <remarks>
/// This will execute on all servers taking part in load balancing
/// </remarks>
static void UnpublishedPageCacheRefresherCacheUpdated(UnpublishedPageCacheRefresher sender, CacheRefresherEventArgs e)
{
switch (e.MessageType)
{
case MessageType.RefreshById:
var c1 = ApplicationContext.Current.Services.ContentService.GetById((int) e.MessageObject);
if (c1 != null)
{
ReIndexForContent(c1, false);
}
break;
case MessageType.RemoveById:
// This is triggered when the item is permanently deleted
DeleteIndexForEntity((int)e.MessageObject, false);
break;
case MessageType.RefreshByInstance:
var c3 = e.MessageObject as IContent;
if (c3 != null)
{
ReIndexForContent(c3, false);
}
break;
case MessageType.RemoveByInstance:
// This is triggered when the item is permanently deleted
var c4 = e.MessageObject as IContent;
if (c4 != null)
{
DeleteIndexForEntity(c4.Id, false);
}
break;
case MessageType.RefreshAll:
case MessageType.RefreshByJson:
default:
//We don't support these, these message types will not fire for unpublished content
break;
}
}
private static void MemberAfterDelete(Member sender, DeleteEventArgs e)
private static void ReIndexForMember(IMember member)
{
var nodeId = sender.Id.ToString(CultureInfo.InvariantCulture);
//ensure that only the providers are flagged to listen execute
ExamineManager.Instance.DeleteFromIndex(nodeId,
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
.Where(x => x.EnableDefaultEventHandler));
}
/// <summary>
/// Only Update indexes for providers that dont SupportUnpublishedContent
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ContentAfterUpdateDocumentCache(Document sender, DocumentCacheEventArgs e)
{
//ensure that only the providers that have DONT unpublishing support enabled
//that are also flagged to listen
ExamineManager.Instance.ReIndexNode(ToXDocument(sender, true).Root, IndexTypes.Content,
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
.Where(x => !x.SupportUnpublishedContent
&& x.EnableDefaultEventHandler));
}
/// <summary>
/// Only update indexes for providers that don't SupportUnpublishedContnet
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ContentAfterClearDocumentCache(Document sender, DocumentCacheEventArgs e)
{
var nodeId = sender.Id.ToString();
//ensure that only the providers that DONT have unpublishing support enabled
//that are also flagged to listen
ExamineManager.Instance.DeleteFromIndex(nodeId,
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
.Where(x => !x.SupportUnpublishedContent
&& x.EnableDefaultEventHandler));
ExamineManager.Instance.ReIndexNode(
member.ToXml(), IndexTypes.Member,
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
//ensure that only the providers are flagged to listen execute
.Where(x => x.EnableDefaultEventHandler));
}
/// <summary>
@@ -238,28 +338,62 @@ namespace Umbraco.Web.Search
}
}
private static void IndexMedia(IMedia sender)
[SecuritySafeCritical]
private static void ReIndexForMedia(IMedia sender, bool isMediaPublished)
{
ExamineManager.Instance.ReIndexNode(
sender.ToXml(), "media",
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>().Where(x => x.EnableDefaultEventHandler));
sender.ToXml(), IndexTypes.Media,
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
//Index this item for all indexers if the media is not trashed, otherwise if the item is trashed
// then only index this for indexers supporting unpublished media
.Where(x => isMediaPublished || (x.SupportUnpublishedContent))
.Where(x => x.EnableDefaultEventHandler));
}
private static void IndexConent(IContent sender)
{
//only index this content if the indexer supports unpublished content. that is because the
// content.AfterUpdateDocumentCache will handle anything being published and will only index against indexers
// that only support published content.
// NOTE: The events for publishing have changed slightly from 6.0 to 6.1 and are streamlined in 6.1. Before
// this event would fire before publishing, then again after publishing. Now the save event fires once before
// publishing and that is all.
ExamineManager.Instance.ReIndexNode(
sender.ToXml(), "content",
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
.Where(x => x.SupportUnpublishedContent && x.EnableDefaultEventHandler));
}
/// <summary>
/// Remove items from any index that doesn't support unpublished content
/// </summary>
/// <param name="entityId"></param>
/// <param name="keepIfUnpublished">
/// If true, indicates that we will only delete this item from indexes that don't support unpublished content.
/// If false it will delete this from all indexes regardless.
/// </param>
[SecuritySafeCritical]
private static void DeleteIndexForEntity(int entityId, bool keepIfUnpublished)
{
ExamineManager.Instance.DeleteFromIndex(
entityId.ToString(CultureInfo.InvariantCulture),
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
//if keepIfUnpublished == true then only delete this item from indexes not supporting unpublished content,
// otherwise if keepIfUnpublished == false then remove from all indexes
.Where(x => keepIfUnpublished == false || x.SupportUnpublishedContent == false)
.Where(x => x.EnableDefaultEventHandler));
}
/// <summary>
/// Re-indexes a content item whether published or not but only indexes them for indexes supporting unpublished content
/// </summary>
/// <param name="sender"></param>
/// <param name="isContentPublished">
/// Value indicating whether the item is published or not
/// </param>
[SecuritySafeCritical]
private static void ReIndexForContent(IContent sender, bool isContentPublished)
{
ExamineManager.Instance.ReIndexNode(
sender.ToXml(), IndexTypes.Content,
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
//Index this item for all indexers if the content is published, otherwise if the item is not published
// then only index this for indexers supporting unpublished content
.Where(x => isContentPublished || (x.SupportUnpublishedContent))
.Where(x => x.EnableDefaultEventHandler));
}
/// <summary>
/// Converts a content node to XDocument