diff --git a/src/Umbraco.Examine/ContentIndexPopulator.cs b/src/Umbraco.Examine/ContentIndexPopulator.cs index 99ff4d7f87..01a7046723 100644 --- a/src/Umbraco.Examine/ContentIndexPopulator.cs +++ b/src/Umbraco.Examine/ContentIndexPopulator.cs @@ -4,6 +4,7 @@ using System.Linq; using Examine; using Umbraco.Core; using Umbraco.Core.Models; +using Umbraco.Core.Models.Blocks; using Umbraco.Core.Services; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseModelDefinitions; @@ -15,7 +16,7 @@ namespace Umbraco.Examine /// /// Performs the data lookups required to rebuild a content index /// - public class ContentIndexPopulator : IndexPopulator + public class ContentIndexPopulator : IndexPopulator { private readonly IContentService _contentService; private readonly IValueSetBuilder _contentValueSetBuilder; @@ -58,6 +59,12 @@ namespace Umbraco.Examine _parentId = parentId; } + public override bool IsRegistered(IUmbracoContentIndex2 index) + { + // check if it should populate based on published values + return _publishedValuesOnly == index.PublishedValuesOnly; + } + protected override void PopulateIndexes(IReadOnlyList indexes) { if (indexes.Count == 0) return; @@ -70,21 +77,24 @@ namespace Umbraco.Examine { contentParentId = _parentId.Value; } + + if (_publishedValuesOnly) + { + IndexPublishedContent(contentParentId, pageIndex, pageSize, indexes); + } + else + { + IndexAllContent(contentParentId, pageIndex, pageSize, indexes); + } + } + + protected void IndexAllContent(int contentParentId, int pageIndex, int pageSize, IReadOnlyList indexes) + { IContent[] content; do { - if (!_publishedValuesOnly) - { - content = _contentService.GetPagedDescendants(contentParentId, pageIndex, pageSize, out _).ToArray(); - } - else - { - //add the published filter - //note: We will filter for published variants in the validator - content = _contentService.GetPagedDescendants(contentParentId, pageIndex, pageSize, out _, - _publishedQuery, Ordering.By("Path", Direction.Ascending)).ToArray(); - } + content = _contentService.GetPagedDescendants(contentParentId, pageIndex, pageSize, out _).ToArray(); if (content.Length > 0) { @@ -96,5 +106,54 @@ namespace Umbraco.Examine pageIndex++; } while (content.Length == pageSize); } + + protected void IndexPublishedContent(int contentParentId, int pageIndex, int pageSize, + IReadOnlyList indexes) + { + IContent[] content; + + var publishedPages = new HashSet(); + + do + { + //add the published filter + //note: We will filter for published variants in the validator + content = _contentService.GetPagedDescendants(contentParentId, pageIndex, pageSize, out _, _publishedQuery, + Ordering.By("Path", Direction.Ascending)).ToArray(); + + + if (content.Length > 0) + { + var indexableContent = new List(); + + foreach (var item in content) + { + if (item.Level == 1) + { + // first level pages are always published so no need to filter them + indexableContent.Add(item); + publishedPages.Add(item.Id); + } + else + { + if (publishedPages.Contains(item.ParentId)) + { + // only index when parent is published + publishedPages.Add(item.Id); + indexableContent.Add(item); + } + } + } + + // ReSharper disable once PossibleMultipleEnumeration + foreach (var index in indexes) + index.IndexItems(_contentValueSetBuilder.GetValueSets(indexableContent.ToArray())); + } + + pageIndex++; + } while (content.Length == pageSize); + } } + + } diff --git a/src/Umbraco.Examine/IUmbracoContentIndex.cs b/src/Umbraco.Examine/IUmbracoContentIndex.cs index 3181ff663e..b718ec6bce 100644 --- a/src/Umbraco.Examine/IUmbracoContentIndex.cs +++ b/src/Umbraco.Examine/IUmbracoContentIndex.cs @@ -2,6 +2,20 @@ using Examine; namespace Umbraco.Examine { + /// + /// Marker interface for indexes of Umbraco content + /// + /// + /// This is a backwards compat change, in next major version remove the need for this and just have a single interface + /// + public interface IUmbracoContentIndex2 : IUmbracoContentIndex + { + bool PublishedValuesOnly { get; } + } + + /// + /// Marker interface for indexes of Umbraco content + /// public interface IUmbracoContentIndex : IIndex { diff --git a/src/Umbraco.Examine/IndexPopulator.cs b/src/Umbraco.Examine/IndexPopulator.cs index f9d4d85dc8..bfd757f9be 100644 --- a/src/Umbraco.Examine/IndexPopulator.cs +++ b/src/Umbraco.Examine/IndexPopulator.cs @@ -13,9 +13,16 @@ namespace Umbraco.Examine { public override bool IsRegistered(IIndex index) { - if (base.IsRegistered(index)) return true; - return index is TIndex; + if (base.IsRegistered(index)) + return true; + + if (!(index is TIndex casted)) + return false; + + return IsRegistered(casted); } + + public virtual bool IsRegistered(TIndex index) => true; } public abstract class IndexPopulator : IIndexPopulator diff --git a/src/Umbraco.Examine/UmbracoContentIndex.cs b/src/Umbraco.Examine/UmbracoContentIndex.cs index 67e430b4e9..88033b1407 100644 --- a/src/Umbraco.Examine/UmbracoContentIndex.cs +++ b/src/Umbraco.Examine/UmbracoContentIndex.cs @@ -17,7 +17,7 @@ namespace Umbraco.Examine /// /// An indexer for Umbraco content and media /// - public class UmbracoContentIndex : UmbracoExamineIndex, IUmbracoContentIndex + public class UmbracoContentIndex : UmbracoExamineIndex, IUmbracoContentIndex2 { public const string VariesByCultureFieldName = SpecialFieldPrefix + "VariesByCulture"; protected ILocalizationService LanguageService { get; } diff --git a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs index e9f18d8947..1a288b423c 100644 --- a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs +++ b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs @@ -45,7 +45,7 @@ namespace Umbraco.Tests.UmbracoExamine public static ContentIndexPopulator GetContentIndexRebuilder(PropertyEditorCollection propertyEditors, IContentService contentService, IScopeProvider scopeProvider, bool publishedValuesOnly) { var contentValueSetBuilder = GetContentValueSetBuilder(propertyEditors, scopeProvider, publishedValuesOnly); - var contentIndexDataSource = new ContentIndexPopulator(true, null, contentService, scopeProvider.SqlContext, contentValueSetBuilder); + var contentIndexDataSource = new ContentIndexPopulator(publishedValuesOnly, null, contentService, scopeProvider.SqlContext, contentValueSetBuilder); return contentIndexDataSource; }