Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Full set of classes and config changes required to index modular content in Sitecore, i.e. content that is added to the page as a separate rendering with a datasource. Configured to only index certain renderings based on config, to disallow indexing of renderings that may be "Related Items" or other types of renderings that are shared and not pe…
using System.Linq;
using Sitecore;
using Sitecore.ContentSearch;
using Sitecore.ContentSearch.Pipelines.GetDependencies;
using Sitecore.Data;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
namespace Common.Sitecore.Search.GetDependencies
{
public class GetDatasourceDependencies : BaseProcessor
{
public override void Process(GetDependenciesArgs context)
{
Assert.IsNotNull(context.IndexedItem, "indexed item");
Assert.IsNotNull(context.Dependencies, "dependencies");
var item = (Item)(context.IndexedItem as SitecoreIndexableItem);
if (item == null)
return;
bool Func(ItemUri uri) => (uri != null) && uri != item.Uri;
var source = (
from l
in Globals.LinkDatabase.GetReferrers(item, FieldIDs.LayoutField)
select l.GetSourceItem().Uri)
.Where(Func)
.ToList();
source.AddRange(
(
from l
in Globals.LinkDatabase.GetReferrers(item, FieldIDs.FinalLayoutField)
select l.GetSourceItem().Uri)
.Where(Func)
);
source = source.Distinct().ToList();
context.Dependencies.AddRange(source.Select(x => (SitecoreItemUniqueId)x));
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using Sitecore.Configuration;
using Sitecore.Data;
using Sitecore.Xml;
namespace Common.Sitecore.ConfigElements
{
public class IndexedRenderings
{
public string Name { get; set; }
public ID Id { get; set; }
public static List<IndexedRenderings> IndexableRenderings()
{
return (from XmlNode node in Factory.GetConfigNodes("indexedRenderings/indexedRendering")
select new IndexedRenderings
{
Name = XmlUtil.GetAttribute("name", node),
Id = new ID(XmlUtil.GetAttribute("id", node))
}).ToList();
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Sitecore;
using Sitecore.ContentSearch;
using Sitecore.ContentSearch.ComputedFields;
using Sitecore.Data;
using Sitecore.Data.Fields;
using Sitecore.Data.Items;
using Sitecore.WordOCX.HtmlDocument;
using Common.Sitecore.ConfigElements;
namespace Common.Sitecore.Search.ComputedFields
{
public class RenderedContent : AbstractComputedIndexField
{
private IEnumerable<ID> _indexableRenderings;
public override object ComputeFieldValue(IIndexable indexable)
{
var item = (Item)(indexable as SitecoreIndexableItem);
if (item == null)
return null;
_indexableRenderings = IndexedRenderings.IndexableRenderings().Select(i => i.Id);
if (!_indexableRenderings.Any())
return null;
var deviceItem = item.Database.Resources.Devices.GetAll().FirstOrDefault(d => d.IsDefault);
if (deviceItem == null)
return null;
var itemDatasources = ExtractRenderingDataSourceItems(item, _indexableRenderings, item.Fields[FieldIDs.FinalLayoutField], deviceItem).ToList(); // for later `Distinct()`
itemDatasources.AddRange(ExtractRenderingDataSourceItems(item, _indexableRenderings, item.Fields[FieldIDs.LayoutField], deviceItem));
itemDatasources = itemDatasources.Distinct().ToList();
if (!itemDatasources.Any())
return null;
var content = new List<string>();
foreach (var itemDatasource in itemDatasources)
GetItemContent(itemDatasource, content);
if (!content.Any())
return null;
var aggregateContent = content.Aggregate((a, b) => $"{a} {b}");
aggregateContent = StripLineBreaksAndWhiteSpace(aggregateContent);
return aggregateContent;
}
private static IEnumerable<Item> ExtractRenderingDataSourceItems(Item item, IEnumerable<ID> indexableRenderings, Field layoutField, DeviceItem deviceItem)
{
if (layoutField == null)
return Enumerable.Empty<Item>();
var layoutXml = LayoutField.GetFieldValue(layoutField);
if (string.IsNullOrEmpty(layoutXml))
return Enumerable.Empty<Item>();
var renderings = item.Visualization.GetRenderings(deviceItem, false);
if (renderings == null || renderings.Length == 0)
return Enumerable.Empty<Item>();
var datasourceItems = new List<Item>();
for (var renderingIndex = renderings.Length - 1; renderingIndex >= 0; renderingIndex--)
{
var rendering = renderings[renderingIndex];
if (rendering == null || rendering.Database != item.Database)
continue;
if (!indexableRenderings.Contains(rendering.RenderingID))
continue;
var datasourceId = rendering.Settings.DataSource;
if (!ID.IsID(datasourceId))
continue;
var datasourceItem = item.Database.GetItem(new ID(datasourceId));
if(datasourceItem == null)
continue;
datasourceItems.Add(datasourceItem);
}
return datasourceItems;
}
/// <summary>
/// Extracts textual content from an item's fields
/// </summary>
private static void GetItemContent(Item dataSource, ICollection<string> content)
{
//.Where(field => !field.Name.StartsWith("__")
foreach (Field field in dataSource.Fields)
{
if (!IndexOperationsHelper.IsTextField(new SitecoreItemDataField(field)))
continue;
var fieldValue = StripHtmlTags(field.Value ?? string.Empty);
if (!string.IsNullOrWhiteSpace(fieldValue))
content.Add(fieldValue);
}
foreach (Item child in dataSource.Children)
{
GetItemContent(child, content);
}
}
private static string StripHtmlTags(string source)
{
if (source == null)
return null;
var doc = new HtmlDocument();
doc.LoadHtml(source);
return doc.DocumentNode.InnerText;
}
private static string StripLineBreaksAndWhiteSpace(string source)
{
if(string.IsNullOrWhiteSpace(source))
return null;
source = source.Replace(System.Environment.NewLine, "");
source = Regex.Replace(source, @"\s+", " ");
return source.Trim(' ');
}
}
}
<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<contentSearch>
<indexConfigurations>
<defaultLuceneIndexConfiguration> <!-- swap for your configuration, e.g. SOLR!!! -->
<documentOptions>
<fields hint="raw:AddComputedIndexField">
<field fieldName="renderedContent" storageType="no" indexType="tokenized">Common.Sitecore.Search.ComputedFields.RenderedContent,Common</field>
</fields>
</documentOptions>
</defaultLuceneIndexConfiguration>
</indexConfigurations>
</contentSearch>
<pipelines>
<indexing.getDependencies>
<processor type="Common.Sitecore.Search.GetDependencies.GetDatasourceDependencies, Common"/>
</indexing.getDependencies>
</pipelines>
<indexedRenderings>
<indexedRendering name="RichText" id="{4F8942FF-C4E4-408A-B3D5-4657EE5050CA}" />
<indexedRendering name="EmployeeBio" id="{53F8166B-6627-4C1B-BED5-FBD0B36EC527}" />
<indexedRendering name="HighlightStatic" id="{75100A87-B7B0-4D1F-BE85-1A8FC6342514}" />
<indexedRendering name="IntroText" id="{89D7EE42-A5E1-4F24-B247-BFD382E501D4}" />
</indexedRenderings>
</sitecore>
</configuration>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment