diff --git a/src/Umbraco.Core/Models/ContentTypeBase.cs b/src/Umbraco.Core/Models/ContentTypeBase.cs
index 2982713e5a..88476f946d 100644
--- a/src/Umbraco.Core/Models/ContentTypeBase.cs
+++ b/src/Umbraco.Core/Models/ContentTypeBase.cs
@@ -326,7 +326,7 @@ namespace Umbraco.Core.Models
}
}
- ///
+ ///
/// A boolean flag indicating if a property type has been removed from this instance.
///
///
diff --git a/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs
index 44a6efe9ff..246571d479 100644
--- a/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs
+++ b/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs
@@ -32,7 +32,7 @@ namespace Umbraco.Web.Cache
///
///
///
- private static JsonPayload[] DeserializeFromJsonPayload(string json)
+ internal static JsonPayload[] DeserializeFromJsonPayload(string json)
{
var serializer = new JavaScriptSerializer();
var jsonObject = serializer.Deserialize(json);
@@ -45,30 +45,28 @@ namespace Umbraco.Web.Cache
///
/// if the item was deleted
///
- private static JsonPayload FromContentType(IContentTypeBase contentType, bool isDeleted = false)
+ internal static JsonPayload FromContentType(IContentTypeBase contentType, bool isDeleted = false)
{
var payload = new JsonPayload
- {
- Alias = contentType.Alias,
- Id = contentType.Id,
- PropertyTypeIds = contentType.PropertyTypes.Select(x => x.Id).ToArray(),
- //either IContentType or IMediaType or IMemberType
- Type = (contentType is IContentType)
- ? typeof(IContentType).Name
- : (contentType is IMediaType)
+ {
+ Alias = contentType.Alias,
+ Id = contentType.Id,
+ PropertyTypeIds = contentType.PropertyTypes.Select(x => x.Id).ToArray(),
+ //either IContentType or IMediaType or IMemberType
+ Type = (contentType is IContentType)
+ ? typeof(IContentType).Name
+ : (contentType is IMediaType)
? typeof(IMediaType).Name
: typeof(IMemberType).Name,
- DescendantPayloads = contentType.Descendants().Select(x => FromContentType(x)).ToArray(),
- WasDeleted = isDeleted
- };
- //here we need to check if the alias of the content type changed or if one of the properties was removed.
- var dirty = contentType as IRememberBeingDirty;
- if (dirty != null)
- {
- payload.PropertyRemoved = dirty.WasPropertyDirty("HasPropertyTypeBeenRemoved");
- payload.AliasChanged = dirty.WasPropertyDirty("Alias");
- payload.IsNew = dirty.WasPropertyDirty("HasIdentity");
- }
+ DescendantPayloads = contentType.Descendants().Select(x => FromContentType(x)).ToArray(),
+ WasDeleted = isDeleted,
+ PropertyRemoved = contentType.WasPropertyDirty("HasPropertyTypeBeenRemoved"),
+ AliasChanged = contentType.WasPropertyDirty("Alias"),
+ PropertyTypeAliasChanged = contentType.PropertyTypes.Any(x => x.WasPropertyDirty("Alias")),
+ IsNew = contentType.WasPropertyDirty("HasIdentity")
+ };
+
+
return payload;
}
@@ -90,7 +88,7 @@ namespace Umbraco.Web.Cache
#region Sub classes
- private class JsonPayload
+ internal class JsonPayload
{
public JsonPayload()
{
@@ -103,6 +101,7 @@ namespace Umbraco.Web.Cache
public string Type { get; set; }
public bool AliasChanged { get; set; }
public bool PropertyRemoved { get; set; }
+ public bool PropertyTypeAliasChanged { get; set; }
public JsonPayload[] DescendantPayloads { get; set; }
public bool WasDeleted { get; set; }
public bool IsNew { get; set; }
@@ -190,21 +189,21 @@ namespace Umbraco.Web.Cache
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.IdToKeyCacheKey);
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.KeyToIdCacheKey);
- payloads.ForEach(payload =>
+ foreach (var payload in payloads)
+ {
+ //clear the cache for each item
+ ClearContentTypeCache(payload);
+
+ //we only need to do this for IContentType NOT for IMediaType, we don't want to refresh the whole cache.
+ //if the item was deleted or the alias changed or property removed then we need to refresh the content.
+ //and, don't refresh the cache if it is new.
+ if (payload.Type == typeof(IContentType).Name
+ && payload.IsNew == false
+ && (payload.WasDeleted || payload.AliasChanged || payload.PropertyRemoved || payload.PropertyTypeAliasChanged))
{
- //clear the cache for each item
- ClearContentTypeCache(payload);
-
- //we only need to do this for IContentType NOT for IMediaType, we don't want to refresh the whole cache.
- //if the item was deleted or the alias changed or property removed then we need to refresh the content.
- //and, don't refresh the cache if it is new.
- if (payload.Type == typeof(IContentType).Name
- && !payload.IsNew
- && (payload.WasDeleted || payload.AliasChanged || payload.PropertyRemoved))
- {
- needsContentRefresh = true;
- }
- });
+ needsContentRefresh = true;
+ }
+ }
//need to refresh the xml content cache if required
if (needsContentRefresh)
@@ -237,7 +236,7 @@ namespace Umbraco.Web.Cache
//cache if only a media type has changed.
//we don't want to update the routes cache if all of the content types here are new.
if (payloads.Any(x => x.Type == typeof(IContentType).Name)
- && !payloads.All(x => x.IsNew)) //if they are all new then don't proceed
+ && payloads.All(x => x.IsNew) == false) //if they are all new then don't proceed
{
// SD: we need to clear the routes cache here!
//
diff --git a/src/Umbraco.Web/Search/ExamineEvents.cs b/src/Umbraco.Web/Search/ExamineEvents.cs
index 20701fe330..d02850bffe 100644
--- a/src/Umbraco.Web/Search/ExamineEvents.cs
+++ b/src/Umbraco.Web/Search/ExamineEvents.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Xml;
@@ -67,12 +68,12 @@ namespace Umbraco.Web.Search
///
/// This is used to refresh content indexers IndexData based on the DataService whenever a content type is changed since
- /// properties may have been added/removed
+ /// properties may have been added/removed, then we need to re-index any required data if aliases have been changed
///
///
///
///
- /// See: http://issues.umbraco.org/issue/U4-4798
+ /// See: http://issues.umbraco.org/issue/U4-4798, http://issues.umbraco.org/issue/U4-7833
///
static void ContentTypeCacheRefresherCacheUpdated(ContentTypeCacheRefresher sender, CacheRefresherEventArgs e)
{
@@ -81,6 +82,79 @@ namespace Umbraco.Web.Search
{
provider.RefreshIndexerDataFromDataService();
}
+
+ if (e.MessageType == MessageType.RefreshByJson)
+ {
+ var contentTypesChanged = new HashSet();
+ var mediaTypesChanged = new HashSet();
+ var memberTypesChanged = new HashSet();
+
+ var payloads = ContentTypeCacheRefresher.DeserializeFromJsonPayload(e.MessageObject.ToString());
+ foreach (var payload in payloads)
+ {
+ if (payload.IsNew == false
+ && (payload.WasDeleted || payload.AliasChanged || payload.PropertyRemoved || payload.PropertyTypeAliasChanged))
+ {
+ //if we get here it means that some aliases have changed and the indexes for those particular doc types will need to be updated
+ if (payload.Type == typeof(IContentType).Name)
+ {
+ //if it is content
+ contentTypesChanged.Add(payload.Alias);
+ }
+ else if (payload.Type == typeof(IMediaType).Name)
+ {
+ //if it is media
+ mediaTypesChanged.Add(payload.Alias);
+ }
+ else if (payload.Type == typeof(IMemberType).Name)
+ {
+ //if it is members
+ memberTypesChanged.Add(payload.Alias);
+ }
+ }
+ }
+
+ //TODO: We need to update Examine to support re-indexing multiple items at once instead of one by one which will speed up
+ // the re-indexing process, we don't want to revert to rebuilding the whole thing!
+
+ if (contentTypesChanged.Count > 0)
+ {
+ foreach (var alias in contentTypesChanged)
+ {
+ var ctType = ApplicationContext.Current.Services.ContentTypeService.GetContentType(alias);
+ var contentItems = ApplicationContext.Current.Services.ContentService.GetContentOfContentType(ctType.Id);
+ foreach (var contentItem in contentItems)
+ {
+ ReIndexForContent(contentItem, contentItem.HasPublishedVersion && contentItem.Trashed == false);
+ }
+ }
+ }
+ if (mediaTypesChanged.Count > 0)
+ {
+ foreach (var alias in mediaTypesChanged)
+ {
+ var ctType = ApplicationContext.Current.Services.ContentTypeService.GetMediaType(alias);
+ var mediaItems = ApplicationContext.Current.Services.MediaService.GetMediaOfMediaType(ctType.Id);
+ foreach (var mediaItem in mediaItems)
+ {
+ ReIndexForMedia(mediaItem, mediaItem.Trashed == false);
+ }
+ }
+ }
+ if (memberTypesChanged.Count > 0)
+ {
+ foreach (var alias in memberTypesChanged)
+ {
+ var ctType = ApplicationContext.Current.Services.MemberTypeService.Get(alias);
+ var memberItems = ApplicationContext.Current.Services.MemberService.GetMembersByMemberType(ctType.Id);
+ foreach (var memberItem in memberItems)
+ {
+ ReIndexForMember(memberItem);
+ }
+ }
+ }
+ }
+
}
static void MemberCacheRefresherCacheUpdated(MemberCacheRefresher sender, CacheRefresherEventArgs e)
@@ -432,7 +506,7 @@ namespace Umbraco.Web.Search
//add an icon attribute to get indexed
xml.Add(new XAttribute("icon", sender.ContentType.Icon));
- ExamineManager.Instance.ReIndexNode(
+ ExamineManager.Instance.ReIndexNode(
xml, IndexTypes.Content,
ExamineManager.Instance.IndexProviderCollection.OfType()