Skip to content

Instantly share code, notes, and snippets.

@AThraen
Last active September 8, 2018 18:52
Show Gist options
  • Select an option

  • Save AThraen/17551484c5e2ebd9ce8aa6fcf9a4aaae to your computer and use it in GitHub Desktop.

Select an option

Save AThraen/17551484c5e2ebd9ce8aa6fcf9a4aaae to your computer and use it in GitHub Desktop.
Gist Fetching Block Content Provider for Episerver
using System.ComponentModel.DataAnnotations;
using EPiServer;
using EPiServer.Core;
using EPiServer.DataAbstraction;
using EPiServer.DataAnnotations;
using EPiServer.Web;
namespace AllanTech.Web.Business.ContentProviders
{
/// <summary>
/// Define the Block type to hold the Gist
/// </summary>
[ContentType(DisplayName = "Gist Block", GUID = "bca5e15d-976a-4b0e-8dc0-2b165e052170", Description = "", AvailableInEditMode =false)]
public class GistBlock : BlockData
{
[Editable(false)]
public virtual string Code { get; set; }
[Editable(false)]
public virtual string User { get; set; }
[Editable(false)]
[UIHint(UIHint.Textarea)]
public virtual string Description { get; set; }
[Editable(false)]
public virtual Url HtmlUrl { get; set; }
}
}
using System.Web.Mvc;
using EPiServer.Web.Mvc;
namespace AllanTech.Web.Business.ContentProviders
{
/// <summary>
/// Display the Gist Block
/// </summary>
public class GistBlockController : BlockController<GistBlock>
{
public const string SCRIPTLINE = "<script src=\"https://gist.github.com/{0}/{1}.js\"></script>";
public override ActionResult Index(GistBlock currentBlock)
{
return Content(string.Format(SCRIPTLINE, currentBlock.User, currentBlock.Code));
}
}
}
using EPiServer;
using EPiServer.Construction;
using EPiServer.Core;
using EPiServer.DataAbstraction;
using EPiServer.Framework.Cache;
using EPiServer.ServiceLocation;
using EPiServer.Web;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.Linq;
using System.Web;
namespace AllanTech.Web.Business.ContentProviders
{
public class GistsContentProvider : ContentProvider
{
public const string KEY = "GIST";
public string Username { get; set; }
//The following region maps from ID to Guids using the first 4 bytes of each guid to store the Int ID.
#region GuidMapping
public static Guid BASEGUID = new Guid("2900353B-DFFF-4EB8-A9BF-3CE237EFA96F");
public static int IdFromGuid(Guid g)
{
var b = BitConverter.ToInt32(g.ToByteArray().Take(4).ToArray(), 0);
return b;
}
public static bool IsGuidOk(Guid g)
{
var b1 = BASEGUID.ToByteArray();
var b2 = g.ToByteArray();
for (int i = 4; i < b1.Length; i++)
if (b1[i] != b2[i]) return false;
return true;
}
public static Guid GuidFromId(int Id)
{
var b1 = BASEGUID.ToByteArray();
var b2 = BitConverter.GetBytes(Id);
for (int i = 0; i < b2.Length; i++) b1[i] = b2[i];
return new Guid(b1);
}
#endregion
/// <summary>
/// Return a gistblock
/// </summary>
/// <param name="contentLink"></param>
/// <param name="languageSelector"></param>
/// <returns></returns>
protected override IContent LoadContent(ContentReference contentLink, ILanguageSelector languageSelector)
{
var gist=GetGists().Where(gb => (gb as IContent).ContentLink.CompareToIgnoreWorkID(contentLink)).Cast<IContent>().FirstOrDefault();
return gist;
}
/// <summary>
/// Used to fetch tree structure
/// </summary>
/// <param name="contentLink"></param>
/// <param name="languageID"></param>
/// <param name="languageSpecific"></param>
/// <returns></returns>
protected override IList<GetChildrenReferenceResult> LoadChildrenReferencesAndTypes(ContentReference contentLink, string languageID, out bool languageSpecific)
{
languageSpecific = false;
if (contentLink.CompareToIgnoreWorkID(EntryPoint))
{
//Root, list items
return GetGists().Select(g => new GetChildrenReferenceResult() { ContentLink = (g as IContent).ContentLink, IsLeafNode = true, ModelType = typeof(GistBlock) }).ToList();
}
return base.LoadChildrenReferencesAndTypes(contentLink, languageID, out languageSpecific);
}
/// <summary>
/// Used to resolve Guid, IDs and urls. Needs to work for Gists to remain in content areas.
/// </summary>
/// <param name="contentLink"></param>
/// <returns></returns>
protected override ContentResolveResult ResolveContent(ContentReference contentLink)
{
//Tricky bits
if (contentLink.ProviderName != this.ProviderKey) return null; //Not ours
ContentResolveResult crr = new ContentResolveResult();
crr.ContentLink = contentLink;
var content = LoadContent(contentLink, null);
crr.UniqueID = content.ContentGuid;
crr.ContentUri = ConstructContentUri(content.ContentTypeID, crr.ContentLink, crr.UniqueID);
return crr;
}
protected override ContentResolveResult ResolveContent(Guid contentGuid)
{
if (!IsGuidOk(contentGuid)) return null; //Not ours
ContentResolveResult crr = new ContentResolveResult();
crr.ContentLink = new ContentReference(IdFromGuid(contentGuid),this.ProviderKey);
var content = LoadContent(crr.ContentLink, null);
crr.UniqueID = contentGuid;
crr.ContentUri = ConstructContentUri(content.ContentTypeID, crr.ContentLink, crr.UniqueID);
return crr;
}
public override void Initialize(string name, NameValueCollection config)
{
base.Initialize(name, config);
if (config["username"] != null) Username = config["username"];
LoadGists();
}
/// <summary>
/// Get Gists from Cache
/// </summary>
/// <returns></returns>
protected List<GistBlock> GetGists()
{
var cache = ServiceLocator.Current.GetInstance<ISynchronizedObjectInstanceCache>();
var rt = cache.Get<List<GistBlock>>(KEY, ReadStrategy.Immediate);
if (rt == null)
{
rt = LoadGists();
cache.Insert(KEY, rt, new CacheEvictionPolicy(new TimeSpan(0, 30, 0), CacheTimeoutType.Absolute));
}
return rt;
}
/// <summary>
/// Load Gists from Github and create objects to put in cache
/// </summary>
/// <returns></returns>
private List<GistBlock> LoadGists()
{
//Load Gists
var gists = GistHelper.LoadGists(Username);
var _typeRepo = ServiceLocator.Current.GetInstance<IContentTypeRepository>();
var _contentFactory = ServiceLocator.Current.GetInstance<IContentFactory>();
var _contentRepo = ServiceLocator.Current.GetInstance<IContentRepository>();
ContentType type = _typeRepo.Load(typeof(GistBlock));
int i = 1000;
var Gists = new List<GistBlock>(gists.Count());
foreach (var g in gists.OrderBy(g => g.Created))
{
var fc = _contentFactory.CreateContent(type, new EPiServer.Construction.BuildingContext(type)
{
Parent = _contentRepo.Get<ContentFolder>(EntryPoint)
}) as GistBlock;
fc.Code = g.Id;
(fc as IContent).Name = g.Files.First();
fc.Description = g.Description;
fc.HtmlUrl = new Url(g.HtmlUrl);
fc.User = Username;
(fc as IVersionable).Status = VersionStatus.Published;
(fc as IVersionable).IsPendingPublish = false;
(fc as IVersionable).StartPublish = DateTime.Now;
(fc as ILocalizable).Language = CultureInfo.GetCultureInfo("en");
(fc as IContent).ContentLink = new ContentReference(i, this.ProviderKey);
(fc as IContent).ContentGuid = GuidFromId(i);
(fc as IChangeTrackable).Changed = g.Modified;
(fc as IChangeTrackable).CreatedBy = Username;
(fc as IChangeTrackable).Created = g.Created;
(fc as ILocalizable).MasterLanguage = CultureInfo.InvariantCulture;
(fc as ILocalizable).ExistingLanguages = new List<CultureInfo>();
fc.MakeReadOnly();
Gists.Add(fc);
i++;
}
return Gists;
}
}
}
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web;
namespace AllanTech.Web.Business.ContentProviders
{
/// <summary>
/// Helper class to fetch the gists from github
/// </summary>
public class GistHelper
{
public const string APIPath = "https://api.github.com/users/{0}/gists";
public static IEnumerable<Gist> LoadGists(string Username)
{
//Load url, create gist objects and return them
WebClient wc = new WebClient();
wc.Headers.Add(HttpRequestHeader.UserAgent, "Custom");
string s = wc.DownloadString(string.Format(APIPath, Username));
var array = JArray.Parse(s);
foreach (var gist in array)
{
var g = new Gist();
g.Description = gist["description"].Value<string>();
g.Id = gist["id"].Value<string>();
g.HtmlUrl = gist["html_url"].Value<string>();
g.Created = gist["created_at"].Value<DateTime>();
g.Modified = gist["updated_at"].Value<DateTime>();
var files = gist["files"].Values();
g.Files = files.Select(j => j["filename"].Value<string>()).ToList();
yield return g;
}
}
}
/// <summary>
/// The Gist as it is returned from Github
/// </summary>
public class Gist
{
public string Id { get; set; }
public string Description { get; set; }
public string HtmlUrl { get; set; }
public DateTime Created { get; set; }
public DateTime Modified { get; set; }
public List<string> Files { get; set; }
}
}
using System;
using System.Collections.Specialized;
using System.Linq;
using EPiServer;
using EPiServer.Configuration;
using EPiServer.Core;
using EPiServer.DataAccess;
using EPiServer.Framework;
using EPiServer.Framework.Initialization;
using EPiServer.Security;
using EPiServer.ServiceLocation;
namespace AllanTech.Web.Business.ContentProviders
{
[InitializableModule]
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class GistProviderInitializer : IInitializableModule
{
public static ContentFolder GetEntryPoint(string name)
{
var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
var folder = contentRepository.GetBySegment(ContentReference.GlobalBlockFolder, name, LanguageSelector.AutoDetect()) as ContentFolder;
if (folder == null)
{
folder = contentRepository.GetDefault<ContentFolder>(ContentReference.GlobalBlockFolder);
folder.Name = name;
contentRepository.Save(folder, SaveAction.Publish, AccessLevel.NoAccess);
}
return folder;
}
/// <summary>
/// Alternative to defining in web.config.
/// </summary>
/// <param name="context"></param>
public void Initialize(InitializationEngine context)
{
var gistprovider = new GistsContentProvider();
var providerValues = new NameValueCollection();
var entrypoint = GetEntryPoint("Gists").ContentLink;
providerValues.Add(ContentProviderElement.EntryPointString, entrypoint.ToString());
providerValues.Add(ContentProviderElement.CapabilitiesString, "None");
providerValues.Add("Username", "AThraen");
gistprovider.Initialize(GistsContentProvider.KEY, providerValues);
var providerManager = context.Locate.Advanced.GetInstance<IContentProviderManager>();
providerManager.ProviderMap.AddProvider(gistprovider);
}
public void Uninitialize(InitializationEngine context)
{
//Add uninitialization logic
}
}
}
using EPiServer.Shell;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace AllanTech.Web.Business.ContentProviders
{
[UIDescriptorRegistration]
public class GistUIDescriptor : UIDescriptor<GistBlock>
{
public GistUIDescriptor() : base("icon-document")
{
DefaultView = CmsViewNames.AllPropertiesView;
this.DisabledViews = new List<string>();
this.DisabledViews.Add(CmsViewNames.OnPageEditView);
this.DisabledViews.Add(CmsViewNames.PreviewView);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment