From 3deda7efabf436d905cad69b6d7a7c164bd31de9 Mon Sep 17 00:00:00 2001 From: Claus Date: Wed, 9 Nov 2016 13:09:31 +0100 Subject: [PATCH 1/3] U4-7833 Changing doc type results in invalid cache, lucene indexes, etc... For now: add messages in the UI to tell people they need to publish the items again and rebuilt their indexes. --- src/Umbraco.Web.UI/umbraco/config/lang/da.xml | 3 ++- src/Umbraco.Web.UI/umbraco/config/lang/en.xml | 2 ++ src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml | 1 + src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx | 4 +++- src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.cs | 3 +++ .../umbraco/dialogs/ChangeDocType.aspx.designer.cs | 9 +++++++++ 6 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml index b0452fb631..b9996db11c 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml @@ -109,9 +109,10 @@ Ny skabelon Ny type ingen + Du bør genopbygge dine Examine indekser via 'Examine Management' dashboarded i udvikler sektionen for at sikre at denne ændring registreres i hele dit website. Indhold Vælg ny dokumenttype - Dokumenttypen på detvalgte indhold blev skiftet til [new type], og følgende egenskaber blev overført: + Dokumenttypen på det valgte indhold blev skiftet til [new type], og følgende egenskaber blev overført: til Overførsel af egenskaber kunne ikke fuldføres, da en eller flere egenskaber er indstillet til at blive overført mere end én gang. Kun andre dokumenttyper, der er gyldige på denne placering, vises. diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml index bdc2647563..317c044f9d 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml @@ -100,6 +100,7 @@ Show styles Insert table Generate models + Save and generate models To change the document type for the selected content, first select from the list of valid types for this location. @@ -114,6 +115,7 @@ New Template New Type none + Please make sure to rebuild your Examine indexes using the 'Examine Management' dashboard in the Developer section, to ensure this change is applied everywhere. Content Select New Document Type The document type of the selected content has been successfully changed to [new type] and the following properties mapped: diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml index 7544cacc0c..7a39c59406 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml @@ -115,6 +115,7 @@ New Template New Type none + Please make sure to rebuild your Examine indexes using the 'Examine Management' dashboard in the Developer section, to ensure this change is applied everywhere. Content Select New Document Type The document type of the selected content has been successfully changed to [new type] and the following properties mapped: diff --git a/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx b/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx index 77deab2709..a11c5cab49 100644 --- a/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx +++ b/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx @@ -97,7 +97,9 @@

- <%=umbraco.ui.Text("defaultdialogs", "closeThisWindow") %> + +

+ <%=umbraco.ui.Text("defaultdialogs", "closeThisWindow") %>

diff --git a/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.cs b/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.cs index 0db3b6c36e..5d9243f994 100644 --- a/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.cs +++ b/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.cs @@ -265,10 +265,13 @@ namespace Umbraco.Web.UI.Umbraco.Dialogs { ContentPublishedMessage.Text = global::umbraco.ui.Text("changeDocType", "contentRepublished"); ContentPublishedMessage.Visible = true; + RebuildIndexesMessage.Text = global::umbraco.ui.Text("changeDocType", "rebuildIndexes"); + RebuildIndexesMessage.Visible = true; } else { ContentPublishedMessage.Visible = false; + RebuildIndexesMessage.Visible = false; } SuccessPlaceholder.Visible = true; SaveAndCancelPlaceholder.Visible = false; diff --git a/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.designer.cs b/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.designer.cs index b774a3ff79..5fa673836a 100644 --- a/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.designer.cs +++ b/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.designer.cs @@ -165,6 +165,15 @@ namespace Umbraco.Web.UI.Umbraco.Dialogs { /// protected global::System.Web.UI.WebControls.Literal ContentPublishedMessage; + /// + /// RebuildIndexesMessage control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Literal RebuildIndexesMessage; + /// /// ValidationPlaceholder control. /// From 2de465e8f397f4cd87550984ea2648e4477e0d8c Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 14 Nov 2016 17:39:28 +0100 Subject: [PATCH 2/3] Ensures that indexes are rebuild for items that have had their content type's or property type's aliases changed, also ensures that the content refresher kicks in if a property type alias has changed (this wasn't previously being done) --- src/Umbraco.Core/Models/ContentTypeBase.cs | 2 +- .../Cache/ContentTypeCacheRefresher.cs | 73 +++++++++-------- src/Umbraco.Web/Search/ExamineEvents.cs | 80 ++++++++++++++++++- 3 files changed, 114 insertions(+), 41 deletions(-) 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() From 213f02cbc6b7f30f94ab12d3e122e0f28947b537 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 14 Nov 2016 17:39:46 +0100 Subject: [PATCH 3/3] Revert "U4-7833 Changing doc type results in invalid cache, lucene indexes, etc..." This reverts commit 3deda7efabf436d905cad69b6d7a7c164bd31de9. --- src/Umbraco.Web.UI/umbraco/config/lang/da.xml | 3 +-- src/Umbraco.Web.UI/umbraco/config/lang/en.xml | 2 -- src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml | 1 - src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx | 4 +--- src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.cs | 3 --- .../umbraco/dialogs/ChangeDocType.aspx.designer.cs | 9 --------- 6 files changed, 2 insertions(+), 20 deletions(-) diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml index b9996db11c..b0452fb631 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml @@ -109,10 +109,9 @@ Ny skabelon Ny type ingen - Du bør genopbygge dine Examine indekser via 'Examine Management' dashboarded i udvikler sektionen for at sikre at denne ændring registreres i hele dit website. Indhold Vælg ny dokumenttype - Dokumenttypen på det valgte indhold blev skiftet til [new type], og følgende egenskaber blev overført: + Dokumenttypen på detvalgte indhold blev skiftet til [new type], og følgende egenskaber blev overført: til Overførsel af egenskaber kunne ikke fuldføres, da en eller flere egenskaber er indstillet til at blive overført mere end én gang. Kun andre dokumenttyper, der er gyldige på denne placering, vises. diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml index 317c044f9d..bdc2647563 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml @@ -100,7 +100,6 @@ Show styles Insert table Generate models - Save and generate models To change the document type for the selected content, first select from the list of valid types for this location. @@ -115,7 +114,6 @@ New Template New Type none - Please make sure to rebuild your Examine indexes using the 'Examine Management' dashboard in the Developer section, to ensure this change is applied everywhere. Content Select New Document Type The document type of the selected content has been successfully changed to [new type] and the following properties mapped: diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml index 7a39c59406..7544cacc0c 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml @@ -115,7 +115,6 @@ New Template New Type none - Please make sure to rebuild your Examine indexes using the 'Examine Management' dashboard in the Developer section, to ensure this change is applied everywhere. Content Select New Document Type The document type of the selected content has been successfully changed to [new type] and the following properties mapped: diff --git a/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx b/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx index a11c5cab49..77deab2709 100644 --- a/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx +++ b/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx @@ -97,9 +97,7 @@

- -

- <%=umbraco.ui.Text("defaultdialogs", "closeThisWindow") %> + <%=umbraco.ui.Text("defaultdialogs", "closeThisWindow") %>

diff --git a/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.cs b/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.cs index 5d9243f994..0db3b6c36e 100644 --- a/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.cs +++ b/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.cs @@ -265,13 +265,10 @@ namespace Umbraco.Web.UI.Umbraco.Dialogs { ContentPublishedMessage.Text = global::umbraco.ui.Text("changeDocType", "contentRepublished"); ContentPublishedMessage.Visible = true; - RebuildIndexesMessage.Text = global::umbraco.ui.Text("changeDocType", "rebuildIndexes"); - RebuildIndexesMessage.Visible = true; } else { ContentPublishedMessage.Visible = false; - RebuildIndexesMessage.Visible = false; } SuccessPlaceholder.Visible = true; SaveAndCancelPlaceholder.Visible = false; diff --git a/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.designer.cs b/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.designer.cs index 5fa673836a..b774a3ff79 100644 --- a/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.designer.cs +++ b/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.designer.cs @@ -165,15 +165,6 @@ namespace Umbraco.Web.UI.Umbraco.Dialogs { /// protected global::System.Web.UI.WebControls.Literal ContentPublishedMessage; - /// - /// RebuildIndexesMessage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal RebuildIndexesMessage; - /// /// ValidationPlaceholder control. ///