Created
September 26, 2022 12:39
Visitor Group impersonation through Quick Navigation in Optimizely Content Cloud
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Startup{ | |
//... | |
public void ConfigureServices(IServiceCollection services) | |
{ | |
//... | |
services.AddSingleton<IQuickNavigatorItemProvider, VisitorGroupQuickNavigationProvider>(); | |
//... | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using EPiServer; | |
using EPiServer.Core; | |
using EPiServer.Personalization.VisitorGroups; | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace CodeArt.Optimizely.VisitorGroupManager | |
{ | |
public static class VisitorGroupsHelper | |
{ | |
/// <summary> | |
/// Analyzes which visitor groups are used in a piece of content and returns a list of those groups. | |
/// </summary> | |
/// <param name="vgRepo">The VisitorGroupRepository to extend</param> | |
/// <param name="content">The content to analyze</param> | |
/// <returns></returns> | |
public static IEnumerable<VisitorGroup> ExtractVisitorGroups(this IVisitorGroupRepository vgRepo,IContent content) | |
{ | |
foreach (var p in content.Property) | |
{ | |
if (p.Value == null) continue; | |
if (p.PropertyValueType == typeof(ContentArea)) | |
{ | |
var ca = p.Value as ContentArea; | |
if (ca == null) continue; | |
foreach (var f in ca.Items.Where(l => l.AllowedRoles != null && l.AllowedRoles.Any())) | |
{ | |
//Match! This page uses the visitor groups in l.AllowedRoles. Record. | |
foreach (var r in f.AllowedRoles) | |
{ | |
yield return vgRepo.Load(Guid.Parse(r)); | |
} | |
} | |
} | |
else if (p.PropertyValueType == typeof(XhtmlString)) | |
{ | |
var ca = p.Value as XhtmlString; | |
if (ca == null) continue; | |
foreach (var f in ca.Fragments.Where(fr => fr is EPiServer.Core.Html.StringParsing.PersonalizedContentFragment)) | |
{ | |
var j = f as EPiServer.Core.Html.StringParsing.PersonalizedContentFragment; | |
var roles = j.GetRoles(); | |
foreach (var r in roles) | |
{ | |
yield return vgRepo.Load(Guid.Parse(r)); | |
} | |
} | |
} | |
} | |
} | |
/// <summary> | |
/// Fetches content used by a piece of content (in ContentAreas or XhtmlStrings), including the content itself. | |
/// </summary> | |
/// <param name="repo">The IContentRepository to extend on</param> | |
/// <param name="content">The original content</param> | |
/// <returns>Enumeration of IContent referenced</returns> | |
public static IEnumerable<IContent> FetchReferencedContentRecursively(this IContentRepository repo, IContent content) | |
{ | |
yield return content; | |
foreach (var p in content.Property) | |
{ | |
if (p.Value == null) continue; | |
if (p.PropertyValueType == typeof(ContentArea)) | |
{ | |
var ca = p.Value as ContentArea; | |
if (ca == null) continue; | |
foreach (var f in ca.Items) | |
{ | |
foreach (var y in repo.FetchReferencedContentRecursively(repo.Get<IContent>(f.ContentLink))) | |
yield return y; | |
} | |
} | |
else if (p.PropertyValueType == typeof(XhtmlString)) | |
{ | |
var ca = p.Value as XhtmlString; | |
if (ca == null) continue; | |
foreach (var f in ca.Fragments.Where(fr => fr is EPiServer.Core.Html.StringParsing.ContentFragment)) | |
{ | |
var j = f as EPiServer.Core.Html.StringParsing.ContentFragment; | |
foreach (var y in repo.FetchReferencedContentRecursively(repo.Get<IContent>(j.ContentLink))) | |
yield return y; | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment