From 0e8ffe528a46229c1aab9fce5f67af902fd3ab46 Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Wed, 24 Apr 2013 14:57:20 -1000 Subject: [PATCH] Fixes: #U4-2149 - updates the logic for changing aliases for any content type. Now if an alias changes for any content type, the xml is regenerated for any entity that is of that content type. For DocumentType's this is slightly different because we regenerate the xml for the doc type and any document of the doc type's descendant types. --- .../controls/ContentTypeControlNew.ascx.cs | 8 +- src/umbraco.cms/businesslogic/Content.cs | 36 ++++----- src/umbraco.cms/businesslogic/ContentType.cs | 79 ++++++++++++++++++ .../businesslogic/member/Member.cs | 11 +-- .../businesslogic/member/MemberType.cs | 25 ++++++ src/umbraco.cms/businesslogic/web/Document.cs | 4 +- .../businesslogic/web/DocumentType.cs | 81 +++++++++++++++++++ 7 files changed, 213 insertions(+), 31 deletions(-) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/controls/ContentTypeControlNew.ascx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/controls/ContentTypeControlNew.ascx.cs index 780fab6246..a4fa8f65b3 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/controls/ContentTypeControlNew.ascx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/controls/ContentTypeControlNew.ascx.cs @@ -276,6 +276,10 @@ namespace umbraco.controls { _contentType = new cms.businesslogic.media.MediaType(docTypeId); } + else if (Request.Path.ToLowerInvariant().Contains("editmembertype.aspx")) + { + _contentType = new cms.businesslogic.member.MemberType(docTypeId); + } else { _contentType = new ContentType(docTypeId); @@ -291,9 +295,11 @@ namespace umbraco.controls /// private void RegenerateXmlCaches() { + _contentType.RebuildXmlStructuresForContent(); + + //special case for DocumentType's if (_contentType is DocumentType) { - umbraco.cms.businesslogic.web.Document.RePublishAll(); library.RefreshContent(); } } diff --git a/src/umbraco.cms/businesslogic/Content.cs b/src/umbraco.cms/businesslogic/Content.cs index d8c30138ae..3e5bfacb3d 100644 --- a/src/umbraco.cms/businesslogic/Content.cs +++ b/src/umbraco.cms/businesslogic/Content.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Data; using System.Xml; using Umbraco.Core.IO; +using Umbraco.Core.Logging; using umbraco.cms.businesslogic.property; using umbraco.cms.businesslogic.propertytype; using umbraco.DataLayer; @@ -416,8 +417,7 @@ namespace umbraco.cms.businesslogic /// public virtual void XmlGenerate(XmlDocument xd) { - XmlNode node = generateXmlWithoutSaving(xd); - SaveXmlDocument(node); + SaveXmlDocument(generateXmlWithoutSaving(xd)); } public virtual void XmlPopulate(XmlDocument xd, ref XmlNode x, bool Deep) @@ -428,27 +428,27 @@ namespace umbraco.cms.businesslogic x.AppendChild(p.ToXml(xd)); // attributes - x.Attributes.Append(xmlHelper.addAttribute(xd, "id", this.Id.ToString())); - x.Attributes.Append(xmlHelper.addAttribute(xd, "version", this.Version.ToString())); + x.Attributes.Append(XmlHelper.AddAttribute(xd, "id", this.Id.ToString())); + x.Attributes.Append(XmlHelper.AddAttribute(xd, "version", this.Version.ToString())); if (this.Level > 1) - x.Attributes.Append(xmlHelper.addAttribute(xd, "parentID", this.Parent.Id.ToString())); + x.Attributes.Append(XmlHelper.AddAttribute(xd, "parentID", this.Parent.Id.ToString())); else - x.Attributes.Append(xmlHelper.addAttribute(xd, "parentID", "-1")); - x.Attributes.Append(xmlHelper.addAttribute(xd, "level", this.Level.ToString())); - x.Attributes.Append(xmlHelper.addAttribute(xd, "writerID", this.User.Id.ToString())); + x.Attributes.Append(XmlHelper.AddAttribute(xd, "parentID", "-1")); + x.Attributes.Append(XmlHelper.AddAttribute(xd, "level", this.Level.ToString())); + x.Attributes.Append(XmlHelper.AddAttribute(xd, "writerID", this.User.Id.ToString())); if (this.ContentType != null) - x.Attributes.Append(xmlHelper.addAttribute(xd, "nodeType", this.ContentType.Id.ToString())); - x.Attributes.Append(xmlHelper.addAttribute(xd, "template", "0")); - x.Attributes.Append(xmlHelper.addAttribute(xd, "sortOrder", this.sortOrder.ToString())); - x.Attributes.Append(xmlHelper.addAttribute(xd, "createDate", this.CreateDateTime.ToString("s"))); - x.Attributes.Append(xmlHelper.addAttribute(xd, "updateDate", this.VersionDate.ToString("s"))); - x.Attributes.Append(xmlHelper.addAttribute(xd, "nodeName", this.Text)); + x.Attributes.Append(XmlHelper.AddAttribute(xd, "nodeType", this.ContentType.Id.ToString())); + x.Attributes.Append(XmlHelper.AddAttribute(xd, "template", "0")); + x.Attributes.Append(XmlHelper.AddAttribute(xd, "sortOrder", this.sortOrder.ToString())); + x.Attributes.Append(XmlHelper.AddAttribute(xd, "createDate", this.CreateDateTime.ToString("s"))); + x.Attributes.Append(XmlHelper.AddAttribute(xd, "updateDate", this.VersionDate.ToString("s"))); + x.Attributes.Append(XmlHelper.AddAttribute(xd, "nodeName", this.Text)); if (this.Text != null) - x.Attributes.Append(xmlHelper.addAttribute(xd, "urlName", this.Text.Replace(" ", "").ToLower())); - x.Attributes.Append(xmlHelper.addAttribute(xd, "writerName", this.User.Name)); + x.Attributes.Append(XmlHelper.AddAttribute(xd, "urlName", this.Text.Replace(" ", "").ToLower())); + x.Attributes.Append(XmlHelper.AddAttribute(xd, "writerName", this.User.Name)); if (this.ContentType != null) - x.Attributes.Append(xmlHelper.addAttribute(xd, "nodeTypeAlias", this.ContentType.Alias)); - x.Attributes.Append(xmlHelper.addAttribute(xd, "path", this.Path)); + x.Attributes.Append(XmlHelper.AddAttribute(xd, "nodeTypeAlias", this.ContentType.Alias)); + x.Attributes.Append(XmlHelper.AddAttribute(xd, "path", this.Path)); if (Deep) { diff --git a/src/umbraco.cms/businesslogic/ContentType.cs b/src/umbraco.cms/businesslogic/ContentType.cs index 9634047464..93e5cede1c 100644 --- a/src/umbraco.cms/businesslogic/ContentType.cs +++ b/src/umbraco.cms/businesslogic/ContentType.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Threading; using System.Runtime.CompilerServices; using System.Linq; +using System.Xml; using Umbraco.Core; using Umbraco.Core.Logging; using umbraco.cms.businesslogic.web; @@ -282,6 +283,84 @@ namespace umbraco.cms.businesslogic #region Public Properties + #region Regenerate Xml Structures + + /// + /// Used to rebuild all of the xml structures for content of the current content type in the cmsContentXml table + /// + [MethodImpl(MethodImplOptions.Synchronized)] + internal void RebuildXmlStructuresForContent() + { + //Clears all xml structures in the cmsContentXml table for the current content type + ClearXmlStructuresForContent(); + foreach (var i in GetContentIdsForContentType()) + { + RebuildXmlStructureForContentItem(i); + } + } + + /// + /// Returns all content ids associated with this content type + /// + /// + /// + /// This will generally just return the content ids associated with this content type but in the case + /// of a DocumentType where we can have inherited types, this will return all content Ids that are of + /// this content type or any descendant types as well. + /// + internal virtual IEnumerable GetContentIdsForContentType() + { + var ids = new List(); + //get all the content item ids of the current content type + using (var dr = SqlHelper.ExecuteReader(@"SELECT DISTINCT cmsContent.nodeId FROM cmsContent + INNER JOIN cmsContentType ON cmsContent.contentType = cmsContentType.nodeId + WHERE cmsContentType.nodeId = @nodeId", + SqlHelper.CreateParameter("@nodeId", this.Id))) + { + while (dr.Read()) + { + ids.Add(dr.GetInt("nodeId")); + } + dr.Close(); + } + return ids; + } + + /// + /// Rebuilds the xml structure for the content item by id + /// + /// + /// + /// This is not thread safe + /// + internal virtual void RebuildXmlStructureForContentItem(int contentId) + { + var xd = new XmlDocument(); + try + { + new Content(contentId).XmlGenerate(xd); + } + catch (Exception ee) + { + LogHelper.Error("Error generating xml", ee); + } + } + + /// + /// Clears all xml structures in the cmsContentXml table for the current content type + /// + internal virtual void ClearXmlStructuresForContent() + { + //Remove all items from the cmsContentXml table that are of this current content type + SqlHelper.ExecuteNonQuery(@"DELETE FROM cmsContentXml WHERE nodeId IN + (SELECT DISTINCT cmsContent.nodeId FROM cmsContent + INNER JOIN cmsContentType ON cmsContent.contentType = cmsContentType.nodeId + WHERE cmsContentType.nodeId = @nodeId)", + SqlHelper.CreateParameter("@nodeId", this.Id)); + } + + #endregion + /// /// Get or Sets the Container status of the Content Type. A Container Content Type doesn't show its children in the tree, /// but instead adds a tab when edited showing its children in a grid diff --git a/src/umbraco.cms/businesslogic/member/Member.cs b/src/umbraco.cms/businesslogic/member/Member.cs index e94ee3e642..958994e794 100644 --- a/src/umbraco.cms/businesslogic/member/Member.cs +++ b/src/umbraco.cms/businesslogic/member/Member.cs @@ -585,16 +585,7 @@ namespace umbraco.cms.businesslogic.member FireAfterSave(e); } } - - /// - /// Generates the xmlrepresentation of a member - /// - /// - public override void XmlGenerate(XmlDocument xd) - { - SaveXmlDocument(generateXmlWithoutSaving(xd)); - } - + /// /// Xmlrepresentation of a member /// diff --git a/src/umbraco.cms/businesslogic/member/MemberType.cs b/src/umbraco.cms/businesslogic/member/MemberType.cs index 30b04b5b23..3e204f512a 100644 --- a/src/umbraco.cms/businesslogic/member/MemberType.cs +++ b/src/umbraco.cms/businesslogic/member/MemberType.cs @@ -1,6 +1,7 @@ using System; using System.Data; using System.Xml; +using Umbraco.Core.Logging; using umbraco.cms.businesslogic.propertytype; using System.Linq; using umbraco.BusinessLogic; @@ -27,6 +28,30 @@ namespace umbraco.cms.businesslogic.member /// MemberType id public MemberType(Guid id) : base(id) { } + #region Regenerate Xml Structures + + /// + /// Rebuilds the xml structure for the member item by id + /// + /// + /// + /// This is not thread safe + /// + internal override void RebuildXmlStructureForContentItem(int contentId) + { + var xd = new XmlDocument(); + try + { + new Member(contentId).XmlGenerate(xd); + } + catch (Exception ee) + { + LogHelper.Error("Error generating xml", ee); + } + } + + #endregion + /// /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility /// diff --git a/src/umbraco.cms/businesslogic/web/Document.cs b/src/umbraco.cms/businesslogic/web/Document.cs index 925cdf2bdf..f2d4c47b0f 100644 --- a/src/umbraco.cms/businesslogic/web/Document.cs +++ b/src/umbraco.cms/businesslogic/web/Document.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Web; using System.Xml; using Umbraco.Core.IO; +using Umbraco.Core.Logging; using umbraco.BusinessLogic; using umbraco.BusinessLogic.Actions; using umbraco.cms.businesslogic.property; @@ -655,8 +656,7 @@ order by {1} } catch (Exception ee) { - Log.Add(LogTypes.Error, User.GetUser(0), dr.GetInt("nodeId"), - string.Format("Error generating xml: {0}", ee)); + LogHelper.Error("Error generating xml", ee); } } dr.Close(); diff --git a/src/umbraco.cms/businesslogic/web/DocumentType.cs b/src/umbraco.cms/businesslogic/web/DocumentType.cs index f254e1af74..a8af88fd6a 100644 --- a/src/umbraco.cms/businesslogic/web/DocumentType.cs +++ b/src/umbraco.cms/businesslogic/web/DocumentType.cs @@ -4,6 +4,7 @@ using System.Data; using System.Text; using System.Xml; using System.Linq; +using Umbraco.Core.Logging; using umbraco.BusinessLogic; using umbraco.cms.businesslogic.propertytype; using umbraco.DataLayer; @@ -294,6 +295,86 @@ namespace umbraco.cms.businesslogic.web #region Public Methods + #region Regenerate Xml Structures + + /// + /// This will return all PUBLISHED content Ids that are of this content type or any descendant types as well. + /// + /// + internal override IEnumerable GetContentIdsForContentType() + { + var ids = new List(); + int? currentContentTypeId = this.Id; + while (currentContentTypeId != null) + { + //get all the content item ids of the current content type + using (var dr = SqlHelper.ExecuteReader(@"SELECT DISTINCT cmsDocument.nodeId FROM cmsDocument + INNER JOIN cmsContent ON cmsContent.nodeId = cmsDocument.nodeId + INNER JOIN cmsContentType ON cmsContent.contentType = cmsContentType.nodeId + WHERE cmsContentType.nodeId = @contentTypeId AND cmsDocument.published = 1", + SqlHelper.CreateParameter("@contentTypeId", currentContentTypeId))) + { + while (dr.Read()) + { + ids.Add(dr.GetInt("nodeId")); + } + dr.Close(); + } + + //lookup the child content type if there is one + currentContentTypeId = SqlHelper.ExecuteScalar("SELECT nodeId FROM cmsContentType WHERE masterContentType=@contentTypeId", + SqlHelper.CreateParameter("@contentTypeId", currentContentTypeId)); + } + return ids; + } + + /// + /// Rebuilds the xml structure for the content item by id + /// + /// + /// + /// This is not thread safe + /// + internal override void RebuildXmlStructureForContentItem(int contentId) + { + var xd = new XmlDocument(); + try + { + new Document(contentId).XmlGenerate(xd); + } + catch (Exception ee) + { + LogHelper.Error("Error generating xml", ee); + } + } + + /// + /// Clears all xml structures in the cmsContentXml table for the current content type and any of it's descendant types + /// + /// + /// This is not thread safe + /// + internal override void ClearXmlStructuresForContent() + { + int? currentContentTypeId = this.Id; + while (currentContentTypeId != null) + { + //Remove all items from the cmsContentXml table that are of this current content type + SqlHelper.ExecuteNonQuery(@"DELETE FROM cmsContentXml WHERE nodeId IN + (SELECT DISTINCT cmsContent.nodeId FROM cmsContent + INNER JOIN cmsContentType ON cmsContent.contentType = cmsContentType.nodeId + WHERE cmsContentType.nodeId = @contentTypeId)", + SqlHelper.CreateParameter("@contentTypeId", currentContentTypeId)); + + //lookup the child content type if there is one + currentContentTypeId = SqlHelper.ExecuteScalar("SELECT nodeId FROM cmsContentType WHERE masterContentType=@contentTypeId", + SqlHelper.CreateParameter("@contentTypeId", currentContentTypeId)); + } + + } + + #endregion + public void RemoveTemplate(int templateId) { // remove if default template