From eed13fcfdadd39e1f48856745b55b0446d9d5e06 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Fri, 29 Jun 2012 10:32:20 -0100 Subject: [PATCH] Fixed workitem:29297 - overloaded mssql db reads caused by creating styles on a stylesheet for use in the richtexteditor styles drop down (tinymce). Patch supplied by @tentonipete (unable to create fork/PR) --- .../businesslogic/web/StyleSheet.cs | 138 +++++++-------- .../businesslogic/web/StylesheetProperty.cs | 162 ++++++++++-------- .../tinyMCE3/TinyMCE.cs | 3 +- 3 files changed, 153 insertions(+), 150 deletions(-) diff --git a/src/umbraco.cms/businesslogic/web/StyleSheet.cs b/src/umbraco.cms/businesslogic/web/StyleSheet.cs index edcbfb8c4f..7969b34ee1 100644 --- a/src/umbraco.cms/businesslogic/web/StyleSheet.cs +++ b/src/umbraco.cms/businesslogic/web/StyleSheet.cs @@ -1,12 +1,11 @@ using System; using System.Collections; using System.IO; -using System.Data; -using System.Xml; -using umbraco.DataLayer; using System.Linq; using System.Text.RegularExpressions; +using System.Xml; using umbraco.cms.businesslogic.cache; +using umbraco.DataLayer; using umbraco.IO; namespace umbraco.cms.businesslogic.web @@ -33,9 +32,8 @@ namespace umbraco.cms.businesslogic.web //move old file _filename = value; - SqlHelper.ExecuteNonQuery("update cmsStylesheet set filename = '" + _filename + "' where nodeId = " + base.Id.ToString()); + SqlHelper.ExecuteNonQuery(string.Format("update cmsStylesheet set filename = '{0}' where nodeId = {1}", _filename, Id)); InvalidateCache(); - } } @@ -60,7 +58,9 @@ namespace umbraco.cms.businesslogic.web StylesheetProperty[] retVal = new StylesheetProperty[tmp.Length]; for (int i = 0; i < tmp.Length; i++) + { retVal[i] = StylesheetProperty.GetStyleSheetProperty(this.ChildrenOfAllObjectTypes[i].Id); + } m_properties = retVal; } return m_properties; @@ -101,49 +101,49 @@ namespace umbraco.cms.businesslogic.web } } - private void setupStyleSheet(bool loadFileData, bool updateStyleProperties) { // Get stylesheet data - IRecordsReader dr = SqlHelper.ExecuteReader("select filename, content from cmsStylesheet where nodeid = " + base.Id.ToString()); - if (dr.Read()) + using (IRecordsReader dr = SqlHelper.ExecuteReader("select filename, content from cmsStylesheet where nodeid = " + Id)) { - if (!dr.IsNull("filename")) - _filename = dr.GetString("filename"); - // Get Content from db or file - if (!loadFileData) + if (dr.Read()) { - if (!dr.IsNull("content")) - _content = dr.GetString("content"); - } - else - if (File.Exists(IOHelper.MapPath(SystemDirectories.Css + "/" + this.Text + ".css"))) + if (!dr.IsNull("filename")) + _filename = dr.GetString("filename"); + // Get Content from db or file + if (!loadFileData) + { + if (!dr.IsNull("content")) + _content = dr.GetString("content"); + } + else if (File.Exists(IOHelper.MapPath(String.Format("{0}/{1}.css", SystemDirectories.Css, this.Text)))) { - - StreamReader re = File.OpenText(IOHelper.MapPath(SystemDirectories.Css + "/" + this.Text + ".css")); - string input = null; - bool read = true; - _content = string.Empty; - // NH: Updates the reader to support properties - bool readingProperties = false; string propertiesContent = String.Empty; - while ((input = re.ReadLine()) != null && read) - { - if (input.Contains("EDITOR PROPERTIES")) - { - readingProperties = true; - } - else if (readingProperties) - { - propertiesContent += input.Replace("\n", "") + "\n"; - } - else - { - _content += input.Replace("\n", "") + "\n"; + using (StreamReader re = File.OpenText(IOHelper.MapPath(String.Format("{0}/{1}.css", SystemDirectories.Css, this.Text)))) + { + string input = null; + _content = string.Empty; + // NH: Updates the reader to support properties + bool readingProperties = false; + + while ((input = re.ReadLine()) != null && true) + { + if (input.Contains("EDITOR PROPERTIES")) + { + readingProperties = true; + } + else + if (readingProperties) + { + propertiesContent += input.Replace("\n", "") + "\n"; + } + else + { + _content += input.Replace("\n", "") + "\n"; + } } } - re.Close(); // update properties if (updateStyleProperties) @@ -154,16 +154,13 @@ namespace umbraco.cms.businesslogic.web } } } - + } } - dr.Close(); - } private void parseProperties(string propertiesContent) { - MatchCollection m = - Regex.Matches(propertiesContent, "([^{]*){([^}]*)}", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + MatchCollection m = Regex.Matches(propertiesContent, "([^{]*){([^}]*)}", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); foreach (Match match in m) { @@ -171,7 +168,7 @@ namespace umbraco.cms.businesslogic.web string cssClass = groups[1].Value.Replace("\n", "").Replace("\r", "").Trim().Trim(Environment.NewLine.ToCharArray()); string cssCode = groups[2].Value.Trim(Environment.NewLine.ToCharArray()); foreach (StylesheetProperty sp in this.Properties) - if (sp.Alias == cssClass) + if (sp.Alias == cssClass && sp.value != cssCode) // check before setting to avoid invalidating cache unecessarily sp.value = cssCode; } } @@ -183,7 +180,7 @@ namespace umbraco.cms.businesslogic.web CMSNode newNode = CMSNode.MakeNew(-1, ModuleObjectType, user.Id, 1, Text, Guid.NewGuid()); // Create the stylesheet data - SqlHelper.ExecuteNonQuery("insert into cmsStylesheet (nodeId, filename, content) values ('" + newNode.Id.ToString() + "','" + FileName + "',@content)", SqlHelper.CreateParameter("@content", Content)); + SqlHelper.ExecuteNonQuery(string.Format("insert into cmsStylesheet (nodeId, filename, content) values ('{0}','{1}',@content)", newNode.Id, FileName), SqlHelper.CreateParameter("@content", Content)); // save to file to avoid file coherency issues StyleSheet newCss = new StyleSheet(newNode.Id, false, false); @@ -229,7 +226,7 @@ namespace umbraco.cms.businesslogic.web string content = string.Empty; - using (StreamReader re = File.OpenText(IOHelper.MapPath(SystemDirectories.Css + "/" + fileStylesheets[i].ToString() + ".css"))) + using (StreamReader re = File.OpenText(IOHelper.MapPath(string.Format("{0}/{1}.css", SystemDirectories.Css, fileStylesheets[i])))) { content = re.ReadToEnd(); } @@ -257,7 +254,7 @@ namespace umbraco.cms.businesslogic.web if (!e.Cancel) { - File.Delete(IOHelper.MapPath(SystemDirectories.Css + "/" + this.Text + ".css")); + File.Delete(IOHelper.MapPath(String.Format("{0}/{1}.css", SystemDirectories.Css, this.Text))); foreach (StylesheetProperty p in this.Properties) p.delete(); SqlHelper.ExecuteNonQuery("delete from cmsStylesheet where nodeId = @nodeId", SqlHelper.CreateParameter("@nodeId", this.Id)); @@ -270,18 +267,16 @@ namespace umbraco.cms.businesslogic.web public void saveCssToFile() { - StreamWriter SW; - SW = File.CreateText(IOHelper.MapPath(SystemDirectories.Css + "/" + this.Text + ".css")); - string tmpCss; - //tmpCss = "/* GENERAL STYLES */\n"; - tmpCss = this.Content + "\n\n"; - tmpCss += "/* EDITOR PROPERTIES - PLEASE DON'T DELETE THIS LINE TO AVOID DUPLICATE PROPERTIES */\n"; - foreach (StylesheetProperty p in this.Properties) + using (StreamWriter SW = File.CreateText(IOHelper.MapPath(string.Format("{0}/{1}.css", SystemDirectories.Css, this.Text)))) { - tmpCss += p.ToString() + "\n"; + string tmpCss = this.Content + "\n\n"; + tmpCss += "/* EDITOR PROPERTIES - PLEASE DON'T DELETE THIS LINE TO AVOID DUPLICATE PROPERTIES */\n"; + foreach (StylesheetProperty p in this.Properties) + { + tmpCss += p + "\n"; + } + SW.Write(tmpCss); } - SW.Write(tmpCss); - SW.Close(); } public XmlNode ToXml(XmlDocument xd) @@ -308,26 +303,22 @@ namespace umbraco.cms.businesslogic.web return doc; } - public static StyleSheet GetStyleSheet(int id, bool setupStyleProperties, bool loadContentFromFile) { - return Cache.GetCacheItem(GetCacheKey(id), stylesheetCacheSyncLock, - TimeSpan.FromMinutes(30), - delegate - { - try - { - return new StyleSheet(id, setupStyleProperties, loadContentFromFile); - } - catch - { - return null; - } - }); - + return Cache.GetCacheItem(GetCacheKey(id), stylesheetCacheSyncLock, TimeSpan.FromMinutes(30), () => + { + try + { + return new StyleSheet(id, setupStyleProperties, loadContentFromFile); + } + catch + { + return null; + } + }); } - private void InvalidateCache() + public void InvalidateCache() { Cache.ClearCacheItem(GetCacheKey(this.Id)); } @@ -337,7 +328,6 @@ namespace umbraco.cms.businesslogic.web return UmbracoStylesheetCacheKey + id; } - //EVENTS /// /// The save event handler diff --git a/src/umbraco.cms/businesslogic/web/StylesheetProperty.cs b/src/umbraco.cms/businesslogic/web/StylesheetProperty.cs index 05d5b15d13..347cab0304 100644 --- a/src/umbraco.cms/businesslogic/web/StylesheetProperty.cs +++ b/src/umbraco.cms/businesslogic/web/StylesheetProperty.cs @@ -1,49 +1,49 @@ using System; -using System.Data; -using umbraco.DataLayer; - using umbraco.cms.businesslogic.cache; +using umbraco.DataLayer; namespace umbraco.cms.businesslogic.web { - public class StylesheetProperty : CMSNode - { - private string _alias; + public class StylesheetProperty : CMSNode + { + private string _alias; private string _value; private static object stylesheetPropertyCacheSyncLock = new object(); private static readonly string UmbracoStylesheetPropertyCacheKey = "UmbracoStylesheetProperty"; - private static Guid moduleObjectType = new Guid("5555da4f-a123-42b2-4488-dcdfb25e4111"); - // internal static moduleId = + private static Guid moduleObjectType = new Guid("5555da4f-a123-42b2-4488-dcdfb25e4111"); + // internal static moduleId = - public StylesheetProperty(int id) : base(id) - { - initProperty(); - } + // Used to check whether the parent stylesheet cache has already been cleared + private bool isParentStyleSheetCacheCleared; - public StylesheetProperty(Guid id) : base(id) - { - initProperty(); - } - private void initProperty() { + public StylesheetProperty(int id) : base(id) + { + initProperty(); + } - IRecordsReader dr = SqlHelper.ExecuteReader("Select stylesheetPropertyAlias,stylesheetPropertyValue from cmsStylesheetProperty where nodeId = " + this.Id.ToString()); - if (dr.Read()) - { - _alias = dr.GetString("stylesheetPropertyAlias"); - _value = dr.GetString("stylesheetPropertyValue"); - } - else - throw new ArgumentException("NO DATA EXSISTS"); - dr.Close(); + public StylesheetProperty(Guid id) : base(id) + { + initProperty(); + } - } + private void initProperty() { + IRecordsReader dr = SqlHelper.ExecuteReader("Select stylesheetPropertyAlias,stylesheetPropertyValue from cmsStylesheetProperty where nodeId = " + this.Id); + if (dr.Read()) + { + _alias = dr.GetString("stylesheetPropertyAlias"); + _value = dr.GetString("stylesheetPropertyValue"); + } + else + throw new ArgumentException("NO DATA EXSISTS"); + dr.Close(); + } - public StyleSheet StyleSheet() { - return new StyleSheet(this.Parent.Id, true, false); - } + public StyleSheet StyleSheet() { + return new StyleSheet(this.Parent.Id, true, false); + } public void RefreshFromFile() { // ping the stylesheet @@ -51,47 +51,51 @@ namespace umbraco.cms.businesslogic.web initProperty(); } + public string Alias { + get{return _alias;} + set { + SqlHelper.ExecuteNonQuery(String.Format("update cmsStylesheetProperty set stylesheetPropertyAlias = '{0}' where nodeId = {1}", value.Replace("'", "''"), this.Id)); + _alias=value; - public string Alias { - get{return _alias;} - set { - SqlHelper.ExecuteNonQuery("update cmsStylesheetProperty set stylesheetPropertyAlias = '"+ value.Replace("'","''")+"' where nodeId = " + this.Id); - _alias=value; InvalidateCache(); + InvalidateParentStyleSheetCache(); } - } - - public string value { - get {return _value;} - set { - SqlHelper.ExecuteNonQuery("update cmsStylesheetProperty set stylesheetPropertyValue = '"+ value.Replace("'","''")+"' where nodeId = " + this.Id); - _value=value; - InvalidateCache(); - } - } + } - public static StylesheetProperty MakeNew(string Text, StyleSheet sheet, BusinessLogic.User user) { - CMSNode newNode = CMSNode.MakeNew(sheet.Id, moduleObjectType, user.Id, 2, Text, Guid.NewGuid()); - SqlHelper.ExecuteNonQuery("Insert into cmsStylesheetProperty (nodeId,stylesheetPropertyAlias,stylesheetPropertyValue) values ('"+ newNode.Id +"','" + Text+ "','')"); - StylesheetProperty ssp = new StylesheetProperty(newNode.Id); + public string value { + get {return _value;} + set { + SqlHelper.ExecuteNonQuery(String.Format("update cmsStylesheetProperty set stylesheetPropertyValue = '{0}' where nodeId = {1}", value.Replace("'", "''"), this.Id)); + _value=value; + + InvalidateCache(); + InvalidateParentStyleSheetCache(); + } + } + + public static StylesheetProperty MakeNew(string Text, StyleSheet sheet, BusinessLogic.User user) { + CMSNode newNode = CMSNode.MakeNew(sheet.Id, moduleObjectType, user.Id, 2, Text, Guid.NewGuid()); + SqlHelper.ExecuteNonQuery(String.Format("Insert into cmsStylesheetProperty (nodeId,stylesheetPropertyAlias,stylesheetPropertyValue) values ('{0}','{1}','')", newNode.Id, Text)); + StylesheetProperty ssp = new StylesheetProperty(newNode.Id); NewEventArgs e = new NewEventArgs(); ssp.OnNew(e); return ssp; - } + } - public override void delete() - { + public override void delete() + { DeleteEventArgs e = new DeleteEventArgs(); FireBeforeDelete(e); if (!e.Cancel) { InvalidateCache(); + InvalidateParentStyleSheetCache(); SqlHelper.ExecuteNonQuery("delete from cmsStylesheetProperty where nodeId = @nodeId", SqlHelper.CreateParameter("@nodeId", this.Id)); base.delete(); FireAfterDelete(e); } - } + } public override void Save() { SaveEventArgs e = new SaveEventArgs(); @@ -104,28 +108,25 @@ namespace umbraco.cms.businesslogic.web } } - public override string ToString() - { - return this.Alias +" {\n"+ this.value+"\n}\n"; - } + public override string ToString() + { + return String.Format("{0} {{\n{1}\n}}\n", this.Alias, this.value); + } public static StylesheetProperty GetStyleSheetProperty(int id) { - return Cache.GetCacheItem(GetCacheKey(id), stylesheetPropertyCacheSyncLock, - TimeSpan.FromMinutes(30), - delegate - { - try - { - return new StylesheetProperty(id); - } - catch - { - return null; - } - }); - + return Cache.GetCacheItem(GetCacheKey(id), stylesheetPropertyCacheSyncLock, TimeSpan.FromMinutes(30), () => + { + try + { + return new StylesheetProperty(id); + } + catch + { + return null; + } + }); } private void InvalidateCache() @@ -133,14 +134,25 @@ namespace umbraco.cms.businesslogic.web Cache.ClearCacheItem(GetCacheKey(this.Id)); } + /// + /// Invalidates the parent style sheet cache. + /// + private void InvalidateParentStyleSheetCache() + { + // not sure whether should be doing this check, but if not then the stylesheet is invalidated, then reloaded from db in order to invalidate again. + if (!isParentStyleSheetCacheCleared) + { + umbraco.cms.businesslogic.web.StyleSheet.GetStyleSheet(this.Parent.Id, false, false).InvalidateCache(); + isParentStyleSheetCacheCleared = true; + } + } + private static string GetCacheKey(int id) { return UmbracoStylesheetPropertyCacheKey + id; } - - - //EVENTS + // EVENTS /// /// The save event handler /// @@ -219,5 +231,5 @@ namespace umbraco.cms.businesslogic.web if (AfterDelete != null) AfterDelete(this, e); } - } + } } diff --git a/src/umbraco.editorControls/tinyMCE3/TinyMCE.cs b/src/umbraco.editorControls/tinyMCE3/TinyMCE.cs index 0fdccfc913..97fcc08da5 100644 --- a/src/umbraco.editorControls/tinyMCE3/TinyMCE.cs +++ b/src/umbraco.editorControls/tinyMCE3/TinyMCE.cs @@ -150,7 +150,8 @@ namespace umbraco.editorControls.tinyMCE3 if (styleSheetId.Trim() != "") try { - var s = new StyleSheet(int.Parse(styleSheetId)); + var s = StyleSheet.GetStyleSheet(int.Parse(styleSheetId), false, false); + if (s.nodeObjectType == StyleSheet.ModuleObjectType) { cssFiles += IOHelper.ResolveUrl(SystemDirectories.Css + "/" + s.Text + ".css");