Last active
March 13, 2017 12:39
-
-
Save LucGosso/c60f1c0fccaac79d571a726b4d7f6945 to your computer and use it in GitHub Desktop.
Content Providers in EPiServer is a way of publishing external data as pages/blocks etc... but also a way of publishing content in several places on your web. Due to the lack of publishing in several containers/parents, this is a way of cloning data and keeping friendly urls. Read more http://devblog.gosso.se/2016/09/contentprovider-example-for-…
This file contains 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.DataAbstraction; | |
using EPiServer.Security; | |
using EPiServer.ServiceLocation; | |
using EPiServer.Web.Routing; | |
using System; | |
using System.Collections.Generic; | |
using System.Collections.Specialized; | |
using System.Configuration; | |
using System.Globalization; | |
using System.Linq; | |
namespace Gosso.EPiStuff.ContentProviders | |
{ | |
/** | |
* This replicates pages from one container to another | |
*/ | |
public class ClonedByCategoryContentProvider : EPiServer.Core.ContentProvider | |
{ | |
private int CATEGORYID = -1; | |
private int _sourceid = -1; | |
private const string languageBranch = "en"; | |
private readonly IdentityMappingService _identityMappingService; | |
private readonly IContentTypeRepository _contentTypeRepository; | |
private readonly IContentFactory _contentFactory; | |
private readonly ServiceLocationHelper locator; | |
private readonly IUrlSegmentGenerator _urlSegment; | |
private readonly CategoryRepository categoryRepository; | |
private readonly IContentCacheKeyCreator _cacheCreator; | |
public ClonedCategoryContentProvider(IdentityMappingService identityMappingService, | |
IContentTypeRepository _ContentTypeRepository, | |
IContentFactory _ContentFactory, | |
ServiceLocationHelper _Locator, | |
IUrlSegmentGenerator _UrlSegment, | |
CategoryRepository _categoryRepository, | |
IContentCacheKeyCreator _CacheCreator) | |
{ | |
_identityMappingService = identityMappingService; | |
_contentTypeRepository = _ContentTypeRepository; | |
_contentFactory = _ContentFactory; | |
locator = _Locator; | |
_urlSegment = _UrlSegment; | |
categoryRepository = _categoryRepository; | |
_cacheCreator = _CacheCreator; | |
} | |
/// <summary> | |
/// Initializes the provider from configuration settings. | |
/// </summary> | |
/// <param name="key">The key.</param> | |
/// <param name="configParams">The config params.</param> | |
public override void Initialize(string key, NameValueCollection configParams) | |
{ | |
//Let base classes do their initialization | |
base.Initialize(key, configParams); | |
if (string.IsNullOrEmpty(configParams["sourceid"])) | |
{ | |
throw new ConfigurationErrorsException("ClonedCategoryContentProvider requires configuration attribute sourceid"); | |
} | |
int id; | |
if (int.TryParse(configParams["sourceid"],out id)) | |
{ _sourceid = id; } | |
if (!string.IsNullOrEmpty(configParams["categoryid"])) | |
{ | |
int catid; | |
if (int.TryParse(configParams["categoryid"], out catid)) | |
{ CATEGORYID = catid; } | |
} | |
} | |
protected override IContent LoadContent(ContentReference contentLink, ILanguageSelector languageSelector) | |
{ | |
MappedIdentity mappedIdentity = _identityMappingService.Get(contentLink); | |
if (mappedIdentity != null && mappedIdentity.ExternalIdentifier != null) | |
{ | |
// SOMETIME PARENT IS CALLED FIRST!! breaking change CMS 8 : Possible to set EntryPoint for content provider that have exactly 1 child | |
string strId = mappedIdentity.ExternalIdentifier.Segments[1]; | |
int intId; | |
var success = int.TryParse(strId, out intId); | |
if (success) | |
{ | |
var reference = new PageReference(intId); | |
PageData page = DataFactory.Instance.GetPage(reference, LanguageSelector.Fallback(languageBranch, true)); | |
if (page != null) | |
{ | |
return CreateMirroredContent(mappedIdentity, page); | |
} | |
} | |
} | |
return null; | |
} | |
protected override IList<GetChildrenReferenceResult> LoadChildrenReferencesAndTypes(ContentReference contentLink, string languageID, out bool languageSpecific) | |
{ | |
languageSpecific = false; | |
// Only the root node has children | |
if (contentLink == this.EntryPoint) | |
{ | |
PageReference pr = new PageReference(_sourceid); | |
var entryPoint = repository.Get<PageData>(this.EntryPoint); | |
if (!PageReference.IsNullOrEmpty(pr)) | |
{ | |
System.Collections.Generic.IList<GetChildrenReferenceResult> list = new List<GetChildrenReferenceResult>(); | |
var pages = DataFactory.Instance.GetChildren(pr, new LanguageSelector(entryPoint.LanguageBranch)).OrderByDescending(z => z.StartPublish).Where(s => s.CheckPublishedStatus(PagePublishedStatus.Published)); //.Where(x => x.Categories.IsEmpty); | |
foreach (PageData page in pages) | |
{ | |
if (page.Category.MemberOf(CATEGORYID) || CATEGORYID<1) | |
{ | |
Uri externalID = MappedIdentity.ConstructExternalIdentifier(ProviderKey, page.ContentLink.ToString()); | |
var mappedIdentity = _identityMappingService.Get(externalID, true); | |
System.Type modelType = null; | |
modelType = typeof(PageData); | |
ContentReference contentRef = page.PageLink; | |
GetChildrenReferenceResult result = new GetChildrenReferenceResult | |
{ | |
ContentLink = mappedIdentity.ContentLink, | |
ModelType = modelType, | |
IsLeafNode=true | |
}; | |
list.Add(result); | |
} | |
} | |
return list.Reverse().ToList(); | |
} | |
} | |
return null; | |
} | |
/// <summary> | |
/// Used for routing | |
/// </summary> | |
/// <param name="parentLink"></param> | |
/// <param name="urlSegment"></param> | |
/// <returns></returns> | |
protected override IList<MatchingSegmentResult> ListMatchingSegments(ContentReference parentLink, string urlSegment) | |
{ | |
var list = new List<MatchingSegmentResult>(); | |
foreach (var child in LoadChildren<IContent>(parentLink, LanguageSelector.Fallback("en", true), -1, -1)) | |
{ | |
var routable = child as IRoutable; | |
var isMatch = routable != null && urlSegment.Equals(routable.RouteSegment, StringComparison.OrdinalIgnoreCase); | |
if (isMatch) | |
{ | |
list.Add(new MatchingSegmentResult | |
{ | |
ContentLink = child.ContentLink | |
}); | |
} | |
} | |
return list; | |
} | |
public IContent CreateMirroredContent(MappedIdentity mappedIdentity, PageData original) | |
{ | |
PageData mirrored = original.CreateWritableClone(); | |
mirrored.ParentLink = new PageReference(EntryPoint.ID); | |
mirrored.ContentLink = mappedIdentity.ContentLink; | |
mirrored.ContentGuid = mappedIdentity.ContentGuid; | |
(mirrored as PageData).LinkType = PageShortcutType.Normal; | |
(mirrored as IRoutable).RouteSegment = (original as IRoutable).RouteSegment; | |
mirrored.LinkURL = ""; | |
return mirrored; | |
} | |
/// <summary> | |
/// The set cache settings. | |
/// </summary> | |
/// <param name="content"> | |
/// The content. | |
/// </param> | |
/// <param name="cacheSettings"> | |
/// The cache settings. | |
/// </param> | |
protected override void SetCacheSettings(IContent content, CacheSettings cacheSettings) | |
{ | |
if (content == null || cacheSettings == null) | |
{ | |
return; | |
} | |
// Make the cache of this content provider depend on the original content | |
cacheSettings.CacheKeys.Add(_cacheCreator.CreateCommonCacheKey(new ContentReference(content.ContentLink.ID))); | |
} | |
protected override void SetCacheSettings(ContentReference contentReference, IEnumerable<GetChildrenReferenceResult> children, CacheSettings cacheSettings) | |
{ | |
// Set a low cache setting so new items are fetched from data source, but keep the | |
// items already fetched for a long time in the cache. | |
cacheSettings.SlidingExpiration = TimeSpan.FromSeconds(30); | |
base.SetCacheSettings(contentReference, children, cacheSettings); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment