From f95cfc2ee0e57669080d8d2a66763d5fee2891de Mon Sep 17 00:00:00 2001
From: Shannon Deminick
Date: Tue, 29 Jan 2013 21:18:17 +0600
Subject: [PATCH 01/43] Changes v4.x config transforms
---
src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 4 ----
src/Umbraco.Web.UI/web.Template.ShandemVaio.Debug.config | 2 +-
2 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
index f5c7a726b0..09d081e51f 100644
--- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
+++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
@@ -2303,10 +2303,6 @@
Web.Template.config
-
- Web.Template.config
- Designer
- Web.Template.config
diff --git a/src/Umbraco.Web.UI/web.Template.ShandemVaio.Debug.config b/src/Umbraco.Web.UI/web.Template.ShandemVaio.Debug.config
index ff4fbbd217..30a793e0e0 100644
--- a/src/Umbraco.Web.UI/web.Template.ShandemVaio.Debug.config
+++ b/src/Umbraco.Web.UI/web.Template.ShandemVaio.Debug.config
@@ -19,7 +19,7 @@
+ value="4.11.4"/>
Date: Tue, 29 Jan 2013 21:19:16 +0600
Subject: [PATCH 02/43] Fixes: #U4-1170 - template with hyphen or dash
---
src/Umbraco.Web/Mvc/RenderRouteHandler.cs | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs
index fab342df7b..30bac69666 100644
--- a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs
+++ b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs
@@ -271,9 +271,10 @@ namespace Umbraco.Web.Mvc
// to the index Action
if (publishedContentRequest.HasTemplate)
{
- //check if the custom controller has an action with the same name as the template name (we convert ToUmbracoAlias since the template name might have invalid chars).
- //NOTE: This also means that all custom actions MUST be PascalCase.. but that should be standard.
- var templateName = publishedContentRequest.Template.Alias.Split('.')[0].ToUmbracoAlias(StringAliasCaseType.PascalCase);
+ //the template Alias should always be already saved with a safe name.
+ //if there are hyphens in the name and there is a hijacked route, then the Action will need to be attributed
+ // with the action name attribute.
+ var templateName = publishedContentRequest.Template.Alias.Split('.')[0];
def.ActionName = templateName;
}
From 3fda0308ac640afcf52d5e74191867ba97b8d5fb Mon Sep 17 00:00:00 2001
From: Shannon Deminick
Date: Wed, 30 Jan 2013 04:56:28 +0600
Subject: [PATCH 03/43] Fixes: #U4-1594 - SQL for SqlOptimizedSingle not
correct for published state Fixes: #U4-1596 - new GetPathPublishedDescendants
method on Document for optimizations Fixes: #U4-1595 - Obsoletes
HasPublishedVersion() method and ensures lazy loading of Published property,
as well as ensuring that the backing property is set correctly on first load
(optmization) Fixes: #U4-1597 - PathPublished property should be set in an
optimized way and/or lazy loaded if it cannot be
---
.../umbraco/editContent.aspx.cs | 9 +-
src/umbraco.cms/businesslogic/web/Document.cs | 249 +++++++++++++-----
2 files changed, 191 insertions(+), 67 deletions(-)
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs
index b342ce9080..e80d1d7263 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs
@@ -82,7 +82,7 @@ namespace umbraco.cms.presentation
}
// we need to check if there's a published version of this document
- _documentHasPublishedVersion = _document.HasPublishedVersion();
+ _documentHasPublishedVersion = _document.Published;
// Check publishing permissions
if (!base.getUser().GetPermissions(_document.Path).Contains(ActionPublish.Instance.Letter.ToString()))
@@ -322,10 +322,13 @@ namespace umbraco.cms.presentation
if (base.getUser().GetPermissions(_document.Path).IndexOf("U") > -1)
UnPublish.Visible = true;
- _documentHasPublishedVersion = _document.HasPublishedVersion();
+ _documentHasPublishedVersion = _document.Published;
- foreach (var descendant in _document.GetDescendants().Cast().Where(descendant => descendant.HasPublishedVersion()))
+ foreach (var descendant in _document.GetPathPublishedDescendants())
+ {
library.UpdateDocumentCache(descendant.Id);
+ }
+
}
else
{
diff --git a/src/umbraco.cms/businesslogic/web/Document.cs b/src/umbraco.cms/businesslogic/web/Document.cs
index 703207644e..ac36db5294 100644
--- a/src/umbraco.cms/businesslogic/web/Document.cs
+++ b/src/umbraco.cms/businesslogic/web/Document.cs
@@ -85,16 +85,13 @@ namespace umbraco.cms.businesslogic.web
{
using (IRecordsReader dr =
- SqlHelper.ExecuteReader(string.Format(m_SQLOptimizedSingle.Trim(), "umbracoNode.id = @id", "cmsContentVersion.id desc"),
+ SqlHelper.ExecuteReader(string.Format(SqlOptimizedSingle.Trim(), "umbracoNode.id = @id", "cmsContentVersion.id desc"),
SqlHelper.CreateParameter("@nodeObjectType", Document._objectType),
SqlHelper.CreateParameter("@id", id)))
{
if (dr.Read())
{
// Initialize node and basic document properties
- bool _hc = false;
- if (dr.GetInt("children") > 0)
- _hc = true;
int? masterContentType = null;
if (!dr.IsNull("masterContentType"))
masterContentType = dr.GetInt("masterContentType");
@@ -103,14 +100,14 @@ namespace umbraco.cms.businesslogic.web
, dr.GetInt("parentId")
, dr.GetInt("nodeUser")
, dr.GetInt("documentUser")
- , dr.GetBoolean("published")
+ , dr.GetInt("published") > 0
, dr.GetString("path")
, dr.GetString("text")
, dr.GetDateTime("createDate")
, dr.GetDateTime("updateDate")
, dr.GetDateTime("versionDate")
, dr.GetString("icon")
- , _hc
+ , dr.GetInt("children") > 0
, dr.GetString("alias")
, dr.GetString("thumbnail")
, dr.GetString("description")
@@ -139,7 +136,7 @@ namespace umbraco.cms.businesslogic.web
tmpReleaseDate,
tmpExpireDate,
dr.GetDateTime("updateDate"),
- dr.GetBoolean("published")
+ dr.GetInt("published") > 0
);
}
}
@@ -149,31 +146,33 @@ namespace umbraco.cms.businesslogic.web
#endregion
#region Constants and Static members
+
+
// NH: Modified to support SQL CE 4 (doesn't support nested selects)
- private const string m_SQLOptimizedSingle = @"
- Select
- CASE WHEN (childrenTable.total>0) THEN childrenTable.total ELSE 0 END as Children,
- CASE WHEN (publishedTable.publishedTotal>0) THEN publishedTable.publishedTotal ELSE 0 END as Published,
- cmsContentVersion.VersionId,
- cmsContentVersion.versionDate,
- contentTypeNode.uniqueId as ContentTypeGuid,
- cmsContent.ContentType, cmsContentType.icon, cmsContentType.alias, cmsContentType.thumbnail, cmsContentType.description, cmsContentType.masterContentType, cmsContentType.nodeId as contentTypeId,
- published, documentUser, coalesce(templateId, cmsDocumentType.templateNodeId) as templateId, cmsDocument.text as DocumentText, releaseDate, expireDate, updateDate,
- umbracoNode.createDate, umbracoNode.trashed, umbracoNode.parentId, umbracoNode.nodeObjectType, umbracoNode.nodeUser, umbracoNode.level, umbracoNode.path, umbracoNode.sortOrder, umbracoNode.uniqueId, umbracoNode.text
- from
- umbracoNode
- inner join cmsContentVersion on cmsContentVersion.contentID = umbracoNode.id
- inner join cmsDocument on cmsDocument.versionId = cmsContentVersion.versionId
- inner join cmsContent on cmsDocument.nodeId = cmsContent.NodeId
- inner join cmsContentType on cmsContentType.nodeId = cmsContent.ContentType
- inner join umbracoNode contentTypeNode on contentTypeNode.id = cmsContentType.nodeId
- left join cmsDocumentType on cmsDocumentType.contentTypeNodeId = cmsContent.contentType and cmsDocumentType.IsDefault = 1
- /* SQL CE support */
- left outer join (select count(id) as total, parentId from umbracoNode where parentId = @id group by parentId) as childrenTable on childrenTable.parentId = umbracoNode.id
- left outer join (select Count(published) as publishedTotal, nodeId from cmsDocument where published = 1 And nodeId = @id group by nodeId) as publishedTable on publishedTable.nodeId = umbracoNode.id
- /* end SQL CE support */
- where umbracoNode.nodeObjectType = @nodeObjectType AND {0}
- order by {1}
+ private const string SqlOptimizedSingle = @"
+Select
+ CASE WHEN (childrenTable.total>0) THEN childrenTable.total ELSE 0 END as Children,
+ CASE WHEN (publishedTable.publishedTotal>0) THEN publishedTable.publishedTotal ELSE 0 END as Published,
+ cmsContentVersion.VersionId,
+ cmsContentVersion.versionDate,
+ contentTypeNode.uniqueId as ContentTypeGuid,
+ cmsContent.ContentType, cmsContentType.icon, cmsContentType.alias, cmsContentType.thumbnail, cmsContentType.description, cmsContentType.masterContentType, cmsContentType.nodeId as contentTypeId,
+ documentUser, coalesce(templateId, cmsDocumentType.templateNodeId) as templateId, cmsDocument.text as DocumentText, releaseDate, expireDate, updateDate,
+ umbracoNode.createDate, umbracoNode.trashed, umbracoNode.parentId, umbracoNode.nodeObjectType, umbracoNode.nodeUser, umbracoNode.level, umbracoNode.path, umbracoNode.sortOrder, umbracoNode.uniqueId, umbracoNode.text
+from
+ umbracoNode
+ inner join cmsContentVersion on cmsContentVersion.contentID = umbracoNode.id
+ inner join cmsDocument on cmsDocument.versionId = cmsContentVersion.versionId
+ inner join cmsContent on cmsDocument.nodeId = cmsContent.NodeId
+ inner join cmsContentType on cmsContentType.nodeId = cmsContent.ContentType
+ inner join umbracoNode contentTypeNode on contentTypeNode.id = cmsContentType.nodeId
+ left join cmsDocumentType on cmsDocumentType.contentTypeNodeId = cmsContent.contentType and cmsDocumentType.IsDefault = 1
+ /* SQL CE support */
+ left outer join (select count(id) as total, parentId from umbracoNode where parentId = @id group by parentId) as childrenTable on childrenTable.parentId = umbracoNode.id
+ left outer join (select Count(published) as publishedTotal, nodeId from cmsDocument where published = 1 And nodeId = @id group by nodeId) as publishedTable on publishedTable.nodeId = umbracoNode.id
+ /* end SQL CE support */
+where umbracoNode.nodeObjectType = @nodeObjectType AND {0}
+order by {1}
";
// NH: Had to modify this for SQL CE 4. Only change is that the "coalesce(publishCheck.published,0) as published" didn't work in SQL CE 4
@@ -182,7 +181,7 @@ namespace umbraco.cms.businesslogic.web
// zb-00010 #29443 : removed the following lines + added constraint on cmsDocument.newest in where clause (equivalent + handles duplicate dates)
// inner join (select contentId, max(versionDate) as versionDate from cmsContentVersion group by contentId) temp
// on cmsContentVersion.contentId = temp.contentId and cmsContentVersion.versionDate = temp.versionDate
- private const string m_SQLOptimizedMany = @"
+ private const string SqlOptimizedMany = @"
select count(children.id) as children, umbracoNode.id, umbracoNode.uniqueId, umbracoNode.level, umbracoNode.parentId,
cmsDocument.documentUser, coalesce(cmsDocument.templateId, cmsDocumentType.templateNodeId) as templateId,
umbracoNode.path, umbracoNode.sortOrder, coalesce(publishCheck.published,0) as isPublished, umbracoNode.createDate,
@@ -208,7 +207,7 @@ namespace umbraco.cms.businesslogic.web
order by {1}
";
- private const string m_SQLOptimizedForPreview = @"
+ private const string SqlOptimizedForPreview = @"
select umbracoNode.id, umbracoNode.parentId, umbracoNode.level, umbracoNode.sortOrder, cmsDocument.versionId, cmsPreviewXml.xml from cmsDocument
inner join umbracoNode on umbracoNode.id = cmsDocument.nodeId
inner join cmsPreviewXml on cmsPreviewXml.nodeId = cmsDocument.nodeId and cmsPreviewXml.versionId = cmsDocument.versionId
@@ -226,7 +225,17 @@ namespace umbraco.cms.businesslogic.web
private DateTime _release;
private DateTime _expire;
private int _template;
- private bool _published;
+
+ ///
+ /// a backing property for the 'Published' property
+ ///
+ private bool? _published;
+
+ ///
+ /// Used as a value flag to indicate that we've already executed the sql for IsPathPublished()
+ ///
+ private bool? _pathPublished;
+
private XmlNode _xml;
private User _creator;
private User _writer;
@@ -521,7 +530,7 @@ namespace umbraco.cms.businesslogic.web
var tmp = new List();
using (IRecordsReader dr =
SqlHelper.ExecuteReader(
- string.Format(m_SQLOptimizedMany.Trim(), "cmsContent.contentType = @contentTypeId", "umbracoNode.sortOrder"),
+ string.Format(SqlOptimizedMany.Trim(), "cmsContent.contentType = @contentTypeId", "umbracoNode.sortOrder"),
SqlHelper.CreateParameter("@nodeObjectType", Document._objectType),
SqlHelper.CreateParameter("@contentTypeId", docTypeId)))
{
@@ -552,7 +561,7 @@ namespace umbraco.cms.businesslogic.web
var tmp = new List();
using (IRecordsReader dr =
SqlHelper.ExecuteReader(
- string.Format(m_SQLOptimizedMany.Trim(), "umbracoNode.parentID = @parentId", "umbracoNode.sortOrder"),
+ string.Format(SqlOptimizedMany.Trim(), "umbracoNode.parentID = @parentId", "umbracoNode.sortOrder"),
SqlHelper.CreateParameter("@nodeObjectType", Document._objectType),
SqlHelper.CreateParameter("@parentId", NodeId)))
{
@@ -572,7 +581,7 @@ namespace umbraco.cms.businesslogic.web
var tmp = new List();
using (IRecordsReader dr =
SqlHelper.ExecuteReader(
- string.Format(m_SQLOptimizedMany.Trim(), "umbracoNode.parentID = @parentId and umbracoNode.text like @search", "umbracoNode.sortOrder"),
+ string.Format(SqlOptimizedMany.Trim(), "umbracoNode.parentID = @parentId and umbracoNode.text like @search", "umbracoNode.sortOrder"),
SqlHelper.CreateParameter("@nodeObjectType", Document._objectType),
SqlHelper.CreateParameter("@search", searchString),
SqlHelper.CreateParameter("@parentId", NodeId)))
@@ -767,8 +776,20 @@ namespace umbraco.cms.businesslogic.web
/// the node and all its parents are published, and therefore whether the node is visible.
public bool Published
{
- get { return _published; }
+ get
+ {
+ if (!_published.HasValue)
+ {
+ var count = SqlHelper.ExecuteScalar(@"
+select Count(published) as CountOfPublished
+from cmsDocument
+inner join umbracoNode on cmsDocument.nodeId = umbracoNode.id
+where published = 1 And nodeId = @nodeId And trashed = 0", SqlHelper.CreateParameter("@nodeId", Id));
+ _published = count > 0;
+ }
+ return _published.Value;
+ }
set
{
_published = value;
@@ -777,23 +798,50 @@ namespace umbraco.cms.businesslogic.web
}
}
- ///
- /// Gets a value indicating whether the document and all its parents are published.
- ///
+ ///
+ /// Returns true if the document has a front-end published version (all documents in it's path are published)
+ ///
+ ///
+ ///
+ /// A document may be marked as published in the database but not published on the front-end. This occurs when you have a node structure such as
+ /// - Home
+ /// -- Page 1
+ /// --- Sub 1
+ /// --- Sub 2
+ ///
+ /// And they are all published, but then you unpublish 'Page 1'. What happens is that Page 1 and all of it's descendants are removed from the front-end
+ /// published cache and the 'Page 1' item is flagged as not published in the database, however both "Sub" pages will still be flagged in the database
+ /// as published. This is for performance and tracking reasons since these Sub pages have not physically been unpublished, they just cannot be seen on the
+ /// front -end.
+ ///
+ /// This method will return true or false based on whether or not there is published version on the front-end but this lookup is based purely on the databse
+ /// by comparing the ancesctors published count of the current node.
+ ///
+ /// If a node is in the recycle bin it will also be deemed not published
+ ///
public bool PathPublished
{
get
{
- // get all nodes in the path to the document, and get all matching published documents
- // the difference should be zero if everything is published
- // test nodeObjectType to make sure we only count _content_ nodes
- int x = SqlHelper.ExecuteScalar(@"select count(node.id) - count(doc.nodeid)
+ //check our cached value for this object
+ if (!_pathPublished.HasValue)
+ {
+ // get all nodes in the path to the document, and get all matching published documents
+ // the difference should be zero if everything is published
+ // test nodeObjectType to make sure we only count _content_ nodes
+ var sql = @"select count(node.id) - count(doc.nodeid)
from umbracoNode as node
left join cmsDocument as doc on (node.id=doc.nodeId and doc.published=1)
where '" + Path + ",' like " + SqlHelper.Concat("node.path", "',%'") + @"
-and node.nodeObjectType='C66BA18E-EAF3-4CFF-8A22-41B16D66A972'");
- return (x == 0);
+and node.nodeObjectType=@nodeObjectType";
+
+ var count = SqlHelper.ExecuteScalar(sql, SqlHelper.CreateParameter("@nodeObjectType", Document._objectType));
+ _pathPublished = (count == 0);
+ }
+
+ return _pathPublished.Value;
}
+ internal set { _pathPublished = value; }
}
public override string Text
@@ -1236,21 +1284,20 @@ and node.nodeObjectType='C66BA18E-EAF3-4CFF-8A22-41B16D66A972'");
}
///
- /// Returns true if the document is published
+ /// Returns true if the document has a published item in the database but is not in the recycle bin
///
///
///
- /// If the document is in the trash then this will return false
+ /// This will still return true if this document is not published on the front-end in some cases if one of it's ancestors are
+ /// not-published. If you have a published document and unpublish one of it's ancestors, it will retain it's published flag in the
+ /// database.
+ ///
+ /// If you are wanting to check if this document is published on the front end use the IsPathPublished() method.
///
+ [Obsolete("Use the Published property instead")]
public bool HasPublishedVersion()
{
- var count = SqlHelper.ExecuteScalar(@"
-select Count(published) as CountOfPublished
-from cmsDocument
-inner join umbracoNode on cmsDocument.nodeId = umbracoNode.id
-where published = 1 And nodeId = @nodeId And trashed = 0", SqlHelper.CreateParameter("@nodeId", Id));
-
- return count > 0;
+ return Published;
}
///
@@ -1463,26 +1510,55 @@ where published = 1 And nodeId = @nodeId And trashed = 0", SqlHelper.CreateParam
}
}
+ ///
+ /// Returns all descendants that are published on the front-end (hava a full published path)
+ ///
+ ///
+ public IEnumerable GetPathPublishedDescendants()
+ {
+ var documents = new List();
+ using (var dr = SqlHelper.ExecuteReader(
+ string.Format(SqlOptimizedMany.Trim(), "umbracoNode.path LIKE '%," + this.Id + ",%'", "umbracoNode.level"),
+ SqlHelper.CreateParameter("@nodeObjectType", Document._objectType)))
+ {
+ while (dr.Read())
+ {
+ var d = new Document(dr.GetInt("id"), true);
+ d.PopulateDocumentFromReader(dr);
+ documents.Add(d);
+ }
+ }
+
+ //update the PathPublished correctly for all documents added to this list
+ UpdatePathPublishedOnDescendants(documents);
+
+ //now, we only want to return any descendants that have a PathPublished = true
+ return documents.Where(x => x.PathPublished);
+ }
+
///
/// Returns all decendants of the current document
///
///
public override IEnumerable GetDescendants()
{
- var tmp = new List();
+ var documents = new List();
using (IRecordsReader dr = SqlHelper.ExecuteReader(
- string.Format(m_SQLOptimizedMany.Trim(), "umbracoNode.path LIKE '%," + this.Id + ",%'", "umbracoNode.level"),
+ string.Format(SqlOptimizedMany.Trim(), "umbracoNode.path LIKE '%," + this.Id + ",%'", "umbracoNode.level"),
SqlHelper.CreateParameter("@nodeObjectType", Document._objectType)))
{
while (dr.Read())
{
- Document d = new Document(dr.GetInt("id"), true);
+ var d = new Document(dr.GetInt("id"), true);
d.PopulateDocumentFromReader(dr);
- tmp.Add(d);
+ documents.Add(d);
}
}
- return tmp.ToArray();
+ //update the PathPublished correctly for all documents added to this list
+ UpdatePathPublishedOnDescendants(documents);
+
+ return documents.ToArray();
}
///
@@ -1662,7 +1738,7 @@ where published = 1 And nodeId = @nodeId And trashed = 0", SqlHelper.CreateParam
string pathExp = childrenOnly ? Path + ",%" : Path;
- IRecordsReader dr = SqlHelper.ExecuteReader(String.Format(m_SQLOptimizedForPreview, pathExp));
+ IRecordsReader dr = SqlHelper.ExecuteReader(String.Format(SqlOptimizedForPreview, pathExp));
while (dr.Read())
nodes.Add(new CMSPreviewNode(dr.GetInt("id"), dr.GetGuid("versionId"), dr.GetInt("parentId"), dr.GetShort("level"), dr.GetInt("sortOrder"), dr.GetString("xml")));
dr.Close();
@@ -1717,8 +1793,6 @@ where published = 1 And nodeId = @nodeId And trashed = 0", SqlHelper.CreateParam
throw new ArgumentException(string.Format("No Document exists with Version '{0}'", Version));
}
}
-
- _published = HasPublishedVersion();
}
protected void InitializeDocument(User InitUser, User InitWriter, string InitText, int InitTemplate,
@@ -1743,6 +1817,10 @@ where published = 1 And nodeId = @nodeId And trashed = 0", SqlHelper.CreateParam
_published = InitPublished;
}
+ ///
+ /// Updates this document object based on the data in the IRecordsReader for data returned from the SqlOptimizedMany SQL call
+ ///
+ ///
protected void PopulateDocumentFromReader(IRecordsReader dr)
{
var hc = dr.GetInt("children") > 0;
@@ -1776,6 +1854,7 @@ where published = 1 And nodeId = @nodeId And trashed = 0", SqlHelper.CreateParam
_release = dr.GetDateTime("releaseDate");
if (!dr.IsNull("expireDate"))
_expire = dr.GetDateTime("expireDate");
+
}
protected void SaveXmlPreview(XmlDocument xd)
@@ -1786,6 +1865,48 @@ where published = 1 And nodeId = @nodeId And trashed = 0", SqlHelper.CreateParam
#endregion
#region Private Methods
+
+ ///
+ /// Updates this the PathPublished property for all pre-populated descendant nodes in list format
+ ///
+ /// The pre-populated list of descendants of the root node passed in
+ ///
+ /// This method will ensure that the document's PathPublished is automatically set based on this (the root ancestor) document.
+ /// It will set the PathPublished based on the documents with the shortest path first since the parent document to those documents
+ /// are 'this' document. Then we will go to the next level and set the PathPublished based on their parent documents... since they will
+ /// now have the PathPublished property set. and so on.
+ ///
+ private void UpdatePathPublishedOnDescendants(List descendantsList)
+ {
+ //create a new list containing 'this' so the list becomes DescendantsAndSelf
+ var descendantsAndSelf = descendantsList.Concat(new[] {this}).ToList();
+
+ //determine all path lengths in the list
+ var pathLengths = descendantsList.Select(x => x.Path.Split(',').Length).Distinct();
+ //start with the shortest paths
+ foreach (var pathLength in pathLengths.OrderBy(x => x))
+ {
+ var length = pathLength;
+ var docsWithPathLength = descendantsList.Where(x => x.Path.Split(',').Length == length);
+ //iterate over all documents with the current path length
+ foreach (var d in docsWithPathLength)
+ {
+ //we need to find the current doc's parent doc in the descendantsOrSelf list
+ var parent = descendantsAndSelf.SingleOrDefault(x => x.Id == d.ParentId);
+ if (parent != null)
+ {
+ //here we jsut check what the parent document's PathPublished property is.
+ // If it is false then the current 'd' document's PathPublished is also false.
+ // If it is true and if the current 'd' document's Published is true, the the 'd' document's PathPublished is also true.
+ // If it is true and if the current 'd' document's Published is false, the the 'd' document's PathPublished is false.
+ d.PathPublished = parent.PathPublished && d.Published;
+ }
+ }
+ }
+
+
+ }
+
private void SetupDocumentForTree(Guid uniqueId, int level, int parentId, int creator, int writer, bool publish, string path,
string text, DateTime createDate, DateTime updateDate,
DateTime versionDate, string icon, bool hasChildren, string contentTypeAlias, string contentTypeThumb,
From d0ace55d032df9942037f8ccd63e5712df87cef2 Mon Sep 17 00:00:00 2001
From: Shannon Deminick
Date: Wed, 30 Jan 2013 05:04:31 +0600
Subject: [PATCH 04/43] Fixes: #U4-1593 - Content tree doesn't check for
correct publish state.
---
.../umbraco.presentation/umbraco/Trees/BaseContentTree.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/BaseContentTree.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/BaseContentTree.cs
index f2c267f8e4..12b3d776e3 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/BaseContentTree.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/BaseContentTree.cs
@@ -113,7 +113,7 @@ function openContent(id) {
node.OpenIcon = dd.ContentTypeIcon;
}
- if (dd.Published == false)
+ if (!dd.PathPublished)
node.Style.DimNode();
if (dd.HasPendingChanges())
@@ -193,7 +193,7 @@ function openContent(id) {
protected void SetNonPublishedAttribute(ref XmlTreeNode treeElement, Document dd)
{
treeElement.NotPublished = false;
- if (dd.Published)
+ if (dd.PathPublished)
{
//if (Math.Round(new TimeSpan(dd.UpdateDate.Ticks - dd.VersionDate.Ticks).TotalSeconds, 0) > 1)
// treeElement.NotPublished = true;
From a734a0cff773ba3c688207bee2defc96fd09a5fb Mon Sep 17 00:00:00 2001
From: Shannon Deminick
Date: Wed, 30 Jan 2013 05:37:32 +0600
Subject: [PATCH 05/43] Fixes unit tests for
Umbraco_Route_User_Defined_Controller_Action
---
src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs | 7 +++++--
src/Umbraco.Web/Mvc/RenderRouteHandler.cs | 2 +-
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs
index 306a02bb5b..b4f5d19ba6 100644
--- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs
+++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs
@@ -64,7 +64,8 @@ namespace Umbraco.Tests.Routing
}
//test all template name styles to match the ActionName
- [TestCase("home-page")]
+ [TestCase("home-\\234^^*32page")]
+ [TestCase("home-page")]
[TestCase("Home-Page")]
[TestCase("HomePage")]
[TestCase("homePage")]
@@ -84,7 +85,9 @@ namespace Umbraco.Tests.Routing
handler.GetHandlerForRoute(routingContext.UmbracoContext.HttpContext.Request.RequestContext, docRequest);
Assert.AreEqual("CustomDocument", routeData.Values["controller"].ToString());
- Assert.AreEqual("HomePage", routeData.Values["action"].ToString());
+ Assert.AreEqual(
+ global::umbraco.cms.helpers.Casing.SafeAlias(templateName),
+ routeData.Values["action"].ToString());
}
diff --git a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs
index 30bac69666..53047d3c3a 100644
--- a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs
+++ b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs
@@ -274,7 +274,7 @@ namespace Umbraco.Web.Mvc
//the template Alias should always be already saved with a safe name.
//if there are hyphens in the name and there is a hijacked route, then the Action will need to be attributed
// with the action name attribute.
- var templateName = publishedContentRequest.Template.Alias.Split('.')[0];
+ var templateName = global::umbraco.cms.helpers.Casing.SafeAlias(publishedContentRequest.Template.Alias.Split('.')[0]);
def.ActionName = templateName;
}
From 2d87f933d5c243be4bd9de03fbf7193dd246c9bf Mon Sep 17 00:00:00 2001
From: Shannon Deminick
Date: Wed, 30 Jan 2013 07:57:31 +0600
Subject: [PATCH 06/43] Updates Document's Published property to return true if
the document is 100% published (viewable on the front-end) Reverts Document's
HasPublishedVersion() to return true if the document has any published
version (may or may not be viewable on the front-end) Updates the Document's
new UpdatePublishedOnDescendants to set both the Published and PathPublished
fields. Reverts some stuff in the editContent to use HasPublishedContent() to
set the _documentHasPublishedVersion field. Reverts the BaseContentTree to
use the Published property now that it returns the correct value. Updates the
editContent method to use the UpdateDocumentCache overload accepting an
object so there's not another N+1 SQL call made.
---
.../umbraco/Trees/BaseContentTree.cs | 8 +-
.../umbraco/editContent.aspx.cs | 8 +-
src/umbraco.cms/businesslogic/web/Document.cs | 164 ++++++++++++------
3 files changed, 115 insertions(+), 65 deletions(-)
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/BaseContentTree.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/BaseContentTree.cs
index 12b3d776e3..1170bb8d33 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/BaseContentTree.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/BaseContentTree.cs
@@ -35,7 +35,7 @@ namespace umbraco.cms.presentation.Trees
public BaseContentTree(string application) : base(application) { }
- private User m_user;
+ private User _user;
///
/// Returns the current User. This ensures that we don't instantiate a new User object
@@ -45,7 +45,7 @@ namespace umbraco.cms.presentation.Trees
{
get
{
- return (m_user == null ? (m_user = UmbracoEnsuredPage.CurrentUser) : m_user);
+ return (_user == null ? (_user = UmbracoEnsuredPage.CurrentUser) : _user);
}
}
@@ -113,7 +113,7 @@ function openContent(id) {
node.OpenIcon = dd.ContentTypeIcon;
}
- if (!dd.PathPublished)
+ if (!dd.Published)
node.Style.DimNode();
if (dd.HasPendingChanges())
@@ -193,7 +193,7 @@ function openContent(id) {
protected void SetNonPublishedAttribute(ref XmlTreeNode treeElement, Document dd)
{
treeElement.NotPublished = false;
- if (dd.PathPublished)
+ if (dd.Published)
{
//if (Math.Round(new TimeSpan(dd.UpdateDate.Ticks - dd.VersionDate.Ticks).TotalSeconds, 0) > 1)
// treeElement.NotPublished = true;
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs
index e80d1d7263..c074e1cbad 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs
@@ -82,7 +82,7 @@ namespace umbraco.cms.presentation
}
// we need to check if there's a published version of this document
- _documentHasPublishedVersion = _document.Published;
+ _documentHasPublishedVersion = _document.HasPublishedVersion();
// Check publishing permissions
if (!base.getUser().GetPermissions(_document.Path).Contains(ActionPublish.Instance.Letter.ToString()))
@@ -322,11 +322,11 @@ namespace umbraco.cms.presentation
if (base.getUser().GetPermissions(_document.Path).IndexOf("U") > -1)
UnPublish.Visible = true;
- _documentHasPublishedVersion = _document.Published;
+ _documentHasPublishedVersion = _document.HasPublishedVersion();
- foreach (var descendant in _document.GetPathPublishedDescendants())
+ foreach (var descendant in _document.GetPublishedDescendants())
{
- library.UpdateDocumentCache(descendant.Id);
+ library.UpdateDocumentCache(descendant);
}
}
diff --git a/src/umbraco.cms/businesslogic/web/Document.cs b/src/umbraco.cms/businesslogic/web/Document.cs
index ac36db5294..60f4b8024d 100644
--- a/src/umbraco.cms/businesslogic/web/Document.cs
+++ b/src/umbraco.cms/businesslogic/web/Document.cs
@@ -230,7 +230,12 @@ order by {1}
/// a backing property for the 'Published' property
///
private bool? _published;
-
+
+ ///
+ /// a backing property for the 'HasPublishedVersion()' method
+ ///
+ private bool? _hasPublishedVersion;
+
///
/// Used as a value flag to indicate that we've already executed the sql for IsPathPublished()
///
@@ -558,24 +563,49 @@ order by {1}
///
public static Document[] GetChildrenForTree(int NodeId)
{
- var tmp = new List();
- using (IRecordsReader dr =
+ var documents = GetChildrenForTreeInternal(NodeId).ToList();
+ if (NodeId > 0)
+ {
+ var parent = new Document(NodeId);
+ //update the Published/PathPublished correctly for all documents added to this list
+ UpdatePublishedOnDescendants(documents, parent);
+ }
+ return documents.ToArray();
+ }
+
+ ///
+ /// Performance tuned method for use in the tree
+ ///
+ /// The parent document
+ ///
+ public static Document[] GetChildrenForTree(Document parent)
+ {
+ var documents = GetChildrenForTreeInternal(parent.Id).ToList();
+ //update the Published/PathPublished correctly for all documents added to this list
+ UpdatePublishedOnDescendants(documents, parent);
+ return documents.ToArray();
+ }
+
+ public static IEnumerable GetChildrenForTreeInternal(int nodeId)
+ {
+ var documents = new List();
+ using (var dr =
SqlHelper.ExecuteReader(
string.Format(SqlOptimizedMany.Trim(), "umbracoNode.parentID = @parentId", "umbracoNode.sortOrder"),
SqlHelper.CreateParameter("@nodeObjectType", Document._objectType),
- SqlHelper.CreateParameter("@parentId", NodeId)))
+ SqlHelper.CreateParameter("@parentId", nodeId)))
{
while (dr.Read())
{
- Document d = new Document(dr.GetInt("id"), true);
+ var d = new Document(dr.GetInt("id"), true);
d.PopulateDocumentFromReader(dr);
- tmp.Add(d);
+ documents.Add(d);
}
}
-
- return tmp.ToArray();
+ return documents;
}
+
public static List GetChildrenBySearch(int NodeId, string searchString)
{
var tmp = new List();
@@ -780,13 +810,18 @@ order by {1}
{
if (!_published.HasValue)
{
- var count = SqlHelper.ExecuteScalar(@"
-select Count(published) as CountOfPublished
-from cmsDocument
-inner join umbracoNode on cmsDocument.nodeId = umbracoNode.id
-where published = 1 And nodeId = @nodeId And trashed = 0", SqlHelper.CreateParameter("@nodeId", Id));
+ // get all nodes in the path to the document, and get all matching published documents
+ // the difference should be zero if everything is published
+ // test nodeObjectType to make sure we only count _content_ nodes
+ var sql = @"select count(node.id) - count(doc.nodeid)
+from umbracoNode as node
+left join cmsDocument as doc on (node.id=doc.nodeId and doc.published=1)
+where (('" + Path + ",' like " + SqlHelper.Concat("node.path", "',%'") + @")
+ or ('" + Path + @"' = node.path)) and node.id <> -1
+and node.nodeObjectType=@nodeObjectType";
- _published = count > 0;
+ var count = SqlHelper.ExecuteScalar(sql, SqlHelper.CreateParameter("@nodeObjectType", Document._objectType));
+ _published = (count == 0);
}
return _published.Value;
}
@@ -799,25 +834,10 @@ where published = 1 And nodeId = @nodeId And trashed = 0", SqlHelper.CreateParam
}
///
- /// Returns true if the document has a front-end published version (all documents in it's path are published)
+ /// Returns true if the document's ancestors are all published
///
///
///
- /// A document may be marked as published in the database but not published on the front-end. This occurs when you have a node structure such as
- /// - Home
- /// -- Page 1
- /// --- Sub 1
- /// --- Sub 2
- ///
- /// And they are all published, but then you unpublish 'Page 1'. What happens is that Page 1 and all of it's descendants are removed from the front-end
- /// published cache and the 'Page 1' item is flagged as not published in the database, however both "Sub" pages will still be flagged in the database
- /// as published. This is for performance and tracking reasons since these Sub pages have not physically been unpublished, they just cannot be seen on the
- /// front -end.
- ///
- /// This method will return true or false based on whether or not there is published version on the front-end but this lookup is based purely on the databse
- /// by comparing the ancesctors published count of the current node.
- ///
- /// If a node is in the recycle bin it will also be deemed not published
///
public bool PathPublished
{
@@ -957,7 +977,7 @@ and node.nodeObjectType=@nodeObjectType";
{
//cache the documents children so that this db call doesn't have to occur again
if (this._children == null)
- this._children = Document.GetChildrenForTree(this.Id);
+ this._children = GetChildrenForTree(this);
return this._children.ToArray();
}
@@ -1291,13 +1311,20 @@ and node.nodeObjectType=@nodeObjectType";
/// This will still return true if this document is not published on the front-end in some cases if one of it's ancestors are
/// not-published. If you have a published document and unpublish one of it's ancestors, it will retain it's published flag in the
/// database.
- ///
- /// If you are wanting to check if this document is published on the front end use the IsPathPublished() method.
///
- [Obsolete("Use the Published property instead")]
public bool HasPublishedVersion()
{
- return Published;
+ if (!_hasPublishedVersion.HasValue)
+ {
+ var count = SqlHelper.ExecuteScalar(@"
+select Count(published) as CountOfPublished
+from cmsDocument
+inner join umbracoNode on cmsDocument.nodeId = umbracoNode.id
+where published = 1 And nodeId = @nodeId And trashed = 0", SqlHelper.CreateParameter("@nodeId", Id));
+
+ _hasPublishedVersion = count > 0;
+ }
+ return _hasPublishedVersion.Value;
}
///
@@ -1514,7 +1541,7 @@ and node.nodeObjectType=@nodeObjectType";
/// Returns all descendants that are published on the front-end (hava a full published path)
///
///
- public IEnumerable GetPathPublishedDescendants()
+ public IEnumerable GetPublishedDescendants()
{
var documents = new List();
using (var dr = SqlHelper.ExecuteReader(
@@ -1529,11 +1556,11 @@ and node.nodeObjectType=@nodeObjectType";
}
}
- //update the PathPublished correctly for all documents added to this list
- UpdatePathPublishedOnDescendants(documents);
+ //update the Published/PathPublished correctly for all documents added to this list
+ UpdatePublishedOnDescendants(documents, this);
- //now, we only want to return any descendants that have a PathPublished = true
- return documents.Where(x => x.PathPublished);
+ //now, we only want to return any descendants that have a Published = true (full published path)
+ return documents.Where(x => x.Published);
}
///
@@ -1555,8 +1582,8 @@ and node.nodeObjectType=@nodeObjectType";
}
}
- //update the PathPublished correctly for all documents added to this list
- UpdatePathPublishedOnDescendants(documents);
+ //update the Published/PathPublished correctly for all documents added to this list
+ UpdatePublishedOnDescendants(documents, this);
return documents.ToArray();
}
@@ -1867,19 +1894,20 @@ and node.nodeObjectType=@nodeObjectType";
#region Private Methods
///
- /// Updates this the PathPublished property for all pre-populated descendant nodes in list format
+ /// Updates this the Published property for all pre-populated descendant nodes in list format
///
- /// The pre-populated list of descendants of the root node passed in
+ /// The pre-populated list of descendants of the root node passed in
+ /// The very root document retreiving the ancestors
///
- /// This method will ensure that the document's PathPublished is automatically set based on this (the root ancestor) document.
- /// It will set the PathPublished based on the documents with the shortest path first since the parent document to those documents
- /// are 'this' document. Then we will go to the next level and set the PathPublished based on their parent documents... since they will
- /// now have the PathPublished property set. and so on.
+ /// This method will ensure that the document's Published is automatically set based on this (the root ancestor) document.
+ /// It will set the Published based on the documents with the shortest path first since the parent document to those documents
+ /// are 'this' document. Then we will go to the next level and set the Published based on their parent documents... since they will
+ /// now have the Published property set. and so on.
///
- private void UpdatePathPublishedOnDescendants(List descendantsList)
+ private static void UpdatePublishedOnDescendants(List descendantsList, Document root)
{
//create a new list containing 'this' so the list becomes DescendantsAndSelf
- var descendantsAndSelf = descendantsList.Concat(new[] {this}).ToList();
+ var descendantsAndSelf = descendantsList.Concat(new[] { root }).ToList();
//determine all path lengths in the list
var pathLengths = descendantsList.Select(x => x.Path.Split(',').Length).Distinct();
@@ -1895,11 +1923,11 @@ and node.nodeObjectType=@nodeObjectType";
var parent = descendantsAndSelf.SingleOrDefault(x => x.Id == d.ParentId);
if (parent != null)
{
- //here we jsut check what the parent document's PathPublished property is.
- // If it is false then the current 'd' document's PathPublished is also false.
- // If it is true and if the current 'd' document's Published is true, the the 'd' document's PathPublished is also true.
- // If it is true and if the current 'd' document's Published is false, the the 'd' document's PathPublished is false.
- d.PathPublished = parent.PathPublished && d.Published;
+ //we are published if our parent is published and we have a published version
+ d.Published = parent.Published && d.HasPublishedVersion();
+
+ //our path is published if our parent is published
+ d.PathPublished = parent.Published;
}
}
}
@@ -1907,7 +1935,29 @@ and node.nodeObjectType=@nodeObjectType";
}
- private void SetupDocumentForTree(Guid uniqueId, int level, int parentId, int creator, int writer, bool publish, string path,
+ ///
+ /// Sets properties on this object based on the parameters
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// If this document has a published version
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private void SetupDocumentForTree(Guid uniqueId, int level, int parentId, int creator, int writer, bool hasPublishedVersion, string path,
string text, DateTime createDate, DateTime updateDate,
DateTime versionDate, string icon, bool hasChildren, string contentTypeAlias, string contentTypeThumb,
string contentTypeDesc, int? masterContentType, int contentTypeId, int templateId)
@@ -1915,7 +1965,7 @@ and node.nodeObjectType=@nodeObjectType";
SetupNodeForTree(uniqueId, _objectType, level, parentId, creator, path, text, createDate, hasChildren);
_writerId = writer;
- _published = publish;
+ _hasPublishedVersion = hasPublishedVersion;
_updated = updateDate;
_template = templateId;
ContentType = new ContentType(contentTypeId, contentTypeAlias, icon, contentTypeThumb, masterContentType);
From d38d7b1ff41d328571fa7b3cb70fdac76e2194dd Mon Sep 17 00:00:00 2001
From: Shannon Deminick
Date: Wed, 30 Jan 2013 07:59:03 +0600
Subject: [PATCH 07/43] Updates all code calling UnPublishSingleNode &
UpdateDocumentCache to pass in the already existing Document object if there
is one instead of the ID... this'll save a another ton of SQL calls.
---
.../umbraco.presentation/content.cs | 30 ++++++++++---------
.../umbraco.presentation/library.cs | 21 ++++++++++---
.../umbraco.presentation/publishingService.cs | 2 +-
.../Modules/CreateModule/CreateModule.cs | 2 +-
.../umbraco/actions/publish.aspx.cs | 2 +-
.../umbraco/channels/UmbracoMetaWeblogAPI.cs | 4 +--
.../umbraco/dialogs/moveOrCopy.aspx.cs | 4 +--
.../umbraco/dialogs/publish.aspx.cs | 6 ++--
.../umbraco/uQuery/DocumentExtensions.cs | 2 +-
.../documents/documentService.cs | 8 ++---
10 files changed, 48 insertions(+), 33 deletions(-)
diff --git a/src/Umbraco.Web/umbraco.presentation/content.cs b/src/Umbraco.Web/umbraco.presentation/content.cs
index ee5da1467f..5161c14119 100644
--- a/src/Umbraco.Web/umbraco.presentation/content.cs
+++ b/src/Umbraco.Web/umbraco.presentation/content.cs
@@ -580,40 +580,42 @@ namespace umbraco
ThreadPool.QueueUserWorkItem(delegate { UpdateDocumentCache(documentId); });
}
-
- [Obsolete("Method obsolete in version 4.1 and later, please use ClearDocumentCache", true)]
///
/// Clears the document cache async.
///
/// The document id.
+ [Obsolete("Method obsolete in version 4.1 and later, please use ClearDocumentCache", true)]
public virtual void ClearDocumentCacheAsync(int documentId)
{
ThreadPool.QueueUserWorkItem(delegate { ClearDocumentCache(documentId); });
}
+ public virtual void ClearDocumentCache(int documentId)
+ {
+ // Get the document
+ var d = new Document(documentId);
+ ClearDocumentCache(d);
+ }
///
/// Clears the document cache and removes the document from the xml db cache.
/// This means the node gets unpublished from the website.
///
- /// The document id.
- public virtual void ClearDocumentCache(int documentId)
+ /// The document
+ public virtual void ClearDocumentCache(Document doc)
{
- // Get the document
- var d = new Document(documentId);
-
var e = new DocumentCacheEventArgs();
- FireBeforeClearDocumentCache(d, e);
+ FireBeforeClearDocumentCache(doc, e);
if (!e.Cancel)
{
XmlNode x;
// remove from xml db cache
- d.XmlRemoveFromDB();
+ doc.XmlRemoveFromDB();
// Check if node present, before cloning
- x = XmlContentInternal.GetElementById(d.Id.ToString());
+ x = XmlContentInternal.GetElementById(doc.Id.ToString());
if (x == null)
return;
@@ -626,7 +628,7 @@ namespace umbraco
XmlDocument xmlContentCopy = CloneXmlDoc(XmlContentInternal);
// Find the document in the xml cache
- x = xmlContentCopy.GetElementById(d.Id.ToString());
+ x = xmlContentCopy.GetElementById(doc.Id.ToString());
if (x != null)
{
// The document already exists in cache, so repopulate it
@@ -639,17 +641,17 @@ namespace umbraco
if (x != null)
{
// Run Handler
- Action.RunActionHandlers(d, ActionUnPublish.Instance);
+ Action.RunActionHandlers(doc, ActionUnPublish.Instance);
}
// update sitemapprovider
if (SiteMap.Provider is UmbracoSiteMapProvider)
{
var prov = (UmbracoSiteMapProvider)SiteMap.Provider;
- prov.RemoveNode(d.Id);
+ prov.RemoveNode(doc.Id);
}
- FireAfterClearDocumentCache(d, e);
+ FireAfterClearDocumentCache(doc, e);
}
}
diff --git a/src/Umbraco.Web/umbraco.presentation/library.cs b/src/Umbraco.Web/umbraco.presentation/library.cs
index 8a78f77168..9a081380e3 100644
--- a/src/Umbraco.Web/umbraco.presentation/library.cs
+++ b/src/Umbraco.Web/umbraco.presentation/library.cs
@@ -187,9 +187,7 @@ namespace umbraco
///
/// The Id of the Document to be unpublished
public static void UnPublishSingleNode(int DocumentId)
- {
-
- //PPH Added dispatcher support
+ {
if (UmbracoSettings.UseDistributedCalls)
dispatcher.Remove(
new Guid("27ab3022-3dfa-47b6-9119-5945bc88fd66"),
@@ -198,6 +196,21 @@ namespace umbraco
content.Instance.ClearDocumentCache(DocumentId);
}
+ ///
+ /// Unpublish a node, by removing it from the runtime xml index. Note, prior to this the Document should be
+ /// marked unpublished by setting the publish property on the document object to false
+ ///
+ /// The Document to be unpublished
+ public static void UnPublishSingleNode(Document document)
+ {
+ if (UmbracoSettings.UseDistributedCalls)
+ dispatcher.Remove(
+ new Guid("27ab3022-3dfa-47b6-9119-5945bc88fd66"),
+ document.Id);
+ else
+ content.Instance.ClearDocumentCache(document);
+ }
+
///
/// Publishes a Document by adding it to the runtime xml index. Note, prior to this the Document should be
/// marked published by calling Publish(User u) on the document object.
@@ -219,7 +232,7 @@ namespace umbraco
/// which means we have to re-look up the document in the db again when we already have it, this should save on a few
/// dozen sql calls when publishing.
///
- internal static void UpdateDocumentCache(Document doc)
+ public static void UpdateDocumentCache(Document doc)
{
if (UmbracoSettings.UseDistributedCalls)
dispatcher.Refresh(
diff --git a/src/Umbraco.Web/umbraco.presentation/publishingService.cs b/src/Umbraco.Web/umbraco.presentation/publishingService.cs
index f45c6d5916..163da00565 100644
--- a/src/Umbraco.Web/umbraco.presentation/publishingService.cs
+++ b/src/Umbraco.Web/umbraco.presentation/publishingService.cs
@@ -38,7 +38,7 @@ namespace umbraco.presentation
d.ReleaseDate = DateTime.MinValue; //new DateTime(1, 1, 1); // Causes release date to be null
d.Publish(d.User);
- library.UpdateDocumentCache(d.Id);
+ library.UpdateDocumentCache(d);
}
catch(Exception ee)
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/LiveEditing/Modules/CreateModule/CreateModule.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/LiveEditing/Modules/CreateModule/CreateModule.cs
index 18b0e22a72..fd353d09cc 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/LiveEditing/Modules/CreateModule/CreateModule.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/LiveEditing/Modules/CreateModule/CreateModule.cs
@@ -132,7 +132,7 @@ namespace umbraco.presentation.LiveEditing.Modules.CreateModule
DocumentType typeToCreate = new DocumentType(Convert.ToInt32(m_AllowedDocTypesDropdown.SelectedValue));
Document newDoc = Document.MakeNew(m_NameTextBox.Text, typeToCreate, new global::umbraco.BusinessLogic.User(userid), (int)UmbracoContext.Current.PageId);
newDoc.Publish(new global::umbraco.BusinessLogic.User(userid));
- library.UpdateDocumentCache(newDoc.Id);
+ library.UpdateDocumentCache(newDoc);
Page.Response.Redirect(library.NiceUrl(newDoc.Id), false);
break;
}
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/actions/publish.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/actions/publish.aspx.cs
index 94c88425ac..d58e002785 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/actions/publish.aspx.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/actions/publish.aspx.cs
@@ -39,7 +39,7 @@ namespace umbraco.presentation.actions
confirm.Visible = false;
d.Publish(getUser());
- library.UpdateDocumentCache(d.Id);
+ library.UpdateDocumentCache(d);
deleted.Text = ui.Text("editContentPublishedHeader") + " ('" + d.Text + "') " + ui.Text("editContentPublishedText") + "