Skip to content

Instantly share code, notes, and snippets.

@jeremy-farrance
Last active August 25, 2021 13:55
Show Gist options
  • Save jeremy-farrance/6892f18bf0fd4d60a688d0ca418e449b to your computer and use it in GitHub Desktop.
Save jeremy-farrance/6892f18bf0fd4d60a688d0ca418e449b to your computer and use it in GitHub Desktop.
AccuKit (formerly RazorKit) with DNN platform OHS tools and misc functions for projects
@functions {
public static string Version() { return "20200822"; }
}
@* >>> put me in your DNN /App_Code folder
>>> there are (at least) 2 files, see AccuTheme.cshtml (below)
>>> home = https://gist.github.com/jeremy-farrance/6892f18bf0fd4d60a688d0ca418e449b
// TODO - updates and changes needed
- Move all compatibility stubs (e.g. ) so a separate section at the bottom
- should AccuKit be dependent on AccuTheme (and others) or vice versa??
- above (dependency Q) is related to duplication (e.g. SkinPath, isAccuratyIP, etc)
- rethink and finalize all the Poly(), sbe() stuff; settle on a name!!
Changes and updates:
- added GetVersion() using reflection to look inside a DLL to get its version
- reorganized, comment improvements, added CML's isHome(), added .Version() 20200822 JRF
- renamed from /jeremy-farrance/RazorKit.cshtml 20200721 JRF
- combined all previous versions in to this one 20200721 JRF
- added ThemePath() and ThemeCssPath() 20200720 JRF
- added Razor.Blade (dependency) and misc cleanups, self-docs 202004 JRF
- added initial Polymorph and business rules 20200102 JRF
- added to project and renamed to razor-kit.cshtml 20190313 JRF
- added GetIpFromHostname(); resolve a DNS entry (FQDN)
- added GetIpAddress() of the website visitor
- New 20181015 JRF
Recap:
Accuraty's shared standard utility functions for OHS (open heart surgery) work on DNN Platform projects.
AccuKit.Functions() can be called from 2sxc Views, RazorHost scripts, WebForms (.ascx, .aspx) skin files;
any code-behind server side code that runs post-compiled.
AccuKit is common, reusable functions in an OHS style project,
usually in support of post-go-live maintenance, modifications,
additions, and long term website project work for a client.
Things we keep needing and writing small bits of code for over
the years that make sense to re-use.
Reminder: methods must be "public static"
A few usage examples:
if (AccuKit.Poly() == "dev") {
// true, do dev stuff
} else {
// false, nop
}
// live vs dev in sep folders
@RenderPage(AccuKit.Poly("dev/", "live/") + "__TEMP_this.cshtml")
// live in root, dev in subfolder
@RenderPage(AccuKit.Poly("dev/") + "__TEMP_this.cshtml")
@if ( @AccuKit.GetIpAddress() == "192.241.63.162" ) { do stuff; }
@if ( @AccuKit.GetIpFromHostname("abbv.accuraty.net).Contains("999") ) { do stuff; }
// for places where the {SkinPath} is not a simple call
@AccuKit.ThemePath() = /Portals/_default/skins/abbv/
// pass in something and...
AccuKit.ThemeCssPath("secret/folder") = /Portals/_default/skins/abbv/secret/folder/
2sxc example for AccuTheme; /Modules/*.scss compiles to {SkinPath}/public
// pass in nothing and it defaults to /public
@AccuKit.ThemeCssPath() = /Portals/_default/skins/abbv/public/
// then in 2sxc View (.cshtml
<link rel="stylesheet" href="@AccuKit.ThemeCssPath()/2sxc-carousel.css" data-enableoptimizations="true" />
Report the version of a DLL in the bin folder?
<pre>
Newtonsoft.Json: @AccuKit.GetVersion("Newtonsoft.Json")
ImageResizer: @AccuKit.GetVersion("ImageResizer")
Blade version: @AccuKit.GetVersion("ToSic.Razor")
NonExistentLibrary: @AccuKit.GetVersion("NonExistentLibrary") // not found
</pre>
*@
@using System.Text.RegularExpressions
@using System.Net
@using System.Net.Sockets
@using ToSic.Razor.Blade
@using DotNetNuke.Entities.Portals
@functions {
// .NET compiles any .cshtml file in /App_Code
// the exposed methods need to be public and static!
// Sections
// // Theme (move to AccuTheme.cshtml soon?)
// // Dnn
// // Polymorphism
// // Server/URL
// //
// // Theme; in support of the Theme (Dnn skin, containers, etc)
// do something different because this is the site's Home page
public static bool isHome() {
return PortalSettings.Current.ActiveTab.TabID == PortalSettings.Current.HomeTabId;
}
// Accuraty's SkinPath variable for DNN 9.2+, root of the skin folder
// PortalSettings.Current gets the instance
// https://dnndocs.com/api/DotNetNuke.Entities.Portals.PortalSettings.html
public static string ThemePath() {
return PortalSettings.Current.ActiveTab.SkinPath;
}
// this needs a rethink, either ThemePublicPath(), ThemeMediaPath(), etc
// seems like we'd need to easily path to Theme root,
// then public/dist, media (images, icons, other), and more in the future?
// or maybe ThemePath("part", pathfolder) ?
// or maybe ThemePath().Part(pathFolder) ?
// Where are the skin's compiled, public CSS files?
public static string ThemeCssPath(string pathFolder = "public") {
return ThemePath() + pathFolder + "/";
}
// Where are the skin's optimized, public image files?
public static string ThemeImagePath(string pathFolder = "public/media/images") {
return ThemePath() + pathFolder + "/";
}
// // Dnn; Conveniences, renames, utilities
// is the CURRENT user Super (DNN Host)?
public static bool isSuper() {
return DotNetNuke.Entities.Users.UserController.GetCurrentUserInfo().IsSuperUser;
}
// old function name, for compatibility?
public static bool IsSuper() { return isSuper(); }
// // Polymorphism; use this to switch code/path logic based on rules; IP, Role, URL Params, etc
// sbe = Switch Between Editions; based on Role, IP, etc.
public static string sbe(string returnTrue = "dev", string returnFalse = "") {
return sbeRule() ? returnTrue : returnFalse;
}
// old name for above, deprecated
public static string Poly(string returnTrue = "dev", string returnFalse = "") { return sbe(returnTrue, returnFalse); }
// sbeRule is the (currently hardcoded) true/false; false meaning show normal/live/production
// currently we hardcode this, in future? there could be switches for combinations (needs)
public static bool sbeRule() {
// return false; // if this is uncommented, any sbe()s are turned off
// return isAccuratyIP(); // just people at ASL office
return (isSuper() && isAccuratyIP()); //at ASL office AND Supers
}
// does the URL contain the expected secret?
// do {something} only if URL has "/demo/on" or "&demo=on" added
public static bool isUrlSpecial(string urlParamName = "demo", string urlParamValue = "on") {
return urlQSParam(urlParamName, "") == urlParamValue;
}
// // Server/URL; utilities that simplify common needs...
// safely fetch our URL Param
public static string urlQSParam(string urlParamName = "demo", string returnFalse = "") {
if(Text.Has(Request.QueryString[urlParamName], false)) {
return Request.QueryString[urlParamName];
} else {
return returnFalse;
}
}
// by IP, is the remote IP address a known Accuraty WAN IP?
public static bool isAccuratyIP() {
var list = new List<string> {
"127.0.0.1", // localhost
"192.241.63.162", // 309SN
"108.220.164.129", // 712WV (JRF)
"67.167.3.4", // CML
};
return list.Contains(GetIpAddress());
}
// old function name, for compatibility?
public static bool IsAccuratyIP() { return isAccuratyIP(); }
// Get IP address of the visitor
public static string GetIpAddress() {
string stringIpAddress;
stringIpAddress = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (stringIpAddress == null)
{
stringIpAddress = Request.ServerVariables["REMOTE_ADDR"];
}
return stringIpAddress;
}
// Get IP from Hostname (FQDN), >> does a potentially slow DNS lookup
public static string GetIpFromHostname(string Hostname) {
string ip = "";
try
{
IPHostEntry ipHostEntry = Dns.GetHostEntry(Hostname);
if ( ipHostEntry.AddressList.Length > 0 )
{
//ip = ipHostEntry.AddressList[0].Address.ToString();
ip = ipHostEntry.AddressList[0].ToString();
}
else
{
ip = "No information found.";
}
}
catch ( Exception )
{
ip = "An unspecified error occured.";
return ip;
}
return ip;
}
// Turn any text or title in to a URL Slug, source = https://stackoverflow.com/questions/2920744/url-slugify-algorithm-in-c
public static string ToSlug(string phrase) {
byte[] bytes = System.Text.Encoding.GetEncoding("Cyrillic").GetBytes(phrase);
string str = System.Text.Encoding.ASCII.GetString(bytes);
str = str.ToLower();
// invalid chars
str = Regex.Replace(str, @"[^a-z0-9\s-]", "");
// convert multiple spaces into one space
str = Regex.Replace(str, @"\s+", " ").Trim();
// cut and trim
str = str.Substring(0, str.Length <= 45 ? str.Length : 45).Trim();
str = Regex.Replace(str, @"\s", "-"); // hyphens
return str;
}
// // misc, no section/category yet?
// Get the width from an image file
// <pre>@HttpContext.Current.Server.MapPath(Content.Image)</pre>
public static int imageGetWidthfromFile(string pathFile)
{
if (System.IO.Path.GetExtension(pathFile) == "svg")
{
return 0;
}
using (System.Drawing.Image sourceImage = System.Drawing.Image.FromFile(HttpContext.Current.Server.MapPath(pathFile)))
{
      return sourceImage.Width;
    }
  }
// old name for above, deprecated
  public static int GetWidthfromImageFile(string pathFile) { return imageGetWidthfromFile(pathFile); }
// Get the height from an image file
public static int imageGetHeightfromFile(string pathFile)
{
if (System.IO.Path.GetExtension(pathFile) == "svg")
{
return 0;
}
    using (System.Drawing.Image sourceImage = System.Drawing.Image.FromFile(HttpContext.Current.Server.MapPath(pathFile))) {
      return sourceImage.Width;
    }
  }
// Strip and Format a Phone number; has defaults and allows optional
public static string FormatPhone(string PhoneNumber = "444-555-1212", string PhoneFormat = "{0:(###) ###-####}") {
// remove non-digits and pad (right) with zeros if we have less than 10 numbers
string numericPhone = new String(PhoneNumber.Where(Char.IsDigit).ToArray()).PadRight(10, '0');
return String.Format(PhoneFormat, long.Parse(numericPhone));
}
// Get the version of an installed DLL in /bin
// expecting "ToSic.Razor" and we assume /bin and add .dll
public static string GetVersion(string pathFile) {
string target = HttpContext.Current.Server.MapPath("bin/" + pathFile + ".dll");
if(System.IO.File.Exists(target)) {
return System.Reflection.Assembly.LoadFrom(target).GetName().Version.ToString();
}
else {
return "DLL not found";
}
}
}
@using System.Text.RegularExpressions
@using System.Net
@using System.Net.Sockets
@using DotNetNuke.Entities.Portals
@* @using ToSic.Razor.Blade *@
@functions {
// As of Aug 2021, this is an exact copy of same file in AccuTheme (May 2021)
// Soonish, we need to sort out usage between this file, AccuKit, and __debug.ascx - 20210814 JRF
// ==========================================================================
// Sections
// --
// 1. Theme
// 2. Misc
// X. Dnn >> moved to AccuKit
// X. Polymorphism >> moved to AccuKit
// X. Other >> moved to AccuKit
// ==========================================================================
public static string Version() { return "20210528"; }
//
// 1. Theme
// ========
//
// Skin, Containers, etc.
// --------------------------------------------------------------------------
// Accuraty's SkinPath variable for DNN 9+, root of the skin folder
// https://dnndocs.com/api/DotNetNuke.Entities.Portals.PortalSettings.html
public static string SkinPath = PortalSettings.Current.ActiveTab.SkinPath;
public static string SkinCssPath = SkinPath + "dist";
public static string SkinJsPath = SkinPath + "dist";
public static string SkinMediaPath = SkinPath + "dist/media";
public static string SkinImagesPath = SkinMediaPath + "/images";
public static string SkinSvgPath = SkinMediaPath + "/svg";
public static bool skinFileExists(string skinPath, string fileName)
{
return System.IO.File.Exists(HttpContext.Current.Server.MapPath(skinPath + "/" + fileName));
}
public static bool isHomePage() {
return PortalSettings.Current.ActiveTab.TabID == PortalSettings.Current.HomeTabId;
}
public static HtmlString AccuIcon(string iconName) {
string name = ToSlug(iconName);
string svgSprite = SkinSvgPath + "/AccuTheme-icons.svg";
string output = "<svg class=\"svg svg--icon\" width=\"1em\" height=\"1em\" fill=\"currentColor\" focusable=\"false\" aria-hidden=\"true\"><use xlink:href=\"" + svgSprite + "#" + name + "\"></use></svg>";
return new HtmlString(output);
}
public static HtmlString BootstrapIcon(string iconName) {
string name = ToSlug(iconName);
string svgSprite = SkinSvgPath + "/bootstrap-icons.svg";
string output = "<svg class=\"svg svg--icon bi\" width=\"1em\" height=\"1em\" fill=\"currentColor\" focusable=\"false\" aria-hidden=\"true\"><use xlink:href=\"" + svgSprite + "#" + name + "\"></use></svg>";
return new HtmlString(output);
}
//
// 2. Misc
// =============
//
// Utilities that simplify common needs (in AccuTheme)
// --------------------------------------------------------------------------
// by IP, is the remote IP address a known Accuraty WAN IP?
public static bool isAccuratyIP() {
var list = new List<string> {
"127.0.0.1", // localhost
"192.241.63.162", // 309SN
"108.220.164.129", // 712WV (JRF)
"67.167.3.4", // CML
};
return list.Contains(GetIpAddress());
}
// Get IP address of the visitor
public static string GetIpAddress() {
string stringIpAddress;
stringIpAddress = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (stringIpAddress == null) {
stringIpAddress = Request.ServerVariables["REMOTE_ADDR"];
}
return stringIpAddress;
}
// Turn any text or title in to a URL Slug
// https://stackoverflow.com/questions/2920744/url-slugify-algorithm-in-c
public static string ToSlug(string phrase) {
byte[] bytes = System.Text.Encoding.GetEncoding("Cyrillic").GetBytes(phrase);
string str = System.Text.Encoding.ASCII.GetString(bytes);
str = str.ToLower();
// invalid chars
str = Regex.Replace(str, @"[^a-z0-9\s-]", "");
// convert multiple spaces into one space
str = Regex.Replace(str, @"\s+", " ").Trim();
// cut and trim
str = str.Substring(0, str.Length <= 45 ? str.Length : 45).Trim();
str = Regex.Replace(str, @"\s", "-"); // hyphens
return str;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment