Indexing Pages when a language is deleted

Goal

The purpose of this article is to help you haldle a bug when indexing pages that have been translated to a language that has been deleted.

This bug might appear on Sitefinity version 13.0 and earlier. From 13.1 multilinual is handled in a different way and this problem should not occur.

Prerequisite

Install the Hawksearch Connector:

Problem explanation

In Sitefinity various languages can be added. And all kinds of content could be created in these languages or content could be translated into these chosen languages. When a site has more thаn two languages (ex: English, Spanish, German) and page is created in a language, Spanish for example, but afterwards the Spanish language is deleted, this page is automatically translated into the default language. Actually, it is not translated but fallbacks to an invariant culture, which is the default culture. This means that the pages are still visible in the backend and it looks like they are translated to the default language.
On a database level whenever we are adding languages (up to 5) new columns for this language are created, but all of them share the same PageNode id. When we create a page in Spanish the Spanish columns are filled. When the Spanish language is deleted in the backend this does not mean that the pages that have Spanish translation are deleted. They still exist and are visible in the backend. Sitefinity tries to shows the page in one of the other translations that are still available in the backend.

Whenever there are pages translated in different languages then there is one PageNode (shared PageNode) and different PageData for each translation. When a translation, a language, is deleted we delete the corresponding PageData. It is equal to null and this page can not be accessed if there are no other translations (no other PageData).

This is problem leads to another: the page still exists, but when we try to index the pages the operation fails. The reason is that these pages can not be resolved in the PushData method in the PageInboundPipe. And documents are not passed to the UpdateIndex method.

How can this bug be handled?

There is a simple workaround for handling this issue. Here are the steps:

  1. Inherit the PageInboundPipe

  2. Override the PushData(IList<PublishingSystemEventInfo> items)

  3. Add the logic shown below to check whether the PageData is null.

  4. Register the Pipe in the Global.asax file → follow the second code snippet.

 

using System.Collections.Generic; using System.Linq; using Telerik.Sitefinity.Pages.Model; using Telerik.Sitefinity.Publishing; using Telerik.Sitefinity.Publishing.Pipes; namespace Hawksearch.Publishing { public class CustomPageInboundPipe : PageInboundPipe { public override void PushData(IList<PublishingSystemEventInfo> items) { var itemsToPass = new List<PublishingSystemEventInfo>(); var pageNodes = items.Where(i => i.Item is PageNode).Select(i => i.Item as PageNode).ToList(); var pageNodeIds = pageNodes.Select(pn => pn.Id).ToList(); var pageManager = Telerik.Sitefinity.Modules.Pages.PageManager.GetManager(); var pageData = pageManager.GetPageDataList().Where(pd => pageNodeIds.Contains(pd.NavigationNodeId)).ToList(); foreach (var page in pageData) { if (page != null) { var itemToAdd = items.Where(i => i.Item is PageNode).FirstOrDefault(i => ((PageNode)i.Item).Id == page.NavigationNodeId); if (itemToAdd != null) { itemsToPass.Add(itemToAdd); } } } base.PushData(itemsToPass); } } }

 

 

using System; using SitefinityWebApp.Search; using Telerik.Sitefinity.Abstractions; using Telerik.Sitefinity.Publishing; using Telerik.Sitefinity.Publishing.Pipes; namespace SitefinityWebApp { public class Global : System.Web.HttpApplication { protected void Application_Start(object sender, EventArgs e) { Bootstrapper.Bootstrapped += Bootstrapper_Bootstrapped; } private void Bootstrapper_Bootstrapped(object sender, EventArgs e) { this.RegisterCustomSearchIndexInboundPipe(); } private void RegisterCustomSearchIndexInboundPipe() { PublishingSystemFactory.RegisterPipe(PageInboundPipe.PipeName, typeof(CustomPageInboundPipe)); } } }