Files
Umbraco-CMS/src/Umbraco.Web/CanvasDesignerUtility.cs
2017-05-30 18:13:11 +02:00

283 lines
12 KiB
C#

using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Web.Http;
using AutoMapper;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Mvc;
using umbraco;
using Umbraco.Web.WebApi;
using System;
using System.Net.Http.Headers;
using System.Web;
using System.IO;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using System.Linq;
using System.Text.RegularExpressions;
using Umbraco.Web.Composing;
namespace Umbraco.Web
{
//TODO: This class needs to be overhauled:
// No statics that have dependencies!
// Make into a real class that accept the dependencies required.
// Remove all usages of singletons: HttpContext.Current, ApplicationContext.Current, UmbracoContext.Current, etc...
internal static class CanvasDesignerUtility
{
internal static string canvasdesignerStylePath = "/css/canvasdesigner/";
internal static string resultLessPath = canvasdesignerStylePath + @"{0}.less";
internal static string resultCssPath = canvasdesignerStylePath + @"{0}.css";
internal static string frontBasePath = HttpContext.Current.Server.MapPath(@"\css\canvasdesigner\");
// get style box by tag
internal static String GetStyleBlock(string source, string name)
{
string startTag = string.Format("/***start-{0}***/", name);
string endTag = string.Format("/***end-{0}***/", name);
int indexStartTag = source.IndexOf(startTag);
int indexEndTag = source.IndexOf(endTag);
if (indexStartTag >= 0 && indexEndTag >= 0)
return source.Substring(indexStartTag, indexEndTag - indexStartTag).Replace(startTag, "").Replace(endTag, "");
else
return "";
}
// Get less parameters from lessPath file, both general parameters and grid parameters
internal static string GetLessParameters(int pageId)
{
// Load current page
var contentService = Current.Services.ContentService;
IContent content = contentService.GetById(pageId);
// Get less file path from the page Id
string lessPath = GetStylesheetPath(content.Path.Split(','), true);
string paramBlock = string.Empty;
if (System.IO.File.Exists(HttpContext.Current.Server.MapPath(lessPath)))
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(HttpContext.Current.Server.MapPath(lessPath)))
{
string lessContent = sr.ReadToEnd();
foreach (Match match in Regex.Matches(lessContent, string.Format("@([^;\n]*):([^;\n]*);")))
{
paramBlock = paramBlock + match.Groups[0].Value + "\r\n";
}
}
}
return paramBlock;
}
// Get inherited pageId with canvasdesigner
internal static int GetParentOrSelfTunedPageId(string[] path, bool preview)
{
string styleCanvasdesigner = preview ? @"{0}{1}.less" : "{0}{1}.css";
foreach (var page in path.OrderByDescending(r => path.IndexOf(r)))
{
string stylePath = HttpContext.Current.Server.MapPath(string.Format(styleCanvasdesigner, canvasdesignerStylePath, page));
if (System.IO.File.Exists(stylePath))
{
return int.Parse(page);
}
}
if (preview)
return int.Parse(path[1]);
else
return -1;
}
// Get stylesheet path for current page
internal static string GetStylesheetPath(string[] path, bool preview)
{
string styleCanvasdesigner = preview ? @"{0}{1}.less" : "{0}{1}.css";
int tunedPageId = GetParentOrSelfTunedPageId(path, preview);
if (tunedPageId >0)
return string.Format(styleCanvasdesigner, canvasdesignerStylePath, tunedPageId);
else
return string.Empty;
}
// Create new less file
internal static string CreateOrUpdateLessFile(int pageId, string configs)
{
// Load current page
var contentService = Current.Services.ContentService;
IContent content = contentService.GetById(pageId);
// Get less file path from the page Id
string lessPath = GetStylesheetPath(content.Path.Split(','), true);
// If less file exist, Load its content
string lessContent = string.Empty;
if (System.IO.File.Exists(HttpContext.Current.Server.MapPath(lessPath)))
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(HttpContext.Current.Server.MapPath(lessPath)))
{
lessContent = sr.ReadToEnd();
}
}
// Parse the config file
// for each config read and add less script in global less
dynamic canvasdesignerConfigs = Newtonsoft.Json.Linq.JObject.Parse(configs.ToString());
foreach (var configuration in canvasdesignerConfigs.configs)
{
if (configuration.editors != null)
{
foreach (var editorItem in configuration.editors)
{
var type = (editorItem.type != null && !string.IsNullOrEmpty(editorItem.type.ToString())) ? editorItem.type.ToString() : string.Empty;
var alias = (editorItem.alias != null && !string.IsNullOrEmpty(editorItem.alias.ToString())) ? editorItem.alias.ToString() : string.Empty;
var schema = (configuration.schema != null && !string.IsNullOrEmpty(configuration.schema.ToString())) ? configuration.schema.ToString() : alias;
schema = (editorItem.schema != null && !string.IsNullOrEmpty(editorItem.schema.ToString())) ? editorItem.schema.ToString() : schema;
if (string.IsNullOrEmpty(GetStyleBlock(lessContent, "lessParam-" + alias)))
{
// read the less model file
var lessModelPath = string.Format("/Umbraco/assets/less/{0}.less", type);
var lessModel = string.Empty;
if (System.IO.File.Exists(HttpContext.Current.Server.MapPath(lessModelPath)))
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(HttpContext.Current.Server.MapPath(lessModelPath)))
{
lessModel = sr.ReadToEnd();
}
}
lessContent = lessContent + Environment.NewLine + lessModel
.Replace("-ALIAS-", alias.ToLower())
.Replace("-SCHEMA-", schema);
foreach (var parameter in editorItem)
{
lessContent = lessContent.Replace("-" + parameter.Name.ToString().ToUpper() + "-", parameter.Value.ToString());
}
}
}
}
}
//// Create front directory if necesary
if (!Directory.Exists(frontBasePath))
Directory.CreateDirectory(frontBasePath);
// Save less file
if (string.IsNullOrEmpty(lessPath)) lessPath = string.Format("{0}{1}.less", canvasdesignerStylePath, pageId);
using (System.IO.StreamWriter file = new System.IO.StreamWriter(HttpContext.Current.Server.MapPath(lessPath)))
{
file.Write(lessContent);
}
return lessPath;
}
// Save and publish less style
internal static void SaveAndPublishStyle(string parameters, int pageId, bool inherited)
{
// Get inherited tuned pageId and path
var contentService = Current.Services.ContentService;
IContent content = contentService.GetById(pageId);
int inheritedTunedPageId = CanvasDesignerUtility.GetParentOrSelfTunedPageId(content.Path.Split(','), true);
// Load inherited Less content
string inheritedLessContent = string.Empty;
using (System.IO.StreamReader sr = new System.IO.StreamReader(HttpContext.Current.Server.MapPath(string.Format(resultLessPath, inheritedTunedPageId))))
{
inheritedLessContent = sr.ReadToEnd();
}
// Update pageId if parameters have changed
if (inherited) pageId = inheritedTunedPageId;
// Create front directory if necesary
if (!Directory.Exists(frontBasePath))
Directory.CreateDirectory(frontBasePath);
// Prepare parameters and gf block and replace with the new value
string newParamBlock = string.Empty;
string newGfBlock = string.Empty;
foreach (string parameter in parameters.Trim().Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries))
{
if (parameter.IndexOf("@import") < 0)
{
string name = parameter.Substring(0, parameter.IndexOf(":"));
string value = parameter.Substring(parameter.IndexOf(":") + 1);
if (string.IsNullOrEmpty(value)) value = "''";
inheritedLessContent = Regex.Replace(inheritedLessContent, string.Format("{0}:([^;\n]*);", name), string.Format("{0}:{1};", name, value));
}
else
{
newGfBlock += parameter + ";" + Environment.NewLine;
}
}
// Save less file
using (System.IO.StreamWriter file = new System.IO.StreamWriter(HttpContext.Current.Server.MapPath(string.Format(resultLessPath, pageId))))
{
file.Write(inheritedLessContent);
}
// Compile the Less file
string compiledStyle = GetCssFromLessString(newGfBlock + inheritedLessContent, false, true, true).Replace("@import", "@IMPORT");
// Save compiled file
using (System.IO.StreamWriter file = new System.IO.StreamWriter(HttpContext.Current.Server.MapPath(string.Format(resultCssPath, pageId))))
{
file.Write(compiledStyle);
}
}
// Delete canvasdesigner style
internal static void DeleteStyle(int pageId)
{
// Get inherited tuned pageId and path
var contentService = Current.Services.ContentService;
IContent content = contentService.GetById(pageId);
int inheritedTunedPageId = CanvasDesignerUtility.GetParentOrSelfTunedPageId(content.Path.Split(','), true);
// Path to the less and css files
string newResultLessPath = HttpContext.Current.Server.MapPath(string.Format(resultLessPath, inheritedTunedPageId));
string newResultCssPath = HttpContext.Current.Server.MapPath(string.Format(resultCssPath, inheritedTunedPageId));
// Delete all style file for this page
System.IO.File.Delete(newResultLessPath);
System.IO.File.Delete(newResultCssPath);
}
// Compile and compress less style
private static string GetCssFromLessString(string css, Boolean cacheEnabled, Boolean minifyOutput, Boolean disableVariableRedefines)
{
var config = dotless.Core.configuration.DotlessConfiguration.GetDefaultWeb();
config.DisableVariableRedefines = disableVariableRedefines;
config.CacheEnabled = cacheEnabled;
config.MinifyOutput = minifyOutput;
return dotless.Core.LessWeb.Parse(css, config);
}
}
}