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") + "

" + ui.Text("view") + " " + d.Text + ""; } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/channels/UmbracoMetaWeblogAPI.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/channels/UmbracoMetaWeblogAPI.cs index afe99ac4d2..c1089d77be 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/channels/UmbracoMetaWeblogAPI.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/channels/UmbracoMetaWeblogAPI.cs @@ -84,7 +84,7 @@ namespace umbraco.presentation.channels if (publish) { doc.Publish(new User(username)); - library.UpdateDocumentCache(doc.Id); + library.UpdateDocumentCache(doc); } return true; } @@ -403,7 +403,7 @@ namespace umbraco.presentation.channels if (publish) { doc.Publish(new User(username)); - library.UpdateDocumentCache(doc.Id); + library.UpdateDocumentCache(doc); } return doc.Id.ToString(); } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/moveOrCopy.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/moveOrCopy.aspx.cs index b4e966021c..3bd289e1e0 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/moveOrCopy.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/moveOrCopy.aspx.cs @@ -152,7 +152,7 @@ namespace umbraco.dialogs if (cd.Published) { cd.Publish(new umbraco.BusinessLogic.User(0)); //using library.publish to support load balancing. - umbraco.library.UpdateDocumentCache(cd.Id); + umbraco.library.UpdateDocumentCache(cd); if (cd.HasChildren) { @@ -299,7 +299,7 @@ namespace umbraco.dialogs d.Publish(new umbraco.BusinessLogic.User(0)); //using library.publish to support load balancing. //umbraco.library.PublishSingleNode(d.Id); - umbraco.library.UpdateDocumentCache(d.Id); + umbraco.library.UpdateDocumentCache(d); //PPH added handling of load balanced moving of multiple nodes... if (d.HasChildren) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/publish.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/publish.aspx.cs index 9feee1ecd9..7d05314df7 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/publish.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/publish.aspx.cs @@ -92,7 +92,7 @@ namespace umbraco.dialogs { if (doc.Published) { - library.UpdateDocumentCache(doc.Id); + library.UpdateDocumentCache(doc); } } @@ -116,7 +116,7 @@ namespace umbraco.dialogs { if (d.PublishWithResult(base.getUser())) { - library.UpdateDocumentCache(d.Id); + library.UpdateDocumentCache(d); feedbackMsg.type = umbraco.uicontrols.Feedback.feedbacktype.success; feedbackMsg.Text = ui.Text("publish", "nodePublish", d.Text, base.getUser()) + "

" + ui.Text("closeThisWindow") + ""; } @@ -141,7 +141,7 @@ namespace umbraco.dialogs { // Needed for supporting distributed calls if (UmbracoSettings.UseDistributedCalls) - library.UpdateDocumentCache(d.Id); + library.UpdateDocumentCache(d); else documents.Add(d); diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/uQuery/DocumentExtensions.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/uQuery/DocumentExtensions.cs index 7c7b17c3a2..de897b6209 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/uQuery/DocumentExtensions.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/uQuery/DocumentExtensions.cs @@ -250,7 +250,7 @@ namespace umbraco } } - library.UpdateDocumentCache(document.Id); + library.UpdateDocumentCache(document); return document; } diff --git a/src/umbraco.webservices/documents/documentService.cs b/src/umbraco.webservices/documents/documentService.cs index caea93c368..cea5a61d7e 100644 --- a/src/umbraco.webservices/documents/documentService.cs +++ b/src/umbraco.webservices/documents/documentService.cs @@ -246,13 +246,13 @@ namespace umbraco.webservices.documents case documentCarrier.EPublishAction.Publish: if (doc.PublishWithResult(user)) { - umbraco.library.UpdateDocumentCache(doc.Id); + umbraco.library.UpdateDocumentCache(doc); } break; case documentCarrier.EPublishAction.Unpublish: if (doc.PublishWithResult(user)) { - umbraco.library.UnPublishSingleNode(doc.Id); + umbraco.library.UnPublishSingleNode(doc); } break; case documentCarrier.EPublishAction.Ignore: @@ -260,14 +260,14 @@ namespace umbraco.webservices.documents { if (doc.PublishWithResult(user)) { - umbraco.library.UpdateDocumentCache(doc.Id); + umbraco.library.UpdateDocumentCache(doc); } } else { if (doc.PublishWithResult(user)) { - umbraco.library.UpdateDocumentCache(doc.Id); + umbraco.library.UpdateDocumentCache(doc); } } break; From 0cb9cc6840599d22f0442d61256a92f9da2944a0 Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Wed, 30 Jan 2013 07:59:15 +0600 Subject: [PATCH 08/43] just cleaned up some code formatting. --- .../umbraco/users/UserPermissions.cs | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/users/UserPermissions.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/users/UserPermissions.cs index e2ee304244..018e6d9ff5 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/users/UserPermissions.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/users/UserPermissions.cs @@ -102,11 +102,11 @@ namespace umbraco.cms.presentation.user ///

/// Returns the current user permissions for the node specified /// - /// + /// /// - public List GetExistingNodePermission(int nodeID) + public List GetExistingNodePermission(int nodeId) { - string path = GetNodePath(nodeID); + var path = GetNodePath(nodeId); if (path != "") { //get the user and their permissions @@ -119,13 +119,13 @@ namespace umbraco.cms.presentation.user /// /// gets path attribute for node id passed /// - /// + /// /// - private string GetNodePath(int iNodeID) + private static string GetNodePath(int iNodeId) { - if (Document.IsDocument(iNodeID)) + if (Document.IsDocument(iNodeId)) { - Document doc = new Document(iNodeID); + var doc = new Document(iNodeId); return doc.Path; } @@ -135,14 +135,13 @@ namespace umbraco.cms.presentation.user /// /// Finds all child node IDs /// - /// - /// + /// /// - private List FindChildNodes(int nodeID) + private static IEnumerable FindChildNodes(int nodeId) { - Document[] docs = Document.GetChildrenForTree(nodeID); - List nodeIds = new List(); - foreach (Document doc in docs) + var docs = Document.GetChildrenForTree(nodeId); + var nodeIds = new List(); + foreach (var doc in docs) { nodeIds.Add(doc.Id); if (doc.HasChildren) @@ -153,16 +152,16 @@ namespace umbraco.cms.presentation.user return nodeIds; } - private void InsertPermissions(int[] nodeIDs, IAction permission) + private void InsertPermissions(IEnumerable nodeIDs, IAction permission) { foreach (int i in nodeIDs) InsertPermission(i, permission); } - private void InsertPermission(int nodeID, IAction permission) + private void InsertPermission(int nodeId, IAction permission) { //create a new CMSNode object but don't initialize (this prevents a db query) - CMSNode node = new CMSNode(nodeID, false); + var node = new CMSNode(nodeId, false); Permission.MakeNew(m_user, node, permission.Letter); } From cc5ca0b5fe64ef21e9bdfdcc62745cd04cbfdf41 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Wed, 30 Jan 2013 09:21:43 -0100 Subject: [PATCH 09/43] Fixing U4-359 Previewing new nested pages doesn't work --- .../umbraco/preview/PreviewContent.cs | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/preview/PreviewContent.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/preview/PreviewContent.cs index 92f6203beb..38c376591d 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/preview/PreviewContent.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/preview/PreviewContent.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.Data; using System.Configuration; +using System.Globalization; using System.Linq; using System.Web; using System.Web.Security; @@ -52,13 +54,30 @@ namespace umbraco.presentation.preview // clone xml XmlContent = (XmlDocument)content.Instance.XmlContent.Clone(); - // inject current document xml - int parentId = documentObject.Level == 1 ? -1 : documentObject.Parent.Id; - XmlContent = content.AppendDocumentXml(documentObject.Id, documentObject.Level, parentId, documentObject.ToPreviewXml(XmlContent), XmlContent); + var previewNodes = new List(); + + var parentId = documentObject.Level == 1 ? -1 : documentObject.Parent.Id; + + while (parentId > 0 && XmlContent.GetElementById(parentId.ToString(CultureInfo.InvariantCulture)) == null) + { + var document = new Document(parentId); + previewNodes.Insert(0, document); + parentId = document.ParentId; + } + + previewNodes.Add(documentObject); + + foreach (var document in previewNodes) + { + //Inject preview xml + parentId = document.Level == 1 ? -1 : document.Parent.Id; + var previewXml = document.ToPreviewXml(XmlContent); + content.AppendDocumentXml(document.Id, document.Level, parentId, previewXml, XmlContent); + } if (includeSubs) { - foreach (CMSPreviewNode prevNode in documentObject.GetNodesForPreview(true)) + foreach (var prevNode in documentObject.GetNodesForPreview(true)) { XmlContent = content.AppendDocumentXml(prevNode.NodeId, prevNode.Level, prevNode.ParentId, XmlContent.ReadNode(XmlReader.Create(new StringReader(prevNode.Xml))), XmlContent); } From d5bde0d8dfacce04f60fdeeff4f2d0bc57ac5db7 Mon Sep 17 00:00:00 2001 From: netaddicts Date: Thu, 24 Jan 2013 11:00:15 -0100 Subject: [PATCH 10/43] Makes sure preview is not using cached versions of any macro --- src/Umbraco.Web/umbraco.presentation/macro.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/umbraco.presentation/macro.cs b/src/Umbraco.Web/umbraco.presentation/macro.cs index 2b2d2f9a16..53fc5b940b 100644 --- a/src/Umbraco.Web/umbraco.presentation/macro.cs +++ b/src/Umbraco.Web/umbraco.presentation/macro.cs @@ -311,7 +311,7 @@ namespace umbraco Model.CacheIdentifier = GetCacheIdentifier(Model, pageElements, pageId); - if (Model.CacheDuration > 0) + if (!UmbracoContext.Current.InPreviewMode && Model.CacheDuration > 0) { if (cacheMacroAsString(Model)) { From 30fe0ecaf4f29ca19fe3e4c2d9bebd6f33b86988 Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Wed, 30 Jan 2013 05:55:40 +0600 Subject: [PATCH 11/43] Fixes unit tests and logic for Umbraco_Route_User_Defined_Controller_Action --- src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs | 7 ++++++- src/Umbraco.Web/Mvc/RenderRouteHandler.cs | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index 2c20529d6f..b09cee1c7a 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -69,6 +69,9 @@ 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("Home-Page")] [TestCase("HomePage")] [TestCase("homePage")] @@ -88,7 +91,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 c22a602fc3..427c5ab9ae 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 29ef529c578ed6fd8453f2c5bfbdaa686e0af67f Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Wed, 30 Jan 2013 08:42:26 -0100 Subject: [PATCH 12/43] Fixes U4-1592 so its possible to clear values when saving --- src/umbraco.cms/businesslogic/media/Media.cs | 3 --- src/umbraco.cms/businesslogic/web/Document.cs | 3 --- src/umbraco.editorControls/datepicker/DateData.cs | 2 +- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/umbraco.cms/businesslogic/media/Media.cs b/src/umbraco.cms/businesslogic/media/Media.cs index 076fc37a3e..5a698c9a4f 100644 --- a/src/umbraco.cms/businesslogic/media/Media.cs +++ b/src/umbraco.cms/businesslogic/media/Media.cs @@ -232,9 +232,6 @@ namespace umbraco.cms.businesslogic.media foreach (var property in GenericProperties) { - if (property.Value == null) - continue; - MediaItem.SetValue(property.PropertyType.Alias, property.Value); } diff --git a/src/umbraco.cms/businesslogic/web/Document.cs b/src/umbraco.cms/businesslogic/web/Document.cs index a4c23ab6aa..a32b27a15f 100644 --- a/src/umbraco.cms/businesslogic/web/Document.cs +++ b/src/umbraco.cms/businesslogic/web/Document.cs @@ -887,9 +887,6 @@ namespace umbraco.cms.businesslogic.web foreach (var property in GenericProperties) { - if (property.Value == null) - continue; - Content.SetValue(property.PropertyType.Alias, property.Value); } diff --git a/src/umbraco.editorControls/datepicker/DateData.cs b/src/umbraco.editorControls/datepicker/DateData.cs index ca34f5b343..fe1edc7be4 100644 --- a/src/umbraco.editorControls/datepicker/DateData.cs +++ b/src/umbraco.editorControls/datepicker/DateData.cs @@ -11,7 +11,7 @@ namespace umbraco.editorControls.datepicker public override System.Xml.XmlNode ToXMl(System.Xml.XmlDocument d) { - if (Value.ToString() != "") + if (Value != null && Value.ToString() != "") return d.CreateTextNode(((DateTime) Value).ToString("s")); else return d.CreateTextNode(""); From a2a925fd7a516250be58249f50fa520b59c7c9fd Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Wed, 30 Jan 2013 08:43:23 -0100 Subject: [PATCH 13/43] Fixes U4-1590 so members with a Date picker will save without errors. Improves the saving of date values. --- src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs | 4 +++- src/umbraco.cms/businesslogic/member/Member.cs | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs b/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs index 886b9007da..0eeacc7bfb 100644 --- a/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs @@ -78,7 +78,9 @@ namespace Umbraco.Core.Persistence.Factories } else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Date && property.Value != null && string.IsNullOrWhiteSpace(property.Value.ToString()) == false) { - dto.Date = DateTime.Parse(property.Value.ToString()); + DateTime date; + if(DateTime.TryParse(property.Value.ToString(), out date)) + dto.Date = date; } else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Ntext && property.Value != null) { diff --git a/src/umbraco.cms/businesslogic/member/Member.cs b/src/umbraco.cms/businesslogic/member/Member.cs index b30a664991..94bebaf74a 100644 --- a/src/umbraco.cms/businesslogic/member/Member.cs +++ b/src/umbraco.cms/businesslogic/member/Member.cs @@ -598,7 +598,10 @@ namespace umbraco.cms.businesslogic.member } else if (dbType.Equals("Date")) { - poco.Date = DateTime.Parse(property.Value.ToString()); + DateTime date; + + if(DateTime.TryParse(property.Value.ToString(), out date)) + poco.Date = date; } else if (dbType.Equals("Nvarchar")) { From 1d6587bb6b7bad25e40f49c84208a8a36947877d Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Wed, 30 Jan 2013 09:21:43 -0100 Subject: [PATCH 14/43] Fixing U4-359 Previewing new nested pages doesn't work --- .../umbraco/preview/PreviewContent.cs | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/preview/PreviewContent.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/preview/PreviewContent.cs index 7deebd1613..8600c84c2d 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/preview/PreviewContent.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/preview/PreviewContent.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.Data; using System.Configuration; +using System.Globalization; using System.Linq; using System.Web; using System.Web.Security; @@ -53,13 +55,30 @@ namespace umbraco.presentation.preview // clone xml XmlContent = (XmlDocument)content.Instance.XmlContent.Clone(); - // inject current document xml - int parentId = documentObject.Level == 1 ? -1 : documentObject.Parent.Id; - XmlContent = content.AppendDocumentXml(documentObject.Id, documentObject.Level, parentId, documentObject.ToPreviewXml(XmlContent), XmlContent); + var previewNodes = new List(); + + var parentId = documentObject.Level == 1 ? -1 : documentObject.Parent.Id; + + while (parentId > 0 && XmlContent.GetElementById(parentId.ToString(CultureInfo.InvariantCulture)) == null) + { + var document = new Document(parentId); + previewNodes.Insert(0, document); + parentId = document.ParentId; + } + + previewNodes.Add(documentObject); + + foreach (var document in previewNodes) + { + //Inject preview xml + parentId = document.Level == 1 ? -1 : document.Parent.Id; + var previewXml = document.ToPreviewXml(XmlContent); + content.AppendDocumentXml(document.Id, document.Level, parentId, previewXml, XmlContent); + } if (includeSubs) { - foreach (CMSPreviewNode prevNode in documentObject.GetNodesForPreview(true)) + foreach (var prevNode in documentObject.GetNodesForPreview(true)) { XmlContent = content.AppendDocumentXml(prevNode.NodeId, prevNode.Level, prevNode.ParentId, XmlContent.ReadNode(XmlReader.Create(new StringReader(prevNode.Xml))), XmlContent); } From 14c0e9e1499b88369aceb3c0d869aea6825c4791 Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Wed, 30 Jan 2013 09:33:17 -0100 Subject: [PATCH 15/43] Fixes U4-1584 so property types and related property data is deleted in a way that works for both Document, Media and Member. --- .../controls/ContentTypeControlNew.ascx.cs | 10 +++++++--- .../propertytype/propertytype.cs | 20 ++++++++----------- 2 files changed, 15 insertions(+), 15 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 549ce2657c..f6a54a1d0e 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/controls/ContentTypeControlNew.ascx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/controls/ContentTypeControlNew.ascx.cs @@ -545,10 +545,14 @@ jQuery(document).ready(function() {{ refreshDropDowns(); }}); var gpw = (GenericProperties.GenericPropertyWrapper)sender; var alias = gpw.PropertyType.Alias; - gpw.GenricPropertyControl.PropertyType.delete(); //We have to ensure that the property type is removed from the underlying IContentType object - cType.ContentTypeItem.RemovePropertyType(alias); - cType.Save(); + if (cType.ContentTypeItem != null) + { + cType.ContentTypeItem.RemovePropertyType(alias); + cType.Save(); + } + + gpw.GenricPropertyControl.PropertyType.delete(); cType = ContentType.GetContentType(cType.Id); this.bindDataGenericProperties(true); diff --git a/src/umbraco.cms/businesslogic/propertytype/propertytype.cs b/src/umbraco.cms/businesslogic/propertytype/propertytype.cs index d72a1d3eb3..97563546b9 100644 --- a/src/umbraco.cms/businesslogic/propertytype/propertytype.cs +++ b/src/umbraco.cms/businesslogic/propertytype/propertytype.cs @@ -378,10 +378,6 @@ namespace umbraco.cms.businesslogic.propertytype // flush cache FlushCache(); - // clean all properties on inherited document types (if this propertytype is removed from a master) - CleanPropertiesOnDeletion(_contenttypeid); - // DocumentType.GetAllAsList().FindAll(dt => dt.MasterContentType == _contenttypeid).ForEach(dt => cleanPropertiesOnDeletion(dt.Id)); - // Delete all properties of propertytype CleanPropertiesOnDeletion(_contenttypeid); @@ -413,15 +409,15 @@ namespace umbraco.cms.businesslogic.propertytype DocumentType.GetAllAsList().FindAll(dt => dt.MasterContentTypes.Contains(contentTypeId)).ForEach( dt => CleanPropertiesOnDeletion(dt.Id)); - // then remove from the current doc type - Content[] objs = Content.getContentOfContentType(new ContentType(contentTypeId)); - foreach (Content c in objs.ToList()) + //Initially Content.getContentOfContentType() was called, but because this doesn't include members we resort to sql lookups and deletes + var tmp = new List(); + IRecordsReader dr = SqlHelper.ExecuteReader("SELECT nodeId FROM cmsContent INNER JOIN umbracoNode ON cmsContent.nodeId = umbracoNode.id WHERE ContentType = " + contentTypeId + " ORDER BY umbracoNode.text "); + while (dr.Read()) tmp.Add(dr.GetInt("nodeId")); + dr.Close(); + + foreach (var contentId in tmp) { - Property prop = c.getProperty(this); - if (prop != null) - { - prop.delete(); - } + SqlHelper.ExecuteNonQuery("DELETE FROM cmsPropertyData WHERE PropertyTypeId =" + this.Id + " AND contentNodeId = " + contentId); } // invalidate content type cache From ceb561c113ca0a0849713efb6680e3e38a695c35 Mon Sep 17 00:00:00 2001 From: netaddicts Date: Wed, 30 Jan 2013 09:41:00 -0100 Subject: [PATCH 16/43] Makes sure preview is not using cached versions of any macro --- src/Umbraco.Web/umbraco.presentation/macro.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/umbraco.presentation/macro.cs b/src/Umbraco.Web/umbraco.presentation/macro.cs index d42f8f2a60..4c63531890 100644 --- a/src/Umbraco.Web/umbraco.presentation/macro.cs +++ b/src/Umbraco.Web/umbraco.presentation/macro.cs @@ -311,7 +311,7 @@ namespace umbraco Model.CacheIdentifier = GetCacheIdentifier(Model, pageElements, pageId); - if (Model.CacheDuration > 0) + if (!UmbracoContext.Current.InPreviewMode && Model.CacheDuration > 0) { if (cacheMacroAsString(Model)) { From 97556de447652691b196eb1128921edc04c28da2 Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Wed, 30 Jan 2013 18:58:42 +0600 Subject: [PATCH 17/43] Changed methods created yesterday to internal so we can port to 6+ nicely. --- src/Umbraco.Web/Properties/AssemblyInfo.cs | 3 ++- src/Umbraco.Web/umbraco.presentation/content.cs | 2 +- src/Umbraco.Web/umbraco.presentation/library.cs | 4 ++-- src/umbraco.cms/businesslogic/web/Document.cs | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web/Properties/AssemblyInfo.cs b/src/Umbraco.Web/Properties/AssemblyInfo.cs index 88d65e23cc..aa897d6340 100644 --- a/src/Umbraco.Web/Properties/AssemblyInfo.cs +++ b/src/Umbraco.Web/Properties/AssemblyInfo.cs @@ -28,4 +28,5 @@ using System.Security; [assembly: System.Security.SecurityRules(System.Security.SecurityRuleSet.Level1)] [assembly: InternalsVisibleTo("Umbraco.Tests")] -[assembly: InternalsVisibleTo("umbraco.MacroEngines")] \ No newline at end of file +[assembly: InternalsVisibleTo("umbraco.MacroEngines")] +[assembly: InternalsVisibleTo("umbraco.webservices")] diff --git a/src/Umbraco.Web/umbraco.presentation/content.cs b/src/Umbraco.Web/umbraco.presentation/content.cs index 5161c14119..a8a7b60192 100644 --- a/src/Umbraco.Web/umbraco.presentation/content.cs +++ b/src/Umbraco.Web/umbraco.presentation/content.cs @@ -602,7 +602,7 @@ namespace umbraco /// This means the node gets unpublished from the website. ///
/// The document - public virtual void ClearDocumentCache(Document doc) + internal void ClearDocumentCache(Document doc) { var e = new DocumentCacheEventArgs(); FireBeforeClearDocumentCache(doc, e); diff --git a/src/Umbraco.Web/umbraco.presentation/library.cs b/src/Umbraco.Web/umbraco.presentation/library.cs index 9a081380e3..dfba87492e 100644 --- a/src/Umbraco.Web/umbraco.presentation/library.cs +++ b/src/Umbraco.Web/umbraco.presentation/library.cs @@ -201,7 +201,7 @@ namespace umbraco /// marked unpublished by setting the publish property on the document object to false ///
/// The Document to be unpublished - public static void UnPublishSingleNode(Document document) + internal static void UnPublishSingleNode(Document document) { if (UmbracoSettings.UseDistributedCalls) dispatcher.Remove( @@ -232,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. /// - public static void UpdateDocumentCache(Document doc) + internal static void UpdateDocumentCache(Document doc) { if (UmbracoSettings.UseDistributedCalls) dispatcher.Refresh( diff --git a/src/umbraco.cms/businesslogic/web/Document.cs b/src/umbraco.cms/businesslogic/web/Document.cs index 60f4b8024d..b4ebcf3ca6 100644 --- a/src/umbraco.cms/businesslogic/web/Document.cs +++ b/src/umbraco.cms/businesslogic/web/Document.cs @@ -1541,7 +1541,7 @@ 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 GetPublishedDescendants() + internal IEnumerable GetPublishedDescendants() { var documents = new List(); using (var dr = SqlHelper.ExecuteReader( From 0c19307fa3cddf6dd7ba8b8288eb524dca9721c2 Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Wed, 30 Jan 2013 12:11:10 -0100 Subject: [PATCH 18/43] Making a few optimizations based on the findings in v.4.11.4. --- src/Umbraco.Core/Services/ContentService.cs | 28 ++++++++++++++--- .../Persistence/Querying/QueryBuilderTests.cs | 31 +++++++++++++++++++ .../umbraco/editContent.aspx.cs | 19 ++++++++---- 3 files changed, 67 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index ed438d6967..a65b37f31d 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -1054,6 +1054,22 @@ namespace Umbraco.Core.Services return SaveAndPublishDo(content, omitCacheRefresh, userId, raiseEvents); } + /// + /// Gets a collection of descendants by the first Parent. + /// + /// item to retrieve Descendants from + /// An Enumerable list of objects + internal IEnumerable GetPublishedDescendants(IContent content) + { + using (var repository = _repositoryFactory.CreateContentRepository(_uowProvider.GetUnitOfWork())) + { + var query = Query.Builder.Where(x => x.Id != content.Id && x.Path.StartsWith(content.Path) && x.Published == true && x.Trashed == false); + var contents = repository.GetByQuery(query); + + return contents; + } + } + #endregion #region Private Methods @@ -1243,6 +1259,9 @@ namespace Umbraco.Core.Services return false; } + //Has this content item previously been published? If so, we don't need to refresh the children + var previouslyPublished = HasPublishedVersion(content.Id); + //Check if parent is published (although not if its a root node) - if parent isn't published this Content cannot be published if (content.ParentId != -1 && content.ParentId != -20 && IsPublishable(content) == false) { @@ -1294,13 +1313,12 @@ namespace Umbraco.Core.Services if (omitCacheRefresh == false) _publishingStrategy.PublishingFinalized(content); - //We need to check if children and their publish state to ensure that we republish content that was previously published - if (omitCacheRefresh == false && HasChildren(content.Id)) + //We need to check if children and their publish state to ensure that we 'republish' content that was previously published + if (omitCacheRefresh == false && previouslyPublished == false && HasChildren(content.Id)) { - var children = GetDescendants(content); - var shouldBeRepublished = children.Where(child => HasPublishedVersion(child.Id)); + var descendants = GetPublishedDescendants(content); - _publishingStrategy.PublishingFinalized(shouldBeRepublished, false); + _publishingStrategy.PublishingFinalized(descendants, false); } Audit.Add(AuditTypes.Publish, "Save and Publish performed by user", userId, content.Id); diff --git a/src/Umbraco.Tests/Persistence/Querying/QueryBuilderTests.cs b/src/Umbraco.Tests/Persistence/Querying/QueryBuilderTests.cs index 46bc9099ac..282d93bd1c 100644 --- a/src/Umbraco.Tests/Persistence/Querying/QueryBuilderTests.cs +++ b/src/Umbraco.Tests/Persistence/Querying/QueryBuilderTests.cs @@ -1,6 +1,7 @@ using System; using NUnit.Framework; using Umbraco.Core.Models; +using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Querying; using Umbraco.Tests.TestHelpers; @@ -78,5 +79,35 @@ namespace Umbraco.Tests.Persistence.Querying Assert.That(strResult, Is.EqualTo(expectedResult)); Console.WriteLine(strResult); } + + [Test] + public void Can_Build_PublishedDescendants_Query_For_IContent() + { + // Arrange + var path = "-1,1046,1076,1089"; + var id = 1046; + var nodeObjectTypeId = new Guid("C66BA18E-EAF3-4CFF-8A22-41B16D66A972"); + + var sql = new Sql(); + sql.Select("*") + .From() + .InnerJoin() + .On(left => left.VersionId, right => right.VersionId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(x => x.NodeObjectType == nodeObjectTypeId); + + var query = Query.Builder.Where(x => x.Path.StartsWith(path) && x.Id != id && x.Published == true && x.Trashed == false); + + // Act + var translator = new SqlTranslator(sql, query); + var result = translator.Translate(); + var strResult = result.SQL; + + // Assert + Console.WriteLine(strResult); + } } } \ No newline at end of file diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs index 08fa0f6ed8..d6ef34ee67 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs @@ -4,6 +4,7 @@ using System.Web.UI.WebControls; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Caching; +using Umbraco.Core.Services; using umbraco.BusinessLogic.Actions; using umbraco.IO; using umbraco.uicontrols.DatePicker; @@ -316,6 +317,8 @@ namespace umbraco.cms.presentation { if (_document.Level == 1 || _document.PathPublished) { + var previouslyPublished = _document.HasPublishedVersion(); + Trace.Warn("before d.publish"); if (_document.PublishWithResult(base.getUser())) @@ -330,15 +333,19 @@ namespace umbraco.cms.presentation _documentHasPublishedVersion = _document.HasPublishedVersion(); - var descendants = ApplicationContext.Current.Services.ContentService.GetDescendants(_document.Id); - var publishableDescendants = descendants.Where(descendant => descendant.HasPublishedVersion()).ToList(); - if(publishableDescendants.Any()) + if (previouslyPublished == false) { - foreach (var descendant in publishableDescendants) + var descendants = ((ContentService) ApplicationContext.Current.Services.ContentService) + .GetPublishedDescendants(_document.Content).ToList(); + + if (descendants.Any()) { - library.UpdateDocumentCache(descendant.Id); + foreach (var descendant in descendants) + { + library.UpdateDocumentCache(descendant.Id); + } + library.RefreshContent(); } - library.RefreshContent(); } } else From b722bce2ed6d797eccc4160114a94da30e0b5a8c Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Wed, 30 Jan 2013 19:15:16 +0600 Subject: [PATCH 19/43] Fixes: #U4-1593 - ensures that the content tree checks for the Published property not HasPublishedVersion() --- .../umbraco.presentation/umbraco/Trees/BaseContentTree.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/BaseContentTree.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/BaseContentTree.cs index aa5e64c9ea..6a86e35fba 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.HasPublishedVersion() == false) + if (dd.Published == false) node.Style.DimNode(); if (dd.HasPendingChanges()) From 19869e6d5f840c777ca14b4ed720cd6fc74042db Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Wed, 30 Jan 2013 14:22:07 -0100 Subject: [PATCH 20/43] Possible fix for U4-1539 Removing SaveXmlPreview from the Document class save methods. The Save and SaveAndPublish methods in the ContentService now handle the saving of preview xml to the database. --- src/Umbraco.Core/Services/ContentService.cs | 42 ++++++++++++++++--- src/umbraco.cms/businesslogic/web/Document.cs | 4 -- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index a65b37f31d..21a064581e 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -1298,11 +1298,27 @@ namespace Umbraco.Core.Services if (published) { var xml = content.ToXml(); - var poco = new ContentXmlDto { NodeId = content.Id, Xml = xml.ToString(SaveOptions.None) }; - var exists = uow.Database.FirstOrDefault("WHERE nodeId = @Id", new { Id = content.Id }) != null; - int result = exists - ? uow.Database.Update(poco) - : Convert.ToInt32(uow.Database.Insert(poco)); + //Content Xml + var contentPoco = new ContentXmlDto { NodeId = content.Id, Xml = xml.ToString(SaveOptions.None) }; + var contentExists = uow.Database.ExecuteScalar("SELECT COUNT(nodeId) FROM cmsContentXml WHERE nodeId = @Id", new { Id = content.Id }) != 0; + int contentResult = contentExists + ? uow.Database.Update(contentPoco) + : Convert.ToInt32(uow.Database.Insert(contentPoco)); + //Preview Xml + var previewPoco = new PreviewXmlDto + { + NodeId = content.Id, + Timestamp = DateTime.Now, + VersionId = content.Version, + Xml = xml.ToString(SaveOptions.None) + }; + var previewExists = + uow.Database.ExecuteScalar("SELECT COUNT(nodeId) FROM cmsPreviewXml WHERE nodeId = @Id AND versionId = @Version", + new {Id = content.Id, Version = content.Version}) != 0; + int previewResult = previewExists + ? uow.Database.Update(previewPoco) + : Convert.ToInt32(uow.Database.Insert(previewPoco)); + } } @@ -1352,6 +1368,22 @@ namespace Umbraco.Core.Services repository.AddOrUpdate(content); uow.Commit(); + + //Preview Xml + var xml = content.ToXml(); + var previewPoco = new PreviewXmlDto + { + NodeId = content.Id, + Timestamp = DateTime.Now, + VersionId = content.Version, + Xml = xml.ToString(SaveOptions.None) + }; + var previewExists = + uow.Database.ExecuteScalar("SELECT COUNT(nodeId) FROM cmsPreviewXml WHERE nodeId = @Id AND versionId = @Version", + new { Id = content.Id, Version = content.Version }) != 0; + int previewResult = previewExists + ? uow.Database.Update(previewPoco) + : Convert.ToInt32(uow.Database.Insert(previewPoco)); } if(raiseEvents) diff --git a/src/umbraco.cms/businesslogic/web/Document.cs b/src/umbraco.cms/businesslogic/web/Document.cs index a32b27a15f..d2636232ba 100644 --- a/src/umbraco.cms/businesslogic/web/Document.cs +++ b/src/umbraco.cms/businesslogic/web/Document.cs @@ -897,8 +897,6 @@ namespace umbraco.cms.businesslogic.web ApplicationContext.Current.Services.ContentService.Save(Content, userId); base.Save(); - // update preview xml - SaveXmlPreview(new XmlDocument()); FireAfterSave(e); } @@ -927,8 +925,6 @@ namespace umbraco.cms.businesslogic.web var result = ((ContentService)ApplicationContext.Current.Services.ContentService).SaveAndPublish(Content, true, u.Id); base.Save(); - // update preview xml - SaveXmlPreview(new XmlDocument()); FireAfterSave(e); From b9be5c25615f0f69ae0b91169106ba40d0f42044 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Wed, 30 Jan 2013 15:01:38 -0100 Subject: [PATCH 21/43] Also implement optimization in fdfa687e6f41 to v4: no need to try and republish the child pages if the page you are trying to publish was already published --- .../umbraco/editContent.aspx.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs index c074e1cbad..0b971a189a 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs @@ -309,6 +309,8 @@ namespace umbraco.cms.presentation { if (_document.Level == 1 || new cms.businesslogic.web.Document(_document.Parent.Id).PathPublished) { + var previouslyPublished = _document.Published; + Trace.Warn("before d.publish"); if (_document.PublishWithResult(base.getUser())) @@ -322,13 +324,17 @@ namespace umbraco.cms.presentation if (base.getUser().GetPermissions(_document.Path).IndexOf("U") > -1) UnPublish.Visible = true; - _documentHasPublishedVersion = _document.HasPublishedVersion(); - - foreach (var descendant in _document.GetPublishedDescendants()) + + if (previouslyPublished == false) { - library.UpdateDocumentCache(descendant); + _documentHasPublishedVersion = _document.HasPublishedVersion(); + + foreach (var descendant in _document.GetPublishedDescendants()) + { + library.UpdateDocumentCache(descendant); + } } - + } else { From b20bb7a5a21112c068c4633c322f58191c80f913 Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Wed, 30 Jan 2013 16:23:33 -0100 Subject: [PATCH 22/43] Fixes unit tests using the ContentService.Save method. Because we are using .ToXml in the save method to save preview xml we need to setup the DataTypesResolver in the test setup. --- .../Repositories/ContentRepositoryTest.cs | 20 +++++++++++++++++++ .../Repositories/RelationRepositoryTest.cs | 20 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs index bc59b85d18..8400f1afe0 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Querying; @@ -8,6 +9,8 @@ using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; +using umbraco.editorControls.tinyMCE3; +using umbraco.interfaces; namespace Umbraco.Tests.Persistence.Repositories { @@ -17,6 +20,20 @@ namespace Umbraco.Tests.Persistence.Repositories [SetUp] public override void Initialize() { + //NOTE The DataTypesResolver is only necessary because we are using the Save method in the ContentService + //this ensures its reset + PluginManager.Current = new PluginManager(); + + //for testing, we'll specify which assemblies are scanned for the PluginTypeResolver + PluginManager.Current.AssembliesToScan = new[] + { + typeof(IDataType).Assembly, + typeof(tinyMCE3dataType).Assembly + }; + + DataTypesResolver.Current = new DataTypesResolver( + PluginManager.Current.ResolveDataTypes()); + base.Initialize(); CreateTestData(); @@ -25,6 +42,9 @@ namespace Umbraco.Tests.Persistence.Repositories [TearDown] public override void TearDown() { + //reset the app context + DataTypesResolver.Reset(); + base.TearDown(); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs index 8730dc3aad..5e907c53b2 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Caching; using Umbraco.Core.Persistence.Querying; @@ -8,6 +9,8 @@ using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; +using umbraco.editorControls.tinyMCE3; +using umbraco.interfaces; namespace Umbraco.Tests.Persistence.Repositories { @@ -17,6 +20,20 @@ namespace Umbraco.Tests.Persistence.Repositories [SetUp] public override void Initialize() { + //NOTE The DataTypesResolver is only necessary because we are using the Save method in the ContentService + //this ensures its reset + PluginManager.Current = new PluginManager(); + + //for testing, we'll specify which assemblies are scanned for the PluginTypeResolver + PluginManager.Current.AssembliesToScan = new[] + { + typeof(IDataType).Assembly, + typeof(tinyMCE3dataType).Assembly + }; + + DataTypesResolver.Current = new DataTypesResolver( + PluginManager.Current.ResolveDataTypes()); + base.Initialize(); CreateTestData(); @@ -237,6 +254,9 @@ namespace Umbraco.Tests.Persistence.Repositories [TearDown] public override void TearDown() { + //reset the app context + DataTypesResolver.Reset(); + base.TearDown(); } From 00cf20a8d0c85cd0e3d10a429a1909f618fc1d0c Mon Sep 17 00:00:00 2001 From: "NielsHartvig@UMBRACORATI.localdomain" Date: Wed, 30 Jan 2013 19:41:36 -0100 Subject: [PATCH 23/43] Adds support for install statistics --- src/Umbraco.Web.UI/install/default.aspx | 8 +- src/Umbraco.Web.UI/install/steps/theend.ascx | 3 + src/Umbraco.Web.UI/install/steps/welcome.ascx | 7 +- .../org.umbraco.update/Reference.cs | 120 +++++++++++++----- .../org.umbraco.update/Reference.map | 2 +- .../org.umbraco.update/checkforupgrade.wsdl | 66 +++++++++- .../install/steps/theend.ascx | 3 + .../install/steps/welcome.ascx | 7 +- .../webservices/CheckForUpgrade.asmx.cs | 44 +++++++ 9 files changed, 218 insertions(+), 42 deletions(-) diff --git a/src/Umbraco.Web.UI/install/default.aspx b/src/Umbraco.Web.UI/install/default.aspx index 2d0acda187..9e5f9056da 100644 --- a/src/Umbraco.Web.UI/install/default.aspx +++ b/src/Umbraco.Web.UI/install/default.aspx @@ -11,7 +11,7 @@ - + " /> @@ -40,7 +40,11 @@
- + + + + +
diff --git a/src/Umbraco.Web.UI/install/steps/theend.ascx b/src/Umbraco.Web.UI/install/steps/theend.ascx index 61c6fd86cb..f9c6f30107 100644 --- a/src/Umbraco.Web.UI/install/steps/theend.ascx +++ b/src/Umbraco.Web.UI/install/steps/theend.ascx @@ -12,6 +12,9 @@ jQuery(document).ready(function () { function (data) { jQuery("#ajax-developervids").html(data); }); + + umbraco.presentation.webservices.CheckForUpgrade.InstallStatus(true, navigator.userAgent, ""); + }); diff --git a/src/Umbraco.Web.UI/install/steps/welcome.ascx b/src/Umbraco.Web.UI/install/steps/welcome.ascx index 18f24a143d..a0ce00d7f1 100644 --- a/src/Umbraco.Web.UI/install/steps/welcome.ascx +++ b/src/Umbraco.Web.UI/install/steps/welcome.ascx @@ -47,4 +47,9 @@ Let's get started! - \ No newline at end of file + + \ No newline at end of file diff --git a/src/Umbraco.Web/Web References/org.umbraco.update/Reference.cs b/src/Umbraco.Web/Web References/org.umbraco.update/Reference.cs index 87a309f714..c6a3c0dc17 100644 --- a/src/Umbraco.Web/Web References/org.umbraco.update/Reference.cs +++ b/src/Umbraco.Web/Web References/org.umbraco.update/Reference.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.544 +// Runtime Version:4.0.30319.18033 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -9,27 +9,28 @@ //------------------------------------------------------------------------------ // -// This source code was auto-generated by Microsoft.VSDesigner, Version 4.0.30319.544. +// This source code was auto-generated by Microsoft.VSDesigner, Version 4.0.30319.18033. // #pragma warning disable 1591 -namespace umbraco.presentation.org.umbraco.update -{ +namespace umbraco.presentation.org.umbraco.update { using System; using System.Web.Services; using System.Diagnostics; using System.Web.Services.Protocols; - using System.ComponentModel; using System.Xml.Serialization; + using System.ComponentModel; /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.1")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.17929")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Web.Services.WebServiceBindingAttribute(Name="CheckForUpgradeSoap", Namespace="http://update.umbraco.org/")] public partial class CheckForUpgrade : System.Web.Services.Protocols.SoapHttpClientProtocol { + private System.Threading.SendOrPostCallback InstallOperationCompleted; + private System.Threading.SendOrPostCallback CheckUpgradeOperationCompleted; private bool useDefaultCredentialsSetExplicitly; @@ -70,34 +71,85 @@ namespace umbraco.presentation.org.umbraco.update } } + /// + public event InstallCompletedEventHandler InstallCompleted; + /// public event CheckUpgradeCompletedEventHandler CheckUpgradeCompleted; + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://update.umbraco.org/Install", RequestNamespace="http://update.umbraco.org/", ResponseNamespace="http://update.umbraco.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public void Install(System.Guid installId, bool isUpgrade, bool installCompleted, System.DateTime timestamp, int versionMajor, int versionMinor, int versionPatch, string versionComment, string error, string userAgent, string dbProvider) { + this.Invoke("Install", new object[] { + installId, + isUpgrade, + installCompleted, + timestamp, + versionMajor, + versionMinor, + versionPatch, + versionComment, + error, + userAgent, + dbProvider}); + } + + /// + public void InstallAsync(System.Guid installId, bool isUpgrade, bool installCompleted, System.DateTime timestamp, int versionMajor, int versionMinor, int versionPatch, string versionComment, string error, string userAgent, string dbProvider) { + this.InstallAsync(installId, isUpgrade, installCompleted, timestamp, versionMajor, versionMinor, versionPatch, versionComment, error, userAgent, dbProvider, null); + } + + /// + public void InstallAsync(System.Guid installId, bool isUpgrade, bool installCompleted, System.DateTime timestamp, int versionMajor, int versionMinor, int versionPatch, string versionComment, string error, string userAgent, string dbProvider, object userState) { + if ((this.InstallOperationCompleted == null)) { + this.InstallOperationCompleted = new System.Threading.SendOrPostCallback(this.OnInstallOperationCompleted); + } + this.InvokeAsync("Install", new object[] { + installId, + isUpgrade, + installCompleted, + timestamp, + versionMajor, + versionMinor, + versionPatch, + versionComment, + error, + userAgent, + dbProvider}, this.InstallOperationCompleted, userState); + } + + private void OnInstallOperationCompleted(object arg) { + if ((this.InstallCompleted != null)) { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.InstallCompleted(this, new System.ComponentModel.AsyncCompletedEventArgs(invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + /// [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://update.umbraco.org/CheckUpgrade", RequestNamespace="http://update.umbraco.org/", ResponseNamespace="http://update.umbraco.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] - public UpgradeResult CheckUpgrade(int VersionMajor, int VersionMinor, int VersionPatch, string versionComment) { + public UpgradeResult CheckUpgrade(int versionMajor, int versionMinor, int versionPatch, string versionComment) { object[] results = this.Invoke("CheckUpgrade", new object[] { - VersionMajor, - VersionMinor, - VersionPatch, + versionMajor, + versionMinor, + versionPatch, versionComment}); return ((UpgradeResult)(results[0])); } /// - public void CheckUpgradeAsync(int VersionMajor, int VersionMinor, int VersionPatch, string versionComment) { - this.CheckUpgradeAsync(VersionMajor, VersionMinor, VersionPatch, versionComment, null); + public void CheckUpgradeAsync(int versionMajor, int versionMinor, int versionPatch, string versionComment) { + this.CheckUpgradeAsync(versionMajor, versionMinor, versionPatch, versionComment, null); } /// - public void CheckUpgradeAsync(int VersionMajor, int VersionMinor, int VersionPatch, string versionComment, object userState) { + public void CheckUpgradeAsync(int versionMajor, int versionMinor, int versionPatch, string versionComment, object userState) { if ((this.CheckUpgradeOperationCompleted == null)) { this.CheckUpgradeOperationCompleted = new System.Threading.SendOrPostCallback(this.OnCheckUpgradeOperationCompleted); } this.InvokeAsync("CheckUpgrade", new object[] { - VersionMajor, - VersionMinor, - VersionPatch, + versionMajor, + versionMinor, + versionPatch, versionComment}, this.CheckUpgradeOperationCompleted, userState); } @@ -128,28 +180,18 @@ namespace umbraco.presentation.org.umbraco.update } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.450")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.18033")] [System.SerializableAttribute()] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://update.umbraco.org/")] public partial class UpgradeResult { - private UpgradeType upgradeTypeField; - private string commentField; - private string upgradeUrlField; + private UpgradeType upgradeTypeField; - /// - public UpgradeType UpgradeType { - get { - return this.upgradeTypeField; - } - set { - this.upgradeTypeField = value; - } - } + private string upgradeUrlField; /// public string Comment { @@ -161,6 +203,16 @@ namespace umbraco.presentation.org.umbraco.update } } + /// + public UpgradeType UpgradeType { + get { + return this.upgradeTypeField; + } + set { + this.upgradeTypeField = value; + } + } + /// public string UpgradeUrl { get { @@ -173,7 +225,7 @@ namespace umbraco.presentation.org.umbraco.update } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.450")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.18033")] [System.SerializableAttribute()] [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://update.umbraco.org/")] public enum UpgradeType { @@ -201,11 +253,15 @@ namespace umbraco.presentation.org.umbraco.update } /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.1")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.17929")] + public delegate void InstallCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.17929")] public delegate void CheckUpgradeCompletedEventHandler(object sender, CheckUpgradeCompletedEventArgs e); /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.1")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.17929")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class CheckUpgradeCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { diff --git a/src/Umbraco.Web/Web References/org.umbraco.update/Reference.map b/src/Umbraco.Web/Web References/org.umbraco.update/Reference.map index a0cba8d88b..dc2f3d1d64 100644 --- a/src/Umbraco.Web/Web References/org.umbraco.update/Reference.map +++ b/src/Umbraco.Web/Web References/org.umbraco.update/Reference.map @@ -1,7 +1,7 @@ - + \ No newline at end of file diff --git a/src/Umbraco.Web/Web References/org.umbraco.update/checkforupgrade.wsdl b/src/Umbraco.Web/Web References/org.umbraco.update/checkforupgrade.wsdl index 9661c33653..5c700af0bb 100644 --- a/src/Umbraco.Web/Web References/org.umbraco.update/checkforupgrade.wsdl +++ b/src/Umbraco.Web/Web References/org.umbraco.update/checkforupgrade.wsdl @@ -1,13 +1,34 @@ - + + + + + + + + + + + + + + + + + + + + + + - - - + + + @@ -21,8 +42,8 @@ - + @@ -38,7 +59,20 @@ + + + + + + + + + + + + + @@ -46,6 +80,10 @@ + + + + @@ -53,6 +91,15 @@ + + + + + + + + + @@ -65,6 +112,15 @@ + + + + + + + + + diff --git a/src/Umbraco.Web/umbraco.presentation/install/steps/theend.ascx b/src/Umbraco.Web/umbraco.presentation/install/steps/theend.ascx index 61c6fd86cb..f9c6f30107 100644 --- a/src/Umbraco.Web/umbraco.presentation/install/steps/theend.ascx +++ b/src/Umbraco.Web/umbraco.presentation/install/steps/theend.ascx @@ -12,6 +12,9 @@ jQuery(document).ready(function () { function (data) { jQuery("#ajax-developervids").html(data); }); + + umbraco.presentation.webservices.CheckForUpgrade.InstallStatus(true, navigator.userAgent, ""); + }); diff --git a/src/Umbraco.Web/umbraco.presentation/install/steps/welcome.ascx b/src/Umbraco.Web/umbraco.presentation/install/steps/welcome.ascx index 18f24a143d..a0ce00d7f1 100644 --- a/src/Umbraco.Web/umbraco.presentation/install/steps/welcome.ascx +++ b/src/Umbraco.Web/umbraco.presentation/install/steps/welcome.ascx @@ -47,4 +47,9 @@ Let's get started! - \ No newline at end of file + + \ No newline at end of file diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/CheckForUpgrade.asmx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/CheckForUpgrade.asmx.cs index f06a7e43c7..7c4e000047 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/CheckForUpgrade.asmx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/CheckForUpgrade.asmx.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Web; using System.Web.Services; using System.Web.Script.Services; +using Umbraco.Core; using Umbraco.Core.Configuration; @@ -32,7 +33,50 @@ namespace umbraco.presentation.webservices return new UpgradeResult(result.UpgradeType.ToString(), result.Comment, result.UpgradeUrl); } + [WebMethod] + [ScriptMethod] + public void InstallStatus(bool isCompleted, string userAgent, string errorMsg) + { + bool isUpgrade = false; + // if it's an upgrade, you'll need to be logged in before we allow this call + if (!String.IsNullOrEmpty(Umbraco.Core.Configuration.GlobalSettings.ConfigurationStatus)) + { + isUpgrade = true; + legacyAjaxCalls.Authorize(); + } + + // Check for current install Id + Guid installId = Guid.NewGuid(); + BusinessLogic.StateHelper.Cookies.Cookie installCookie = + new BusinessLogic.StateHelper.Cookies.Cookie("umb_installId", 1); + if (!String.IsNullOrEmpty(installCookie.GetValue())) + { + if (Guid.TryParse(installCookie.GetValue(), out installId)) + { + // check that it's a valid Guid + if (installId == Guid.Empty) + installId = Guid.NewGuid(); + + } + } + installCookie.SetValue(installId.ToString()); + + org.umbraco.update.CheckForUpgrade check = new global::umbraco.presentation.org.umbraco.update.CheckForUpgrade(); + check.Install(installId, + isUpgrade, + isCompleted, + DateTime.Now, + UmbracoVersion.Current.Major, + UmbracoVersion.Current.Minor, + UmbracoVersion.Current.Build, + UmbracoVersion.CurrentComment, + errorMsg, + userAgent, + ApplicationContext.Current.DatabaseContext.DatabaseProvider.ToString()); + } } + + public class UpgradeResult { public string UpgradeType { get; set; } From a5bea7fc59596afe19a80065556d2156e874358f Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Thu, 31 Jan 2013 04:26:37 +0600 Subject: [PATCH 24/43] Added the ability to automate any c# scripts for an upgrade process. I realize this is superceded already in 6.0 but we need a way to do this in 4.x too especially for this release since we need to run a script to fix some db issues. I've added a framework using an UpgradeScriptManager and another install step + unit tests for some of the UpgradeScriptManager methods. --- .../Configuration/GlobalSettings.cs | 25 ++++ .../Install/UpgradeScriptsTests.cs | 66 +++++++++ src/Umbraco.Tests/Umbraco.Tests.csproj | 1 + src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 8 ++ .../install/steps/UpgradeScripts.ascx.cs | 28 ++++ .../steps/UpgradeScripts.ascx.designer.cs | 24 ++++ .../Install/UpgradeScripts/ContentPathFix.cs | 130 ++++++++++++++++++ .../Install/UpgradeScripts/IUpgradeScript.cs | 7 + .../UpgradeScripts/UpgradeScriptManager.cs | 84 +++++++++++ .../UpgradeScripts/UpgradeScriptRegistrar.cs | 28 ++++ .../Install/UpgradeScripts/VersionRange.cs | 40 ++++++ src/Umbraco.Web/Properties/AssemblyInfo.cs | 1 + src/Umbraco.Web/Umbraco.Web.csproj | 10 +- src/Umbraco.Web/WebBootManager.cs | 2 + .../install/default.aspx.cs | 5 +- .../install/steps/Definitions/Database.cs | 23 ++-- .../steps/Definitions/FilePermissions.cs | 3 +- .../steps/Definitions/UpgradeScripts.cs | 78 +++++++++++ .../install/utills/p.aspx.cs | 7 + .../Installer/DefaultInstallerUtility.cs | 42 +----- .../Utility/Installer/VersionSpecs.cs | 44 ++++++ .../umbraco.datalayer.csproj | 1 + 22 files changed, 601 insertions(+), 56 deletions(-) create mode 100644 src/Umbraco.Tests/Install/UpgradeScriptsTests.cs create mode 100644 src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.cs create mode 100644 src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.designer.cs create mode 100644 src/Umbraco.Web/Install/UpgradeScripts/ContentPathFix.cs create mode 100644 src/Umbraco.Web/Install/UpgradeScripts/IUpgradeScript.cs create mode 100644 src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptManager.cs create mode 100644 src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptRegistrar.cs create mode 100644 src/Umbraco.Web/Install/UpgradeScripts/VersionRange.cs create mode 100644 src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/UpgradeScripts.cs create mode 100644 src/umbraco.datalayer/Utility/Installer/VersionSpecs.cs diff --git a/src/Umbraco.Core/Configuration/GlobalSettings.cs b/src/Umbraco.Core/Configuration/GlobalSettings.cs index 3c15ce75cf..8728bb30ff 100644 --- a/src/Umbraco.Core/Configuration/GlobalSettings.cs +++ b/src/Umbraco.Core/Configuration/GlobalSettings.cs @@ -181,6 +181,31 @@ namespace Umbraco.Core.Configuration SaveSetting("umbracoConfigurationStatus", value); } } + + /// + /// Returns the configuration status version as a versoin object or null if it cannot parse + /// + /// + internal static Version GetConfigurationVersion() + { + //create a real version out of the one stored in the settings + var configVersion = ConfigurationStatus.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries); + if (configVersion.Length == 0) + return null; + + int major; + var minor = 0; + var patch = 0; + int currentPart; + if (configVersion.Length > 0 && int.TryParse(configVersion[0], out currentPart)) + major = currentPart; + else + return null; //couldn't parse, no valid version + if (configVersion.Length > 1 && int.TryParse(configVersion[1], out currentPart)) minor = currentPart; + if (configVersion.Length > 2 && int.TryParse(configVersion[2], out currentPart)) patch = currentPart; + + return new Version(major, minor, patch); + } /// /// Saves a setting into the configuration file. diff --git a/src/Umbraco.Tests/Install/UpgradeScriptsTests.cs b/src/Umbraco.Tests/Install/UpgradeScriptsTests.cs new file mode 100644 index 0000000000..04a3f81dfb --- /dev/null +++ b/src/Umbraco.Tests/Install/UpgradeScriptsTests.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using NUnit.Framework; +using Umbraco.Web.Install.UpgradeScripts; + +namespace Umbraco.Tests.Install +{ + [TestFixture] + public class UpgradeScriptsTests + { + [TearDown] + public void TearDown() + { + UpgradeScriptManager.Clear(); + } + + [TestCase("0.0.0", "6.0.0", "4.10.0", true)] + [TestCase("4.10.0", "6.0.0", "4.10.0", true)] + [TestCase("4.10.0", "4.11.4", "4.10.0", true)] + [TestCase("4.11.0", "4.11.4", "4.10.0", false)] + [TestCase("4.11.0", "6.0.0", "4.10.0", false)] + [TestCase("6.0.0", "6.0.0", "6.0.0", false)] //this is not in range because it is up to 6.0 but not including 6.0 + [TestCase("6.0.0", "6.0.0", "6.0.1", false)] + public void Test_Version_Range(string startVersion, string endVersion, string current, bool inRange) + { + var currVersionParts = current.Split('.').Select(int.Parse).ToArray(); + var currentVersion = new Version(currVersionParts[0], currVersionParts[1], currVersionParts[2]); + + var startVersionParts = startVersion.Split('.').Select(int.Parse).ToArray(); + var endVersionParts = endVersion.Split('.').Select(int.Parse).ToArray(); + + UpgradeScriptManager.AddUpgradeScript( + new VersionRange( + new Version(startVersionParts[0], startVersionParts[1], startVersionParts[2]), + new Version(endVersionParts[0], endVersionParts[1], endVersionParts[2]))); + + Assert.AreEqual(inRange, UpgradeScriptManager.HasScriptsForVersion(currentVersion)); + } + + [Test] + public void Test_Specific_Version() + { + var currentVersion = new Version(4, 10, 0); + + UpgradeScriptManager.AddUpgradeScript( + new VersionRange( + new Version(4, 10, 0))); + + Assert.IsTrue(UpgradeScriptManager.HasScriptsForVersion(currentVersion)); + Assert.IsFalse(UpgradeScriptManager.HasScriptsForVersion(new Version(4, 10, 11))); + Assert.IsFalse(UpgradeScriptManager.HasScriptsForVersion(new Version(4, 11, 0))); + } + + public class UpgradeScript1 : IUpgradeScript + { + public void Execute() + { + Debug.WriteLine("Executing!"); + } + } + + } +} diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index c7bfb8cba0..0634e58db7 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -63,6 +63,7 @@ + diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 09d081e51f..b99a660c02 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -289,6 +289,13 @@ loadStarterKits.ascx + + UpgradeScripts.ascx + ASPXCodeBehind + + + UpgradeScripts.ascx + editMacro.aspx @@ -418,6 +425,7 @@ UI.xml + diff --git a/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.cs b/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.cs new file mode 100644 index 0000000000..0d94b30821 --- /dev/null +++ b/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; +using Umbraco.Core.Configuration; +using umbraco.presentation.install; +using Umbraco.Web.Install.UpgradeScripts; + +namespace Umbraco.Web.UI.Install.Steps +{ + public partial class UpgradeScripts : System.Web.UI.UserControl + { + protected void Page_Load(object sender, EventArgs e) + { + + } + + protected void RunScripts(object sender, EventArgs e) + { + //run the scripts and then go to the next step + UpgradeScriptManager.ExecuteScriptsForVersion(GlobalSettings.GetConfigurationVersion()); + + Helper.RedirectToNextStep(Page); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.designer.cs b/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.designer.cs new file mode 100644 index 0000000000..a55927fd35 --- /dev/null +++ b/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.designer.cs @@ -0,0 +1,24 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Umbraco.Web.UI.Install.Steps { + + + public partial class UpgradeScripts { + + /// + /// btnNext control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.LinkButton btnNext; + } +} diff --git a/src/Umbraco.Web/Install/UpgradeScripts/ContentPathFix.cs b/src/Umbraco.Web/Install/UpgradeScripts/ContentPathFix.cs new file mode 100644 index 0000000000..f52ae5078d --- /dev/null +++ b/src/Umbraco.Web/Install/UpgradeScripts/ContentPathFix.cs @@ -0,0 +1,130 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using Umbraco.Core; +using Umbraco.Core.IO; +using umbraco.cms.businesslogic; +using umbraco.cms.businesslogic.web; + +namespace Umbraco.Web.Install.UpgradeScripts +{ + /// + /// An upgrade script to fix a moving issue in 4.10+ + /// http://issues.umbraco.org/issue/U4-1491 + /// + public class ContentPathFix : IUpgradeScript + { + private readonly StringBuilder _report = new StringBuilder(); + + public void Execute() + { + //return; + if (ApplicationContext.Current == null) return; + if (HasBeenFixed()) return; + Fix(); + WriteReport(); + } + + private void Fix() + { + AddReportLine("Starting fix paths script"); + + //fix content + AddReportLine("Fixing content"); + foreach (var d in Document.GetRootDocuments()) + { + FixPathsForChildren(d, content => ((Document)content).Children); + } + AddReportLine("Fixing content recycle bin"); + var contentRecycleBin = new RecycleBin(RecycleBin.RecycleBinType.Content); + foreach (var d in contentRecycleBin.Children) + { + FixPathsForChildren(new Document(d.Id), content => ((Document)content).Children); + } + + //fix media + AddReportLine("Fixing media"); + foreach (var d in global::umbraco.cms.businesslogic.media.Media.GetRootMedias()) + { + FixPathsForChildren(d, media => ((global::umbraco.cms.businesslogic.media.Media)media).Children); + } + AddReportLine("Fixing media recycle bin"); + var mediaRecycleBin = new RecycleBin(RecycleBin.RecycleBinType.Media); + foreach (var d in mediaRecycleBin.Children) + { + FixPathsForChildren(new global::umbraco.cms.businesslogic.media.Media(d.Id), media => ((global::umbraco.cms.businesslogic.media.Media)media).Children); + } + AddReportLine("Complete!"); + } + + /// + /// Returns true if this script has run based on a temp file written to + /// ~/App_Data/TEMP/FixPaths/report.txt + /// + /// + private bool HasBeenFixed() + { + return File.Exists(IOHelper.MapPath("~/App_Data/TEMP/FixPaths/report.txt")); + } + + /// + /// Creates the report + /// + private void WriteReport() + { + var filePath = IOHelper.MapPath("~/App_Data/TEMP/FixPaths/report.txt"); + Directory.CreateDirectory(Path.GetDirectoryName(filePath)); + using (var writer = File.CreateText(IOHelper.MapPath("~/App_Data/TEMP/FixPaths/report.txt"))) + { + writer.Write(_report.ToString()); + } + } + + /// + /// Recursively iterates over the children of the document and fixes the path + /// + /// + /// Callback to get the children of the conent item + /// + /// We cannot use GetDescendants() because that is based on the paths of documents and if they are invalid then + /// we cannot use that method. + /// + private void FixPathsForChildren(Content d, Func> getChildren) + { + AddReportLine("Fixing paths for children of " + d.Id); + foreach (var c in getChildren(d)) + { + FixPath(c); + if (c.HasChildren) + { + FixPathsForChildren(c, getChildren); + } + } + } + + /// + /// Check if the path is correct based on the document's parent if it is not correct, then fix it + /// + /// + private void FixPath(CMSNode d) + { + AddReportLine("Checking path for " + d.Id + ". Current = " + d.Path); + //check if the path is correct + var correctpath = d.Parent.Path + "," + d.Id.ToString(); + if (d.Path != correctpath) + { + AddReportLine(" INVALID PATH DETECTED. Path for " + d.Id + " changed to: " + d.Parent.Path + "," + d.Id.ToString()); + d.Path = correctpath; + d.Level = d.Parent.Level + 1; + } + } + + private void AddReportLine(string str) + { + _report.AppendLine(string.Format("{0} - " + str, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"))); + } + + + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Install/UpgradeScripts/IUpgradeScript.cs b/src/Umbraco.Web/Install/UpgradeScripts/IUpgradeScript.cs new file mode 100644 index 0000000000..339dbd4ac2 --- /dev/null +++ b/src/Umbraco.Web/Install/UpgradeScripts/IUpgradeScript.cs @@ -0,0 +1,7 @@ +namespace Umbraco.Web.Install.UpgradeScripts +{ + internal interface IUpgradeScript + { + void Execute(); + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptManager.cs b/src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptManager.cs new file mode 100644 index 0000000000..472415598d --- /dev/null +++ b/src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptManager.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core.Configuration; +using umbraco.DataLayer.Utility.Installer; + +namespace Umbraco.Web.Install.UpgradeScripts +{ + /// + /// Class used to register and execute upgrade scripts during install if they are required. + /// + internal static class UpgradeScriptManager + { + /// + /// Returns true if there are scripts to execute for the version + /// + /// + /// + public static bool HasScriptsForVersion(Version version) + { + return Scripts.Any(x => x.Item2.InRange(version)); + } + + /// + /// Executes all of the scripts for a database version + /// + /// + /// + public static void ExecuteScriptsForVersion(Version version) + { + var types = Scripts.Where(x => x.Item2.InRange(version)).Select(x => x.Item1); + foreach (var instance in types.Select(x => x())) + { + instance.Execute(); + } + } + + public static void AddUpgradeScript(Func script, VersionRange version) + { + Scripts.Add(new Tuple, VersionRange>(script, version)); + } + + ///// + ///// Adds a script to execute for a database version + ///// + ///// + ///// + //public static void AddUpgradeScript(string assemblyQualifiedTypeName, VersionRange version) + //{ + // AddUpgradeScript(new Lazy(() => Type.GetType(assemblyQualifiedTypeName)), version); + //} + + ///// + ///// Adds a script to execute for a database version + ///// + ///// + ///// + //public static void AddUpgradeScript(VersionRange version) + //{ + // AddUpgradeScript(new Lazy(() => typeof(T)), version); + //} + + /// + /// Used for testing + /// + internal static void Clear() + { + Scripts.Clear(); + } + + ///// + ///// Adds a script to execute for a database version + ///// + ///// + ///// + //public static void AddUpgradeScript(Lazy type, VersionRange version) + //{ + // Scripts.Add(new Tuple, VersionRange>(type, version)); + //} + + private static readonly List, VersionRange>> Scripts = new List, VersionRange>>(); + //private static readonly List, VersionRange>> Scripts = new List, VersionRange>>(); + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptRegistrar.cs b/src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptRegistrar.cs new file mode 100644 index 0000000000..611703b7d8 --- /dev/null +++ b/src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptRegistrar.cs @@ -0,0 +1,28 @@ +using System; +using Umbraco.Core; + +namespace Umbraco.Web.Install.UpgradeScripts +{ + internal class UpgradeScriptRegistrar : IApplicationEventHandler + { + public void OnApplicationInitialized(UmbracoApplication httpApplication, ApplicationContext applicationContext) + { + //Add contnet path fixup for any version from 4.10 up to 4.11.4 + UpgradeScriptManager.AddUpgradeScript( + () => new ContentPathFix(), + new VersionRange( + new Version(4, 10), + new Version(4, 11, 4))); + } + + public void OnApplicationStarting(UmbracoApplication httpApplication, ApplicationContext applicationContext) + { + + } + + public void OnApplicationStarted(UmbracoApplication httpApplication, ApplicationContext applicationContext) + { + + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Install/UpgradeScripts/VersionRange.cs b/src/Umbraco.Web/Install/UpgradeScripts/VersionRange.cs new file mode 100644 index 0000000000..adafd7691a --- /dev/null +++ b/src/Umbraco.Web/Install/UpgradeScripts/VersionRange.cs @@ -0,0 +1,40 @@ +using System; + +namespace Umbraco.Web.Install.UpgradeScripts +{ + internal class VersionRange + { + private readonly Version _specificVersion; + private readonly Version _startVersion; + private readonly Version _endVersion; + + public VersionRange(Version specificVersion) + { + _specificVersion = specificVersion; + } + + public VersionRange(Version startVersion, Version endVersion) + { + _startVersion = startVersion; + _endVersion = endVersion; + } + + /// + /// Checks if the versionCheck is in the range (in between) the start and end version + /// + /// + /// + /// + /// For example if our version range is 4.10 -> 4.11.4, we want to return true if the version being checked is: + /// greater than or equal to the start version but less than the end version. + /// + public bool InRange(Version versionCheck) + { + //if it is a specific version + if (_specificVersion != null) + return versionCheck == _specificVersion; + + return versionCheck >= _startVersion && versionCheck < _endVersion; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Properties/AssemblyInfo.cs b/src/Umbraco.Web/Properties/AssemblyInfo.cs index aa897d6340..03623505f9 100644 --- a/src/Umbraco.Web/Properties/AssemblyInfo.cs +++ b/src/Umbraco.Web/Properties/AssemblyInfo.cs @@ -30,3 +30,4 @@ using System.Security; [assembly: InternalsVisibleTo("Umbraco.Tests")] [assembly: InternalsVisibleTo("umbraco.MacroEngines")] [assembly: InternalsVisibleTo("umbraco.webservices")] +[assembly: InternalsVisibleTo("Umbraco.Web.UI")] diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index c7e6b7336b..5c7a263b12 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -252,6 +252,11 @@ + + + + + @@ -329,6 +334,7 @@ ASPXCodeBehind + ASPXCodeBehind @@ -1894,7 +1900,9 @@ ASPXCodeBehind - + + ASPXCodeBehind + diff --git a/src/Umbraco.Web/WebBootManager.cs b/src/Umbraco.Web/WebBootManager.cs index b4aed9339d..915144efcf 100644 --- a/src/Umbraco.Web/WebBootManager.cs +++ b/src/Umbraco.Web/WebBootManager.cs @@ -9,6 +9,7 @@ using Umbraco.Core.Dictionary; using Umbraco.Core.Dynamics; using Umbraco.Core.PropertyEditors; using Umbraco.Web.Dictionary; +using Umbraco.Web.Install.UpgradeScripts; using Umbraco.Web.Media; using Umbraco.Web.Media.ThumbnailProviders; using Umbraco.Web.Models; @@ -90,6 +91,7 @@ namespace Umbraco.Web //add the internal types since we don't want to mark these public ApplicationEventsResolver.Current.AddType(); ApplicationEventsResolver.Current.AddType(); + ApplicationEventsResolver.Current.AddType(); //now we need to call the initialize methods ApplicationEventsResolver.Current.ApplicationEventHandlers diff --git a/src/Umbraco.Web/umbraco.presentation/install/default.aspx.cs b/src/Umbraco.Web/umbraco.presentation/install/default.aspx.cs index 1bd81f7df3..16ceb1195f 100644 --- a/src/Umbraco.Web/umbraco.presentation/install/default.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/install/default.aspx.cs @@ -9,7 +9,7 @@ using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.HtmlControls; using System.Collections.Specialized; -using umbraco.IO; +using Umbraco.Core.IO; using umbraco.cms.businesslogic.installer; using System.Collections.Generic; @@ -36,7 +36,7 @@ namespace umbraco.presentation.install private void loadContent(InstallerStep currentStep) { PlaceHolderStep.Controls.Clear(); - PlaceHolderStep.Controls.Add(new System.Web.UI.UserControl().LoadControl(IOHelper.ResolveUrl(currentStep.UserControl))); + PlaceHolderStep.Controls.Add(LoadControl(IOHelper.ResolveUrl(currentStep.UserControl))); step.Value = currentStep.Alias; currentStepClass = currentStep.Alias; } @@ -136,6 +136,7 @@ namespace umbraco.presentation.install ics.Add(new install.steps.Definitions.Welcome()); ics.Add(new install.steps.Definitions.License()); ics.Add(new install.steps.Definitions.FilePermissions()); + ics.Add(new install.steps.Definitions.UpgradeScripts()); ics.Add(new install.steps.Definitions.Database()); ics.Add(new install.steps.Definitions.DefaultUser()); ics.Add(new install.steps.Definitions.Skinning()); diff --git a/src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/Database.cs b/src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/Database.cs index 9293d0e84b..9c3cadd748 100644 --- a/src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/Database.cs +++ b/src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/Database.cs @@ -1,9 +1,9 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Web; +using Umbraco.Core.IO; using umbraco.cms.businesslogic.installer; -using umbraco.IO; + using umbraco.DataLayer.Utility.Installer; using umbraco.DataLayer; @@ -18,7 +18,7 @@ namespace umbraco.presentation.install.steps.Definitions public override string Name { - get { return "Database"; } + get { return "Database"; } } public override string UserControl @@ -26,7 +26,7 @@ namespace umbraco.presentation.install.steps.Definitions get { return SystemDirectories.Install + "/steps/database.ascx"; } } - + public override bool MoveToNextStepAutomaticly { get @@ -38,13 +38,14 @@ namespace umbraco.presentation.install.steps.Definitions //here we determine if the installer should skip this step... public override bool Completed() { - bool retval = false; + bool retval; try { - IInstallerUtility m_Installer = BusinessLogic.Application.SqlHelper.Utility.CreateInstaller(); - retval = m_Installer.IsLatestVersion; - m_Installer = null; - } catch { + var installer = BusinessLogic.Application.SqlHelper.Utility.CreateInstaller(); + retval = installer.IsLatestVersion; + } + catch + { // this step might fail due to missing connectionstring return false; } @@ -52,6 +53,6 @@ namespace umbraco.presentation.install.steps.Definitions return retval; } - + } } \ No newline at end of file diff --git a/src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/FilePermissions.cs b/src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/FilePermissions.cs index ef3827225f..f0f6887ed3 100644 --- a/src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/FilePermissions.cs +++ b/src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/FilePermissions.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Web; +using Umbraco.Core.IO; using umbraco.cms.businesslogic.installer; namespace umbraco.presentation.install.steps.Definitions @@ -20,7 +21,7 @@ namespace umbraco.presentation.install.steps.Definitions public override string UserControl { - get { return IO.SystemDirectories.Install + "/steps/validatepermissions.ascx"; } + get { return SystemDirectories.Install + "/steps/validatepermissions.ascx"; } } public override bool HideFromNavigation { diff --git a/src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/UpgradeScripts.cs b/src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/UpgradeScripts.cs new file mode 100644 index 0000000000..57d4cf9d9b --- /dev/null +++ b/src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/UpgradeScripts.cs @@ -0,0 +1,78 @@ +using System; +using Umbraco.Core; +using Umbraco.Core.IO; +using Umbraco.Web.Install.UpgradeScripts; +using umbraco.DataLayer.Utility.Installer; +using umbraco.cms.businesslogic.installer; + +namespace umbraco.presentation.install.steps.Definitions +{ + internal class UpgradeScripts : InstallerStep + { + + + + public override string Alias + { + get { return "upgradeScripts"; } + } + + public override bool HideFromNavigation + { + get { return true; } + } + + /// + /// If there are no scripts for this version the skip + /// + /// + public override bool Completed() + { + var canConnect = CanConnectToDb(); + //if we cannot connect to the db, then we cannot run the script and most likely the database doesn't exist yet anyways. + if (!canConnect) return true; //skip + + //if the version is empty then it's probably a new installation, we cannot run scripts + if (GlobalSettings.CurrentVersion.IsNullOrWhiteSpace()) return true; //skip + var currentUmbVersion = Umbraco.Core.Configuration.GlobalSettings.GetConfigurationVersion(); + if (currentUmbVersion == null) + return true; //skip, could not get a version + + //check if we have upgrade script to run for this version + var hasScripts = UpgradeScriptManager.HasScriptsForVersion(currentUmbVersion); + return !hasScripts; + } + + public override string Name + { + get { return "Upgrade scripts"; } + } + + public override string UserControl + { + get { return SystemDirectories.Install + "/steps/UpgradeScripts.ascx"; } + } + + public override bool MoveToNextStepAutomaticly + { + get + { + return true; + } + } + + private bool CanConnectToDb() + { + try + { + var installer = BusinessLogic.Application.SqlHelper.Utility.CreateInstaller(); + var latest = installer.IsLatestVersion; + return true; //if we got this far, we can connect. + } + catch + { + return false; + } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/umbraco.presentation/install/utills/p.aspx.cs b/src/Umbraco.Web/umbraco.presentation/install/utills/p.aspx.cs index 67fb8c6d78..8576f12366 100644 --- a/src/Umbraco.Web/umbraco.presentation/install/utills/p.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/install/utills/p.aspx.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; +using Umbraco.Web.Install.UpgradeScripts; using umbraco.DataLayer.Utility.Installer; using umbraco.DataLayer; @@ -97,6 +98,8 @@ namespace umbraco.presentation.install.utills Helper.setProgress(100, "Database is up-to-date", ""); + return "upgraded"; + } else { @@ -136,6 +139,7 @@ namespace umbraco.presentation.install.utills installer = null; library.RefreshContent(); + return "upgraded"; } } @@ -146,5 +150,8 @@ namespace umbraco.presentation.install.utills return "no connection;"; } + + + } } \ No newline at end of file diff --git a/src/umbraco.datalayer/Utility/Installer/DefaultInstallerUtility.cs b/src/umbraco.datalayer/Utility/Installer/DefaultInstallerUtility.cs index 16c51bae78..b88f7ac157 100644 --- a/src/umbraco.datalayer/Utility/Installer/DefaultInstallerUtility.cs +++ b/src/umbraco.datalayer/Utility/Installer/DefaultInstallerUtility.cs @@ -261,45 +261,5 @@ namespace umbraco.DataLayer.Utility.Installer #endregion } - /// - /// A triple (Field, Table, Version) meaning: - /// if a SELECT statement of Field FROM Table succeeds, - /// the database version is at least Version. - /// - /// - /// This also supports checking for a value in a table. - /// - public struct VersionSpecs - { - /// The SQL statament to execute in order to test for the specified version - public readonly string Sql; - - /// An integer identifying the expected row count from the Sql statement - public readonly int ExpectedRows; - - /// The minimum version number of a database that contains the specified field. - public readonly DatabaseVersion Version; - - /// - /// Initializes a new instance of the struct. - /// - /// The sql statement to execute. - /// The version. - public VersionSpecs(string sql, DatabaseVersion version) - : this(sql, -1, version) - { } - - /// - /// Initializes a new instance of the struct. - /// - /// The sql statement to execute. - /// The expected row count. - /// The version. - public VersionSpecs(string sql, int expectedRows, DatabaseVersion version) - { - Sql = sql; - ExpectedRows = expectedRows; - Version = version; - } - } + } diff --git a/src/umbraco.datalayer/Utility/Installer/VersionSpecs.cs b/src/umbraco.datalayer/Utility/Installer/VersionSpecs.cs new file mode 100644 index 0000000000..c1237e1e97 --- /dev/null +++ b/src/umbraco.datalayer/Utility/Installer/VersionSpecs.cs @@ -0,0 +1,44 @@ +namespace umbraco.DataLayer.Utility.Installer +{ + /// + /// A triple (Field, Table, Version) meaning: + /// if a SELECT statement of Field FROM Table succeeds, + /// the database version is at least Version. + /// + /// + /// This also supports checking for a value in a table. + /// + public struct VersionSpecs + { + /// The SQL statament to execute in order to test for the specified version + public readonly string Sql; + + /// An integer identifying the expected row count from the Sql statement + public readonly int ExpectedRows; + + /// The minimum version number of a database that contains the specified field. + public readonly DatabaseVersion Version; + + /// + /// Initializes a new instance of the struct. + /// + /// The sql statement to execute. + /// The version. + public VersionSpecs(string sql, DatabaseVersion version) + : this(sql, -1, version) + { } + + /// + /// Initializes a new instance of the struct. + /// + /// The sql statement to execute. + /// The expected row count. + /// The version. + public VersionSpecs(string sql, int expectedRows, DatabaseVersion version) + { + Sql = sql; + ExpectedRows = expectedRows; + Version = version; + } + } +} \ No newline at end of file diff --git a/src/umbraco.datalayer/umbraco.datalayer.csproj b/src/umbraco.datalayer/umbraco.datalayer.csproj index 73d169333e..6297b07bc4 100644 --- a/src/umbraco.datalayer/umbraco.datalayer.csproj +++ b/src/umbraco.datalayer/umbraco.datalayer.csproj @@ -117,6 +117,7 @@ + From 61f2647b6222d165317038f861f0b8e7356d3dc8 Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Thu, 31 Jan 2013 04:26:47 +0600 Subject: [PATCH 25/43] missing file --- .../install/steps/UpgradeScripts.ascx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx diff --git a/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx b/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx new file mode 100644 index 0000000000..2728a12f66 --- /dev/null +++ b/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx @@ -0,0 +1,14 @@ +<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="UpgradeScripts.ascx.cs" Inherits="Umbraco.Web.UI.Install.Steps.UpgradeScripts" %> +
+
+

Upgrade scripts

+

+ We need to run a few upgrade scripts, press Continue to execute these scripts and continue to the next step. +

+
+ +
+
 
+ Continue +
+
\ No newline at end of file From fbc10be3815f2e9d775bda25ef189d795343f2d1 Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Thu, 31 Jan 2013 04:46:51 +0600 Subject: [PATCH 26/43] Reverted logic of Document to be what it used to be... Published and HasPublishedVersion() are the same and will return the same thing, though we've kept the lazy loading and optimizations. --- .../Install/UpgradeScriptsTests.cs | 6 +- src/umbraco.cms/businesslogic/web/Document.cs | 59 +++++++++++-------- 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/src/Umbraco.Tests/Install/UpgradeScriptsTests.cs b/src/Umbraco.Tests/Install/UpgradeScriptsTests.cs index 04a3f81dfb..daf95b2241 100644 --- a/src/Umbraco.Tests/Install/UpgradeScriptsTests.cs +++ b/src/Umbraco.Tests/Install/UpgradeScriptsTests.cs @@ -32,7 +32,8 @@ namespace Umbraco.Tests.Install var startVersionParts = startVersion.Split('.').Select(int.Parse).ToArray(); var endVersionParts = endVersion.Split('.').Select(int.Parse).ToArray(); - UpgradeScriptManager.AddUpgradeScript( + UpgradeScriptManager.AddUpgradeScript( + () => new UpgradeScript1(), new VersionRange( new Version(startVersionParts[0], startVersionParts[1], startVersionParts[2]), new Version(endVersionParts[0], endVersionParts[1], endVersionParts[2]))); @@ -45,7 +46,8 @@ namespace Umbraco.Tests.Install { var currentVersion = new Version(4, 10, 0); - UpgradeScriptManager.AddUpgradeScript( + UpgradeScriptManager.AddUpgradeScript( + () => new UpgradeScript1(), new VersionRange( new Version(4, 10, 0))); diff --git a/src/umbraco.cms/businesslogic/web/Document.cs b/src/umbraco.cms/businesslogic/web/Document.cs index b4ebcf3ca6..5d79309f4a 100644 --- a/src/umbraco.cms/businesslogic/web/Document.cs +++ b/src/umbraco.cms/businesslogic/web/Document.cs @@ -227,9 +227,9 @@ order by {1} private int _template; /// - /// a backing property for the 'Published' property + /// a backing property for the 'IsDocumentLive()' method /// - private bool? _published; + private bool? _isDocumentLive; /// /// a backing property for the 'HasPublishedVersion()' method @@ -808,29 +808,39 @@ order by {1} { get { - if (!_published.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) + //this is always the same as HasPublishedVersion in 4.x + return HasPublishedVersion(); + } + set + { + _hasPublishedVersion = value; + SqlHelper.ExecuteNonQuery( + string.Format("update cmsDocument set published = {0} where nodeId = {1}", Id, value ? 1 : 0)); + } + } + + /// + /// Will return true if the document is published and live on the front-end. + /// + /// + internal bool IsDocumentLive() + { + if (!_isDocumentLive.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", "',%'") + @") or ('" + Path + @"' = node.path)) and node.id <> -1 and node.nodeObjectType=@nodeObjectType"; - var count = SqlHelper.ExecuteScalar(sql, SqlHelper.CreateParameter("@nodeObjectType", Document._objectType)); - _published = (count == 0); - } - return _published.Value; - } - set - { - _published = value; - SqlHelper.ExecuteNonQuery( - string.Format("update cmsDocument set published = {0} where nodeId = {1}", Id, value ? 1 : 0)); + var count = SqlHelper.ExecuteScalar(sql, SqlHelper.CreateParameter("@nodeObjectType", Document._objectType)); + _isDocumentLive = (count == 0); } + return _isDocumentLive.Value; } /// @@ -1093,7 +1103,7 @@ and node.nodeObjectType=@nodeObjectType"; _template = new DocumentType(this.ContentType.Id).DefaultTemplate; } - _published = true; + _hasPublishedVersion = true; string tempVersion = Version.ToString(); DateTime versionDate = DateTime.Now; Guid newVersion = createNewVersion(versionDate); @@ -1231,7 +1241,7 @@ and node.nodeObjectType=@nodeObjectType"; if (!e.Cancel) { - _published = true; + _hasPublishedVersion = true; string tempVersion = Version.ToString(); DateTime versionDate = DateTime.Now; Guid newVersion = createNewVersion(versionDate); @@ -1259,7 +1269,7 @@ and node.nodeObjectType=@nodeObjectType"; public void UnPublish() { - UnPublishEventArgs e = new UnPublishEventArgs(); + var e = new UnPublishEventArgs(); FireBeforeUnPublish(e); @@ -1267,7 +1277,7 @@ and node.nodeObjectType=@nodeObjectType"; { SqlHelper.ExecuteNonQuery(string.Format("update cmsDocument set published = 0 where nodeId = {0}", Id)); - _published = false; + _hasPublishedVersion = false; FireAfterUnPublish(e); } @@ -1278,7 +1288,7 @@ and node.nodeObjectType=@nodeObjectType"; /// public override void Save() { - SaveEventArgs e = new SaveEventArgs(); + var e = new SaveEventArgs(); FireBeforeSave(e); if (!e.Cancel) @@ -1314,6 +1324,7 @@ and node.nodeObjectType=@nodeObjectType"; /// public bool HasPublishedVersion() { + //lazy load the value if it is not set. if (!_hasPublishedVersion.HasValue) { var count = SqlHelper.ExecuteScalar(@" @@ -1841,7 +1852,7 @@ where published = 1 And nodeId = @nodeId And trashed = 0", SqlHelper.CreateParam _release = InitReleaseDate; _expire = InitExpireDate; _updated = InitUpdateDate; - _published = InitPublished; + _hasPublishedVersion = InitPublished; } /// From 99c880a4c91a4d33431670ffa26f158395a80ce1 Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Thu, 31 Jan 2013 07:27:13 -0100 Subject: [PATCH 27/43] Added additional logging to migration runner. --- src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs b/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs index 74721961dd..50ff46837f 100644 --- a/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs +++ b/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs @@ -61,10 +61,12 @@ namespace Umbraco.Core.Persistence.Migrations if (isUpgrade) { migration.GetUpExpressions(context); + LogHelper.Info(string.Format("Added UPGRADE migration '{0}' to context", migration.GetType().Name)); } else { migration.GetDownExpressions(context); + LogHelper.Info(string.Format("Added DOWNGRADE migration '{0}' to context", migration.GetType().Name)); } } From c72b6d7ae5498cfe1b09cf3601233c07640a6898 Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Thu, 31 Jan 2013 08:04:20 -0100 Subject: [PATCH 28/43] Minor Typo --- src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs b/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs index 50ff46837f..2eb5896374 100644 --- a/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs +++ b/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs @@ -43,7 +43,7 @@ namespace Umbraco.Core.Persistence.Migrations /// True if migrations were applied, otherwise False public bool Execute(Database database, DatabaseProviders databaseProvider, bool isUpgrade = true) { - LogHelper.Info("Initializing database migration"); + LogHelper.Info("Initializing database migrations"); var foundMigrations = MigrationResolver.Current.Migrations; From ca44094a37715371ee66ef0e6771f1e22bed5e9b Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 31 Jan 2013 08:23:58 -0100 Subject: [PATCH 29/43] Remove RC from the version number --- build/Build.bat | 2 +- src/Umbraco.Core/Configuration/UmbracoVersion.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/Build.bat b/build/Build.bat index fa786d3c85..51196d6527 100644 --- a/build/Build.bat +++ b/build/Build.bat @@ -1,6 +1,6 @@ @ECHO OFF SET release=6.0.0 -SET comment=RC +SET comment= SET version=%release% IF [%comment%] EQU [] (SET version=%release%) ELSE (SET version=%release%-%comment%) diff --git a/src/Umbraco.Core/Configuration/UmbracoVersion.cs b/src/Umbraco.Core/Configuration/UmbracoVersion.cs index 60bf0ee45a..8e7387ba2e 100644 --- a/src/Umbraco.Core/Configuration/UmbracoVersion.cs +++ b/src/Umbraco.Core/Configuration/UmbracoVersion.cs @@ -23,7 +23,7 @@ namespace Umbraco.Core.Configuration /// Gets the version comment (like beta or RC). /// /// The version comment. - public static string CurrentComment { get { return "RC"; } } + public static string CurrentComment { get { return ""; } } // Get the version of the umbraco.dll by looking at a class in that dll // Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx From 7e288f657b240c93192a8e6f032beb6cd5503c4f Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 31 Jan 2013 08:29:55 -0100 Subject: [PATCH 30/43] Pull in the latest translations --- src/Umbraco.Web.UI/umbraco/config/lang/ja.xml | 34 ++++++++++++++++--- src/Umbraco.Web.UI/umbraco/config/lang/zh.xml | 18 +++++----- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/ja.xml b/src/Umbraco.Web.UI/umbraco/config/lang/ja.xml index c41f2631a0..b5c96e1b58 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/ja.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/ja.xml @@ -1,4 +1,4 @@ - + umbraco @@ -15,8 +15,6 @@ 無効 ごみ箱を空にする ドキュメントタイプの書出 - .NETの書き出し - .NETの書き出し ドキュメントタイプの読込 パッケージの読み込み ライブ編集 @@ -25,6 +23,7 @@ メール通知 一般公開 公開 + 公開を止める 最新の情報に更新 サイトのリフレッシュ アクセス権 @@ -38,6 +37,7 @@ ドメインの割り当て + 適当でないホスト名 ドメイン ドメイン '%0%' が新たに割り当てられました ドメイン '%0%' は削除されました @@ -71,6 +71,7 @@ 保存及び公開 保存して承認に送る プレビュー + テンプレートが指定されていないのでプレビューは無効になっています スタイルの選択 スタイルの表示 表の挿入 @@ -90,6 +91,7 @@ このページは公開されていません 公開日時 メディアタイプ + メディアの項目へのリンク メンバーグループ 役割 メンバータイプ @@ -324,6 +326,7 @@ ようこそ... はい + フォルダー 背景色 @@ -482,6 +485,7 @@ Runwayをインストールして作られた新しいウェブサイトがど 現在のノードは、ドキュメントタイプの設定により選択されたノードの子になることはできません。 ノードは、自分のサブページには移動できません 子ドキュメントで権限がないので、その操作はできません。 + コピーしたものを元と関係づける %0% への通知を編集 @@ -586,8 +590,13 @@ Runwayをインストールして作られた新しいウェブサイトがど + + + 非公開の子ページも含めます 公開を進めています - 少々お待ちください... %1% ページ中 %0% ページが公開されました... @@ -648,6 +657,9 @@ Runwayをインストールして作られた新しいウェブサイトがど タブ タブの名前 タブ + マスターコンテンツタイプが有効 + このコンテンツタイプの使用 + マスターコンテンツタイプについては、マスターコンテンツタイプからのタブは表示されず、マスターコンテンツタイプでのみ編集することができます。 ソートが完了しました。 @@ -682,6 +694,7 @@ Runwayをインストールして作られた新しいウェブサイトがど テンプレートを保存しました ユーザーの保存時にエラーが発生しました (ログを確認してください) ユーザーを保存しました + ユーザータイプを保存しました ファイルは未保存です ファイルを保存できません。アクセス権を確認してください。 ファイルを保存しました @@ -700,6 +713,11 @@ Runwayをインストールして作られた新しいウェブサイトがど XSLTを保存できません。アクセス権を確認してください。 XSLTを保存しました XSLTにエラーはありません + コンテンツは公開されていません + 部分ビュー保存しました + 部分ビューをエラーなしで保存しました! + 部分ビューは保存されていません + ファイルを保存するときにエラーが発生しました。 CSSシンタックスを使用 例: h1, .redHeader, .blueTex @@ -727,6 +745,7 @@ Runwayをインストールして作られた新しいウェブサイトがど フィールドの選択 改行コードの変換 改行コードをhtmlタグ &lt;br&gt; に変換する + カスタムフィールド 日付のみ表示 日付の形式 HTMLエンコード @@ -740,6 +759,7 @@ Runwayをインストールして作られた新しいウェブサイトがど 再帰的 段落タグの消去 段落タグ &lt;P&gt; を消去します + 標準フィールド 大文字変換 URLエンコード 文字列をURLで使用可能な文字列に変換する @@ -833,6 +853,8 @@ Runwayをインストールして作られた新しいウェブサイトがど 管理者 フィールドのカテゴリー パスワードの変更 + 新パスワード + 新パスワードの確認 Umbracoの管理画面にアクセスするためのパスワードを変更するには、以下のフォームに新しいパスワード入力して「パスワードの変更」ボタンをクリックしてください。 コンテントチャンネル ログオン後ライブ編集にリダイレクト @@ -851,6 +873,8 @@ Runwayをインストールして作られた新しいウェブサイトがど 新しいパスワードの確認 新しいパスワードの入力 パスワードは空白にできません! + 現在のパスワード + 現在のパスワードが正しくない 新しいパスワードと確認のパスワードが一致しません。再度入力してください! 確認のパスワードは新しいパスワードと一致しません! 子ノードのアクセス権を置き換える @@ -864,4 +888,4 @@ Runwayをインストールして作られた新しいウェブサイトがど ユーザーの種類 投稿者 - \ No newline at end of file + diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/zh.xml b/src/Umbraco.Web.UI/umbraco/config/lang/zh.xml index 189c352d63..f46a3f340c 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/zh.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/zh.xml @@ -501,13 +501,13 @@

您好!这是一封自动发送的邮件,告诉您任务'%1%'已在'%2%'被用户'%3%'执行

-

Update summary:

+

更新概况:

%6%
@@ -515,14 +515,14 @@ -

Have a nice day!

- Cheers from the umbraco robot +

祝您愉快!

+ 该信息由系统自动发送

]]> 在 %2%,[%0%] 关于 %1% 的通告已执行。 From 7300686f3453bf6e1180fadeb062eff639e70372 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 31 Jan 2013 08:53:55 -0100 Subject: [PATCH 31/43] Update to WebPI parameters --- src/WebPi/parameters.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/WebPi/parameters.xml b/src/WebPi/parameters.xml index 8efe1e9506..ae1b4135e9 100644 --- a/src/WebPi/parameters.xml +++ b/src/WebPi/parameters.xml @@ -105,7 +105,9 @@ - + + From ac2c3ff32193564362a51360b89cee8d8b4c5230 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 31 Jan 2013 09:16:49 -0100 Subject: [PATCH 32/43] Move the install stats call down in the page so it doesn't block page load --- src/Umbraco.Web.UI/install/default.aspx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI/install/default.aspx b/src/Umbraco.Web.UI/install/default.aspx index 9e5f9056da..c929a3da16 100644 --- a/src/Umbraco.Web.UI/install/default.aspx +++ b/src/Umbraco.Web.UI/install/default.aspx @@ -40,11 +40,7 @@ - - - - - +
@@ -155,7 +151,12 @@ - + + + + + + From 8473601f034bbb1661f3e0e18d301f723b5f2e26 Mon Sep 17 00:00:00 2001 From: "NielsHartvig@UMBRACORATI.localdomain" Date: Thu, 31 Jan 2013 10:39:30 -0100 Subject: [PATCH 33/43] Fixes issue with db detection in install logger --- .../umbraco/webservices/CheckForUpgrade.asmx.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/CheckForUpgrade.asmx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/CheckForUpgrade.asmx.cs index 7c4e000047..f6aa1f337b 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/CheckForUpgrade.asmx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/CheckForUpgrade.asmx.cs @@ -61,6 +61,10 @@ namespace umbraco.presentation.webservices } installCookie.SetValue(installId.ToString()); + string dbProvider = String.Empty; + if (!String.IsNullOrEmpty(Umbraco.Core.Configuration.GlobalSettings.ConfigurationStatus)) + dbProvider = ApplicationContext.Current.DatabaseContext.DatabaseProvider.ToString(); + org.umbraco.update.CheckForUpgrade check = new global::umbraco.presentation.org.umbraco.update.CheckForUpgrade(); check.Install(installId, isUpgrade, @@ -72,7 +76,7 @@ namespace umbraco.presentation.webservices UmbracoVersion.CurrentComment, errorMsg, userAgent, - ApplicationContext.Current.DatabaseContext.DatabaseProvider.ToString()); + dbProvider); } } From db6da95421dd679cba54dea96afe2843f1f03760 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 31 Jan 2013 10:50:56 -0100 Subject: [PATCH 34/43] Move script back up, there was no need to move it down :) --- src/Umbraco.Web.UI/install/default.aspx | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI/install/default.aspx b/src/Umbraco.Web.UI/install/default.aspx index c929a3da16..9e5f9056da 100644 --- a/src/Umbraco.Web.UI/install/default.aspx +++ b/src/Umbraco.Web.UI/install/default.aspx @@ -40,7 +40,11 @@
- + + + + +
@@ -151,12 +155,7 @@ - - - - - - + From 1249761ecdad1d69c5b70057a1b712ddd1574fa3 Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Thu, 31 Jan 2013 11:22:15 -0100 Subject: [PATCH 35/43] Fixes U4-1610 --- src/Umbraco.Core/Services/ContentService.cs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index 21a064581e..4b8beb1de4 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -1316,7 +1316,15 @@ namespace Umbraco.Core.Services uow.Database.ExecuteScalar("SELECT COUNT(nodeId) FROM cmsPreviewXml WHERE nodeId = @Id AND versionId = @Version", new {Id = content.Id, Version = content.Version}) != 0; int previewResult = previewExists - ? uow.Database.Update(previewPoco) + ? uow.Database.Update( + "SET xml = @Xml, timestamp = @Timestamp WHERE nodeId = @Id AND versionId = @Version", + new + { + Xml = previewPoco.Xml, + Timestamp = previewPoco.Timestamp, + Id = previewPoco.NodeId, + Version = previewPoco.VersionId + }) : Convert.ToInt32(uow.Database.Insert(previewPoco)); } @@ -1382,7 +1390,15 @@ namespace Umbraco.Core.Services uow.Database.ExecuteScalar("SELECT COUNT(nodeId) FROM cmsPreviewXml WHERE nodeId = @Id AND versionId = @Version", new { Id = content.Id, Version = content.Version }) != 0; int previewResult = previewExists - ? uow.Database.Update(previewPoco) + ? uow.Database.Update( + "SET xml = @Xml, timestamp = @Timestamp WHERE nodeId = @Id AND versionId = @Version", + new + { + Xml = previewPoco.Xml, + Timestamp = previewPoco.Timestamp, + Id = previewPoco.NodeId, + Version = previewPoco.VersionId + }) : Convert.ToInt32(uow.Database.Insert(previewPoco)); } From f18c557fb4519ae15d651d549c51ced59c944d27 Mon Sep 17 00:00:00 2001 From: Morten Christensen Date: Thu, 31 Jan 2013 11:22:54 -0100 Subject: [PATCH 36/43] Fixes bug related to U4-1460 - template was incorrectly updated when sorting nodes. --- .../Repositories/ContentRepository.cs | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs index b284a4550a..660589dbbe 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs @@ -42,6 +42,7 @@ namespace Umbraco.Core.Persistence.Repositories { var sql = GetBaseQuery(false) .Where(GetBaseWhereClause(), new { Id = id }) + .Where(x => x.Newest) .OrderByDescending(x => x.VersionDate); var dto = Database.Fetch(sql).FirstOrDefault(); @@ -49,21 +50,8 @@ namespace Umbraco.Core.Persistence.Repositories if (dto == null) return null; - //Get the ContentType that this Content is based on - var contentType = _contentTypeRepository.Get(dto.ContentVersionDto.ContentDto.ContentTypeId); + var content = CreateContentFromDto(dto, dto.ContentVersionDto.VersionId); - var factory = new ContentFactory(contentType, NodeObjectTypeId, id); - var content = factory.BuildEntity(dto); - - //Check if template id is set on DocumentDto, and get ITemplate if it is. - if (dto.TemplateId.HasValue && dto.TemplateId.Value > 0) - { - content.Template = _templateRepository.Get(dto.TemplateId.Value); - } - - content.Properties = GetPropertyCollection(id, dto.ContentVersionDto.VersionId, contentType); - - ((ICanBeDirty)content).ResetDirtyProperties(); return content; } @@ -167,15 +155,9 @@ namespace Umbraco.Core.Persistence.Repositories if (dto == null) return null; + + var content = CreateContentFromDto(dto, versionId); - var contentType = _contentTypeRepository.Get(dto.ContentVersionDto.ContentDto.ContentTypeId); - - var factory = new ContentFactory(contentType, NodeObjectTypeId, dto.NodeId); - var content = factory.BuildEntity(dto); - - content.Properties = GetPropertyCollection(dto.NodeId, versionId, contentType); - - ((ICanBeDirty)content).ResetDirtyProperties(); return content; } @@ -430,6 +412,31 @@ namespace Umbraco.Core.Persistence.Repositories #endregion + /// + /// Private method to create a content object from a DocumentDto, which is used by Get and GetByVersion. + /// + /// + /// + /// + private IContent CreateContentFromDto(DocumentDto dto, Guid versionId) + { + var contentType = _contentTypeRepository.Get(dto.ContentVersionDto.ContentDto.ContentTypeId); + + var factory = new ContentFactory(contentType, NodeObjectTypeId, dto.NodeId); + var content = factory.BuildEntity(dto); + + //Check if template id is set on DocumentDto, and get ITemplate if it is. + if (dto.TemplateId.HasValue && dto.TemplateId.Value > 0) + { + content.Template = _templateRepository.Get(dto.TemplateId.Value); + } + + content.Properties = GetPropertyCollection(dto.NodeId, versionId, contentType); + + ((ICanBeDirty)content).ResetDirtyProperties(); + return content; + } + private PropertyCollection GetPropertyCollection(int id, Guid versionId, IContentType contentType) { var sql = new Sql(); From aaaace8dd3da4691360b9d48ed4e0bd084db1b48 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 31 Jan 2013 11:32:05 -0100 Subject: [PATCH 37/43] Added tag Release-6.0.0 for changeset 1719fbd857f2 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 6a3fe90af2..e6189102f5 100644 --- a/.hgtags +++ b/.hgtags @@ -24,3 +24,4 @@ f6da531fbb4c251ff61d314e2a7effb13c71e74a Release-4.10.0 54cde33b809dcb3a1f7e7ae0d5375f6dd0d89c8d Release-4.11.2.2 ff3bb24ea0c915878396a6ae27f1ff164e8ac150 Release-6.0.0-beta 56015ac26f5ab60e3c61b1d09075297b660afa07 Release-6.0.0-RC +1719fbd857f28b376639ac2aa0abada0ef2e7560 Release-6.0.0 From aa092ab3f3332e597d08d45cfc4f455ba56ba0bf Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 31 Jan 2013 11:41:34 -0100 Subject: [PATCH 38/43] Closing 6.0.0 From 6e0af6827ec8fd735089912652e912faa1216c63 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 31 Jan 2013 14:35:18 -0100 Subject: [PATCH 39/43] Fix weird merge issues --- .../InfrastructureSettings/Infrastructure.cs | 190 ++++++ .../Persistence/DatabaseFactory.cs | 34 ++ .../Persistence/Mappers/ModelDtoMapper.cs | 86 +++ .../Persistence/Querying/ExpressionHelper.cs | 572 ++++++++++++++++++ .../Configurations/RepositorySettingsTests.cs | 32 + .../Persistence/DatabaseFactoryTests.cs | 18 + .../Repositories/ContentRepositoryTest.cs | 2 +- .../Repositories/RelationRepositoryTest.cs | 2 +- 8 files changed, 934 insertions(+), 2 deletions(-) create mode 100644 src/Umbraco.Core/Configuration/InfrastructureSettings/Infrastructure.cs create mode 100644 src/Umbraco.Core/Persistence/DatabaseFactory.cs create mode 100644 src/Umbraco.Core/Persistence/Mappers/ModelDtoMapper.cs create mode 100644 src/Umbraco.Core/Persistence/Querying/ExpressionHelper.cs create mode 100644 src/Umbraco.Tests/Configurations/RepositorySettingsTests.cs create mode 100644 src/Umbraco.Tests/Persistence/DatabaseFactoryTests.cs diff --git a/src/Umbraco.Core/Configuration/InfrastructureSettings/Infrastructure.cs b/src/Umbraco.Core/Configuration/InfrastructureSettings/Infrastructure.cs new file mode 100644 index 0000000000..8a8f4454bc --- /dev/null +++ b/src/Umbraco.Core/Configuration/InfrastructureSettings/Infrastructure.cs @@ -0,0 +1,190 @@ +using System.Configuration; + +namespace Umbraco.Core.Configuration.InfrastructureSettings +{ + public class Infrastructure : ConfigurationSection + { + private const string InfrastructureSectionName = "umbraco/infrastructure"; + + public static Infrastructure Instance + { + get { return (Infrastructure) ConfigurationManager.GetSection(InfrastructureSectionName); } + } + + #region RepositoriesSection Property + + internal const string RepositoriesPropertyName = "repositories"; + + [ConfigurationProperty(RepositoriesPropertyName, IsRequired = true, IsKey = false, IsDefaultCollection = false)] + public Repositories Repositories + { + get { return ((Repositories)base[RepositoriesPropertyName]); } + set { base[RepositoriesPropertyName] = value; } + } + + #endregion + + #region PublishingStrategy Property + + internal const string PublishingStrategyPropertyName = "publishingStrategy"; + + [ConfigurationProperty(PublishingStrategyPropertyName, IsRequired = true, IsKey = false, IsDefaultCollection = false)] + public PublishingProvider PublishingStrategy + { + get { return ((PublishingProvider)base[PublishingStrategyPropertyName]); } + set { base[PublishingStrategyPropertyName] = value; } + } + + #endregion + } + + public class Repositories : ConfigurationElement + { + [ConfigurationProperty("", IsDefaultCollection = true, IsRequired = true)] + public RepositoryElementCollection Repository + { + get { return ((RepositoryElementCollection)(base[""])); } + } + } + + [ConfigurationCollection(typeof(Repository), CollectionType = ConfigurationElementCollectionType.BasicMapAlternate, AddItemName = RepositoryPropertyName)] + public class RepositoryElementCollection : ConfigurationElementCollection + { + internal const string RepositoryPropertyName = "repository"; + + public override ConfigurationElementCollectionType CollectionType + { + get + { + return ConfigurationElementCollectionType.BasicMapAlternate; + } + } + + protected override string ElementName + { + get + { + return RepositoryPropertyName; + } + } + + protected override bool IsElementName(string elementName) + { + return elementName == RepositoryPropertyName; + } + + protected override object GetElementKey(ConfigurationElement element) + { + return ((Repository)element).InterfaceShortTypeName; + } + + protected override ConfigurationElement CreateNewElement() + { + return new Repository(); + } + + #region Indexer + + public Repository this[int index] + { + get { return (Repository)base.BaseGet(index); } + } + + public Repository this[string interfaceShortTypeName] + { + get { return (Repository)base.BaseGet(interfaceShortTypeName); } + } + + #endregion + + #region Add + + public void Add(Repository repository) + { + BaseAdd(repository); + } + + #endregion + + #region Remove + + public void Remove(Repository repository) + { + BaseRemove(repository); + } + + #endregion + + #region GetItem + + public Repository GetItemAt(int index) + { + return (Repository)BaseGet(index); + } + + public Repository GetItemByKey(string interfaceShortTypeName) + { + return (Repository)BaseGet(interfaceShortTypeName); + } + + #endregion + + public bool ContainsKey(string interfaceShortName) + { + bool result = false; + object[] keys = this.BaseGetAllKeys(); + foreach (object key in keys) + { + if ((string)key == interfaceShortName) + { + result = true; + break; + + } + } + return result; + } + } + + public class Repository : ConfigurationElement + { + internal const string InterfaceShortTypeNamePropertyName = "interfaceShortTypeName"; + + [ConfigurationPropertyAttribute(InterfaceShortTypeNamePropertyName, IsRequired = true, IsKey = true, IsDefaultCollection = false)] + public string InterfaceShortTypeName + { + get { return (string) base[InterfaceShortTypeNamePropertyName]; } + set { base[InterfaceShortTypeNamePropertyName] = value; } + } + + internal const string RepositoryFullTypeNamePropertyName = "repositoryFullTypeName"; + + [ConfigurationPropertyAttribute(RepositoryFullTypeNamePropertyName, IsRequired = true, IsKey = false, IsDefaultCollection = false)] + public string RepositoryFullTypeName + { + get { return (string)base[RepositoryFullTypeNamePropertyName]; } + set { base[RepositoryFullTypeNamePropertyName] = value; } + } + + internal const string CacheProviderFullTypeNamePropertyName = "cacheProviderFullTypeName"; + + [ConfigurationPropertyAttribute(CacheProviderFullTypeNamePropertyName, IsRequired = true, IsKey = false, IsDefaultCollection = false)] + public string CacheProviderFullTypeName + { + get { return (string)base[CacheProviderFullTypeNamePropertyName]; } + set { base[CacheProviderFullTypeNamePropertyName] = value; } + } + } + + public class PublishingProvider : ConfigurationElement + { + internal const string TypePropertyName = "type"; + + [ConfigurationPropertyAttribute(TypePropertyName, IsRequired = true, IsKey = false, IsDefaultCollection = false)] + public string Type + { + get { return (string)base[TypePropertyName]; } + set { base[TypePropertyName] = value; } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/DatabaseFactory.cs b/src/Umbraco.Core/Persistence/DatabaseFactory.cs new file mode 100644 index 0000000000..6ce5bd6ac4 --- /dev/null +++ b/src/Umbraco.Core/Persistence/DatabaseFactory.cs @@ -0,0 +1,34 @@ +using System; +using System.Threading; +using Umbraco.Core.Configuration; + +namespace Umbraco.Core.Persistence +{ + /// + /// Provides access to the PetaPoco database as Singleton, so the database is created once in app lifecycle. + /// This is necessary for transactions to work properly + /// + public sealed class DatabaseFactory + { + #region Singleton + + private static readonly Database _database = new Database(GlobalSettings.DbDsn); + private static readonly Lazy lazy = new Lazy(() => new DatabaseFactory()); + + public static DatabaseFactory Current { get { return lazy.Value; } } + + private DatabaseFactory() + { + } + + #endregion + + /// + /// Returns an instance of the PetaPoco database + /// + public Database Database + { + get { return _database; } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Mappers/ModelDtoMapper.cs b/src/Umbraco.Core/Persistence/Mappers/ModelDtoMapper.cs new file mode 100644 index 0000000000..6f43b8e304 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Mappers/ModelDtoMapper.cs @@ -0,0 +1,86 @@ +using System; +using System.Reflection; +using Umbraco.Core.Models; + +namespace Umbraco.Core.Persistence.Mappers +{ + internal class ModelDtoMapper : IMapper + { + public void GetTableInfo(Type t, TableInfo ti) + { } + + public bool MapPropertyToColumn(PropertyInfo pi, ref string columnName, ref bool resultColumn) + { + if (pi.DeclaringType == typeof(Content) || pi.DeclaringType == typeof(IContent)) + { + switch (pi.Name) + { + case "Trashed": + columnName = "[umbracoNode].[trashed]"; + return true; + case "ParentId": + columnName = "[umbracoNode].[parentID]"; + return true; + case "UserId": + columnName = "[umbracoNode].[nodeUser]"; + return true; + case "Level": + columnName = "[umbracoNode].[level]"; + return true; + case "Path": + columnName = "[umbracoNode].[path]"; + return true; + case "SortOrder": + columnName = "[umbracoNode].[sortOrder]"; + return true; + case "NodeId": + columnName = "[umbracoNode].[id]"; + return true; + case "Published": + columnName = "[cmsDocument].[published]"; + return true; + case "Key": + columnName = "[umbracoNode].[uniqueID]"; + return true; + case "CreateDate": + columnName = "[umbracoNode].[createDate]"; + return true; + case "Name": + columnName = "[umbracoNode].[text]"; + return true; + } + } + + if (pi.DeclaringType == typeof(ContentType) || pi.DeclaringType == typeof(IContentType)) + { + switch (pi.Name) + { + case "Alias": + columnName = "[cmsContentType].[alias]"; + return true; + case "Icon": + columnName = "[cmsContentType].[icon]"; + return true; + case "Thumbnail": + columnName = "[cmsContentType].[thumbnail]"; + return true; + case "Description": + columnName = "[cmsContentType].[description]"; + return true; + } + } + + return true; + } + + public Func GetFromDbConverter(PropertyInfo pi, Type sourceType) + { + return null; + } + + public Func GetToDbConverter(Type sourceType) + { + return null; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Querying/ExpressionHelper.cs b/src/Umbraco.Core/Persistence/Querying/ExpressionHelper.cs new file mode 100644 index 0000000000..4a97dc571c --- /dev/null +++ b/src/Umbraco.Core/Persistence/Querying/ExpressionHelper.cs @@ -0,0 +1,572 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Globalization; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using Umbraco.Core.Persistence.Mappers; + +namespace Umbraco.Core.Persistence.Querying +{ + internal class ExpressionHelper + { + private string selectExpression = string.Empty; + private string whereExpression; + private string groupBy = string.Empty; + private string havingExpression; + private string orderBy = string.Empty; + + IList updateFields = new List(); + IList insertFields = new List(); + + private string sep = string.Empty; + private bool useFieldName = false; + private Database.PocoData pd; + + public ExpressionHelper() + { + Database.Mapper = new ModelDtoMapper(); + pd = new Database.PocoData(typeof(T)); + } + + protected internal virtual string Visit(Expression exp) + { + + if (exp == null) return string.Empty; + switch (exp.NodeType) + { + case ExpressionType.Lambda: + return VisitLambda(exp as LambdaExpression); + case ExpressionType.MemberAccess: + return VisitMemberAccess(exp as MemberExpression); + case ExpressionType.Constant: + return VisitConstant(exp as ConstantExpression); + case ExpressionType.Add: + case ExpressionType.AddChecked: + case ExpressionType.Subtract: + case ExpressionType.SubtractChecked: + case ExpressionType.Multiply: + case ExpressionType.MultiplyChecked: + case ExpressionType.Divide: + case ExpressionType.Modulo: + case ExpressionType.And: + case ExpressionType.AndAlso: + case ExpressionType.Or: + case ExpressionType.OrElse: + case ExpressionType.LessThan: + case ExpressionType.LessThanOrEqual: + case ExpressionType.GreaterThan: + case ExpressionType.GreaterThanOrEqual: + case ExpressionType.Equal: + case ExpressionType.NotEqual: + case ExpressionType.Coalesce: + case ExpressionType.ArrayIndex: + case ExpressionType.RightShift: + case ExpressionType.LeftShift: + case ExpressionType.ExclusiveOr: + return "(" + VisitBinary(exp as BinaryExpression) + ")"; + case ExpressionType.Negate: + case ExpressionType.NegateChecked: + case ExpressionType.Not: + case ExpressionType.Convert: + case ExpressionType.ConvertChecked: + case ExpressionType.ArrayLength: + case ExpressionType.Quote: + case ExpressionType.TypeAs: + return VisitUnary(exp as UnaryExpression); + case ExpressionType.Parameter: + return VisitParameter(exp as ParameterExpression); + case ExpressionType.Call: + return VisitMethodCall(exp as MethodCallExpression); + case ExpressionType.New: + return VisitNew(exp as NewExpression); + case ExpressionType.NewArrayInit: + case ExpressionType.NewArrayBounds: + return VisitNewArray(exp as NewArrayExpression); + default: + return exp.ToString(); + } + } + + protected virtual string VisitLambda(LambdaExpression lambda) + { + if (lambda.Body.NodeType == ExpressionType.MemberAccess && sep == " ") + { + MemberExpression m = lambda.Body as MemberExpression; + + if (m.Expression != null) + { + string r = VisitMemberAccess(m); + return string.Format("{0}={1}", r, GetQuotedTrueValue()); + } + + } + return Visit(lambda.Body); + } + + protected virtual string VisitBinary(BinaryExpression b) + { + string left, right; + var operand = BindOperant(b.NodeType); //sep= " " ?? + if (operand == "AND" || operand == "OR") + { + MemberExpression m = b.Left as MemberExpression; + if (m != null && m.Expression != null) + { + string r = VisitMemberAccess(m); + left = string.Format("{0}={1}", r, GetQuotedTrueValue()); + } + else + { + left = Visit(b.Left); + } + m = b.Right as MemberExpression; + if (m != null && m.Expression != null) + { + string r = VisitMemberAccess(m); + right = string.Format("{0}={1}", r, GetQuotedTrueValue()); + } + else + { + right = Visit(b.Right); + } + } + else + { + left = Visit(b.Left); + right = Visit(b.Right); + } + + if (operand == "=" && right == "null") operand = "is"; + else if (operand == "<>" && right == "null") operand = "is not"; + else if (operand == "=" || operand == "<>") + { + if (IsTrueExpression(right)) right = GetQuotedTrueValue(); + else if (IsFalseExpression(right)) right = GetQuotedFalseValue(); + + if (IsTrueExpression(left)) left = GetQuotedTrueValue(); + else if (IsFalseExpression(left)) left = GetQuotedFalseValue(); + + } + + switch (operand) + { + case "MOD": + case "COALESCE": + return string.Format("{0}({1},{2})", operand, left, right); + default: + return left + sep + operand + sep + right; + } + } + + protected virtual string VisitMemberAccess(MemberExpression m) + { + if (m.Expression != null && + m.Expression.NodeType == ExpressionType.Parameter + && m.Expression.Type == typeof(T)) + { + string field = GetFieldName(pd, m.Member.Name); + return field; + } + + if (m.Expression != null && m.Expression.NodeType != ExpressionType.Constant) + { + Database.Mapper = new ModelDtoMapper(); + var def = new Database.PocoData(m.Expression.Type); + string field = GetFieldName(def, m.Member.Name); + return field; + } + + + var member = Expression.Convert(m, typeof(object)); + var lambda = Expression.Lambda>(member); + var getter = lambda.Compile(); + object o = getter(); + return GetQuotedValue(o, o != null ? o.GetType() : null); + + } + + protected virtual string VisitNew(NewExpression nex) + { + // TODO : check ! + var member = Expression.Convert(nex, typeof(object)); + var lambda = Expression.Lambda>(member); + try + { + var getter = lambda.Compile(); + object o = getter(); + return GetQuotedValue(o, o.GetType()); + } + catch (System.InvalidOperationException) + { // FieldName ? + List exprs = VisitExpressionList(nex.Arguments); + var r = new StringBuilder(); + foreach (Object e in exprs) + { + r.AppendFormat("{0}{1}", + r.Length > 0 ? "," : "", + e); + } + return r.ToString(); + } + + } + + protected virtual string VisitParameter(ParameterExpression p) + { + return p.Name; + } + + protected virtual string VisitConstant(ConstantExpression c) + { + if (c.Value == null) + return "null"; + else if (c.Value.GetType() == typeof(bool)) + { + object o = GetQuotedValue(c.Value, c.Value.GetType()); + return string.Format("({0}={1})", GetQuotedTrueValue(), o); + } + else + return GetQuotedValue(c.Value, c.Value.GetType()); + } + + protected virtual string VisitUnary(UnaryExpression u) + { + switch (u.NodeType) + { + case ExpressionType.Not: + string o = Visit(u.Operand); + if (IsFieldName(o)) o = o + "=" + GetQuotedValue(true, typeof(bool)); + return "NOT (" + o + ")"; + default: + return Visit(u.Operand); + } + + } + + protected virtual string VisitMethodCall(MethodCallExpression m) + { + List args = this.VisitExpressionList(m.Arguments); + + Object r; + if (m.Object != null) + r = Visit(m.Object); + else + { + r = args[0]; + args.RemoveAt(0); + } + + switch (m.Method.Name) + { + case "ToUpper": + return string.Format("upper({0})", r); + case "ToLower": + return string.Format("lower({0})", r); + case "StartsWith": + return string.Format("upper({0}) starting with {1} ", r, args[0].ToString().ToUpper()); + case "EndsWith": + return string.Format("upper({0}) like '%{1}'", r, RemoveQuote(args[0].ToString()).ToUpper()); + case "Contains": + return string.Format("upper({0}) like '%{1}%'", r, RemoveQuote(args[0].ToString()).ToUpper()); + case "Substring": + var startIndex = Int32.Parse(args[0].ToString()) + 1; + if (args.Count == 2) + { + var length = Int32.Parse(args[1].ToString()); + return string.Format("substring({0} from {1} for {2})", + r, + startIndex, + length); + } + else + return string.Format("substring({0} from {1})", + r, + startIndex); + case "Round": + case "Floor": + case "Ceiling": + case "Coalesce": + case "Abs": + case "Sum": + return string.Format("{0}({1}{2})", + m.Method.Name, + r, + args.Count == 1 ? string.Format(",{0}", args[0]) : ""); + case "Concat": + var s = new StringBuilder(); + foreach (Object e in args) + { + s.AppendFormat(" || {0}", e); + } + return string.Format("{0}{1}", r, s.ToString()); + + case "In": + + var member = Expression.Convert(m.Arguments[1], typeof(object)); + var lambda = Expression.Lambda>(member); + var getter = lambda.Compile(); + + var inArgs = getter() as object[]; + + var sIn = new StringBuilder(); + foreach (Object e in inArgs) + { + if (e.GetType().ToString() != "System.Collections.Generic.List`1[System.Object]") + { + sIn.AppendFormat("{0}{1}", + sIn.Length > 0 ? "," : "", + GetQuotedValue(e, e.GetType())); + } + else + { + var listArgs = e as IList; + foreach (Object el in listArgs) + { + sIn.AppendFormat("{0}{1}", + sIn.Length > 0 ? "," : "", + GetQuotedValue(el, el.GetType())); + } + } + } + + return string.Format("{0} {1} ({2})", r, m.Method.Name, sIn.ToString()); + case "Desc": + return string.Format("{0} DESC", r); + case "Alias": + case "As": + return string.Format("{0} As {1}", r, + GetQuotedColumnName(RemoveQuoteFromAlias(RemoveQuote(args[0].ToString())))); + case "ToString": + return r.ToString(); + default: + var s2 = new StringBuilder(); + foreach (Object e in args) + { + s2.AppendFormat(",{0}", GetQuotedValue(e, e.GetType())); + } + return string.Format("{0}({1}{2})", m.Method.Name, r, s2.ToString()); + } + } + + protected virtual List VisitExpressionList(ReadOnlyCollection original) + { + var list = new List(); + for (int i = 0, n = original.Count; i < n; i++) + { + if (original[i].NodeType == ExpressionType.NewArrayInit || + original[i].NodeType == ExpressionType.NewArrayBounds) + { + + list.AddRange(VisitNewArrayFromExpressionList(original[i] as NewArrayExpression)); + } + else + list.Add(Visit(original[i])); + + } + return list; + } + + protected virtual string VisitNewArray(NewArrayExpression na) + { + + List exprs = VisitExpressionList(na.Expressions); + var r = new StringBuilder(); + foreach (Object e in exprs) + { + r.Append(r.Length > 0 ? "," + e : e); + } + + return r.ToString(); + } + + protected virtual List VisitNewArrayFromExpressionList(NewArrayExpression na) + { + + List exprs = VisitExpressionList(na.Expressions); + return exprs; + } + + + protected virtual string BindOperant(ExpressionType e) + { + + switch (e) + { + case ExpressionType.Equal: + return "="; + case ExpressionType.NotEqual: + return "<>"; + case ExpressionType.GreaterThan: + return ">"; + case ExpressionType.GreaterThanOrEqual: + return ">="; + case ExpressionType.LessThan: + return "<"; + case ExpressionType.LessThanOrEqual: + return "<="; + case ExpressionType.AndAlso: + return "AND"; + case ExpressionType.OrElse: + return "OR"; + case ExpressionType.Add: + return "+"; + case ExpressionType.Subtract: + return "-"; + case ExpressionType.Multiply: + return "*"; + case ExpressionType.Divide: + return "/"; + case ExpressionType.Modulo: + return "MOD"; + case ExpressionType.Coalesce: + return "COALESCE"; + default: + return e.ToString(); + } + } + + public virtual string GetQuotedTableName(string tableName) + { + return string.Format("\"{0}\"", tableName); + } + + public virtual string GetQuotedColumnName(string columnName) + { + return string.Format("\"{0}\"", columnName); + } + + public virtual string GetQuotedName(string name) + { + return string.Format("\"{0}\"", name); + } + + private string GetQuotedTrueValue() + { + return GetQuotedValue(true, typeof(bool)); + } + + private string GetQuotedFalseValue() + { + return GetQuotedValue(false, typeof(bool)); + } + + public virtual string GetQuotedValue(object value, Type fieldType) + { + if (value == null) return "NULL"; + + if (!fieldType.UnderlyingSystemType.IsValueType && fieldType != typeof(string)) + { + //if (TypeSerializer.CanCreateFromString(fieldType)) + //{ + // return "'" + EscapeParam(TypeSerializer.SerializeToString(value)) + "'"; + //} + + throw new NotSupportedException( + string.Format("Property of type: {0} is not supported", fieldType.FullName)); + } + + if (fieldType == typeof(int)) + return ((int)value).ToString(CultureInfo.InvariantCulture); + + if (fieldType == typeof(float)) + return ((float)value).ToString(CultureInfo.InvariantCulture); + + if (fieldType == typeof(double)) + return ((double)value).ToString(CultureInfo.InvariantCulture); + + if (fieldType == typeof(decimal)) + return ((decimal)value).ToString(CultureInfo.InvariantCulture); + + return ShouldQuoteValue(fieldType) + ? "'" + EscapeParam(value) + "'" + : value.ToString(); + } + + public virtual string EscapeParam(object paramValue) + { + return paramValue.ToString().Replace("'", "''"); + } + + public virtual bool ShouldQuoteValue(Type fieldType) + { + return true; + } + + protected virtual string GetFieldName(Database.PocoData pocoData, string name) + { + var column = pocoData.Columns.FirstOrDefault(x => x.Value.PropertyInfo.Name == name); + return column.Value.ColumnName; + } + + protected virtual string GetFieldName(string name) + { + + if (useFieldName) + { + //FieldDefinition fd = modelDef.FieldDefinitions.FirstOrDefault(x => x.Name == name); + //string fn = fd != default(FieldDefinition) ? fd.FieldName : name; + //return OrmLiteConfig.DialectProvider.GetQuotedColumnName(fn); + return "[" + name + "]"; + } + else + { + return name; + } + } + + protected string RemoveQuote(string exp) + { + + if (exp.StartsWith("'") && exp.EndsWith("'")) + { + exp = exp.Remove(0, 1); + exp = exp.Remove(exp.Length - 1, 1); + } + return exp; + } + + protected string RemoveQuoteFromAlias(string exp) + { + + if ((exp.StartsWith("\"") || exp.StartsWith("`") || exp.StartsWith("'")) + && + (exp.EndsWith("\"") || exp.EndsWith("`") || exp.EndsWith("'"))) + { + exp = exp.Remove(0, 1); + exp = exp.Remove(exp.Length - 1, 1); + } + return exp; + } + + private string GetTrueExpression() + { + object o = GetQuotedTrueValue(); + return string.Format("({0}={1})", o, o); + } + + private string GetFalseExpression() + { + + return string.Format("({0}={1})", + GetQuotedTrueValue(), + GetQuotedFalseValue()); + } + + private bool IsTrueExpression(string exp) + { + return (exp == GetTrueExpression()); + } + + private bool IsFalseExpression(string exp) + { + return (exp == GetFalseExpression()); + } + + protected bool IsFieldName(string quotedExp) + { + return true; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Configurations/RepositorySettingsTests.cs b/src/Umbraco.Tests/Configurations/RepositorySettingsTests.cs new file mode 100644 index 0000000000..c25bd853b5 --- /dev/null +++ b/src/Umbraco.Tests/Configurations/RepositorySettingsTests.cs @@ -0,0 +1,32 @@ +using System.Configuration; +using NUnit.Framework; +using Umbraco.Core.Configuration.InfrastructureSettings; + +namespace Umbraco.Tests.Configurations +{ + [TestFixture] + public class RepositorySettingsTests + { + [Test] + public void Can_Get_Repository_From_Config() + { + Infrastructure infrastructure = Infrastructure.Instance; + Repositories repositories = infrastructure.Repositories; + Repository repository = repositories.Repository["IContentRepository"]; + + Assert.That(repository, Is.Not.Null); + Assert.AreEqual(repository.InterfaceShortTypeName, "IContentRepository"); + Assert.AreEqual(repository.RepositoryFullTypeName, "Umbraco.Core.Persistence.Repositories.ContentRepository, Umbraco.Core"); + Assert.AreEqual(repository.CacheProviderFullTypeName, "Umbraco.Core.Persistence.Caching.RuntimeCacheProvider, Umbraco.Core"); + } + + [Test] + public void Can_Get_PublishingStrategy_From_Config() + { + Infrastructure infrastructure = Infrastructure.Instance; + PublishingProvider strategy = infrastructure.PublishingStrategy; + + Assert.That(strategy.Type, Is.EqualTo("Umbraco.Web.Publishing.PublishingStrategy, Umbraco.Web")); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Persistence/DatabaseFactoryTests.cs b/src/Umbraco.Tests/Persistence/DatabaseFactoryTests.cs new file mode 100644 index 0000000000..4a3337f1b2 --- /dev/null +++ b/src/Umbraco.Tests/Persistence/DatabaseFactoryTests.cs @@ -0,0 +1,18 @@ +using NUnit.Framework; +using Umbraco.Core.Persistence; + +namespace Umbraco.Tests.Persistence +{ + [TestFixture] + public class DatabaseFactoryTests + { + [Test] + public void Can_Verify_Single_Database_Instance() + { + var db1 = DatabaseFactory.Current.Database; + var db2 = DatabaseFactory.Current.Database; + + Assert.AreSame(db1, db2); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs index 8400f1afe0..6a942594ae 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs @@ -32,7 +32,7 @@ namespace Umbraco.Tests.Persistence.Repositories }; DataTypesResolver.Current = new DataTypesResolver( - PluginManager.Current.ResolveDataTypes()); + () => PluginManager.Current.ResolveDataTypes()); base.Initialize(); diff --git a/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs index 5e907c53b2..73249bc3a1 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs @@ -32,7 +32,7 @@ namespace Umbraco.Tests.Persistence.Repositories }; DataTypesResolver.Current = new DataTypesResolver( - PluginManager.Current.ResolveDataTypes()); + () => PluginManager.Current.ResolveDataTypes()); base.Initialize(); From a909b7904ed6fc0d778b9d7ab20d69711fc16b28 Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Fri, 1 Feb 2013 05:29:54 +0600 Subject: [PATCH 40/43] Fixes uGoLive ascx --- src/Umbraco.Web.UI/umbraco/plugins/uGoLive/Dashboard.ascx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI/umbraco/plugins/uGoLive/Dashboard.ascx b/src/Umbraco.Web.UI/umbraco/plugins/uGoLive/Dashboard.ascx index 973bdc1028..a22af5a4f4 100644 --- a/src/Umbraco.Web.UI/umbraco/plugins/uGoLive/Dashboard.ascx +++ b/src/Umbraco.Web.UI/umbraco/plugins/uGoLive/Dashboard.ascx @@ -1,4 +1,4 @@ -<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Dashboard.ascx.cs" Inherits="Our.Umbraco.uGoLive.Web.Umbraco.Plugins.uGoLive.Dashboard" %> +<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Dashboard.ascx.cs" Inherits="Our.Umbraco.uGoLive.Web.Umbraco.Plugins.uGoLive.Dashboard" %> <%@ Import Namespace="umbraco.IO" %> <%@ Import Namespace="Our.Umbraco.uGoLive.Web" %> @@ -24,7 +24,7 @@ -
+
From 560270164523b6672f7cf14e0c798ef29815567e Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Fri, 1 Feb 2013 06:05:39 +0600 Subject: [PATCH 41/43] Fixes uGoLive id and changes dashboard ascx to use CDF to load scripts/styles and using the knockout version shipped in the core. Removes duplicate tree from the config. --- src/Umbraco.Web.UI/config/trees.config | 1 - .../umbraco/plugins/uGoLive/Dashboard.ascx | 14 ++++++++------ .../UmbracoClientDependencyLoader.cs | 6 +++--- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Web.UI/config/trees.config b/src/Umbraco.Web.UI/config/trees.config index 34558bbdaf..6834440077 100644 --- a/src/Umbraco.Web.UI/config/trees.config +++ b/src/Umbraco.Web.UI/config/trees.config @@ -20,7 +20,6 @@ - diff --git a/src/Umbraco.Web.UI/umbraco/plugins/uGoLive/Dashboard.ascx b/src/Umbraco.Web.UI/umbraco/plugins/uGoLive/Dashboard.ascx index 973bdc1028..2650140730 100644 --- a/src/Umbraco.Web.UI/umbraco/plugins/uGoLive/Dashboard.ascx +++ b/src/Umbraco.Web.UI/umbraco/plugins/uGoLive/Dashboard.ascx @@ -1,11 +1,13 @@ <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Dashboard.ascx.cs" Inherits="Our.Umbraco.uGoLive.Web.Umbraco.Plugins.uGoLive.Dashboard" %> <%@ Import Namespace="umbraco.IO" %> <%@ Import Namespace="Our.Umbraco.uGoLive.Web" %> - - - - - +<%@ Register Namespace="ClientDependency.Core.Controls" Assembly="ClientDependency.Core" TagPrefix="cdf" %> + + + + + + -
+
diff --git a/src/umbraco.controls/UmbracoClientDependencyLoader.cs b/src/umbraco.controls/UmbracoClientDependencyLoader.cs index 54536fb9e2..06c369a5a1 100644 --- a/src/umbraco.controls/UmbracoClientDependencyLoader.cs +++ b/src/umbraco.controls/UmbracoClientDependencyLoader.cs @@ -5,7 +5,7 @@ using System.Text; using System.Web.UI; using ClientDependency.Core.Controls; using ClientDependency.Core.FileRegistration.Providers; -using umbraco.IO; +using Umbraco.Core.IO; namespace umbraco.uicontrols { @@ -22,7 +22,7 @@ namespace umbraco.uicontrols public UmbracoClientDependencyLoader() : base() { - this.AddPath("UmbracoClient", IOHelper.ResolveUrl( SystemDirectories.Umbraco_client )); + this.AddPath("UmbracoClient", IOHelper.ResolveUrl( SystemDirectories.UmbracoClient )); this.AddPath("UmbracoRoot", IOHelper.ResolveUrl( SystemDirectories.Umbraco )); this.ProviderName = LoaderControlProvider.DefaultName; @@ -32,7 +32,7 @@ namespace umbraco.uicontrols { if (ClientDependencyLoader.Instance == null) { - UmbracoClientDependencyLoader loader = new UmbracoClientDependencyLoader(); + var loader = new UmbracoClientDependencyLoader(); parent.Controls.Add(loader); isNew = true; return loader; From bea6031de1924f81f1f21e9288942ad6ad98f658 Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Fri, 1 Feb 2013 06:34:28 +0600 Subject: [PATCH 42/43] Removes UpgradeScripts stuff from 4.11.4 ... now to go remove it from there too since I've moved the script to a package. --- .../Configuration/GlobalSettings.cs | 24 ---- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 7 - .../install/steps/UpgradeScripts.ascx | 14 -- .../install/steps/UpgradeScripts.ascx.cs | 28 ---- .../steps/UpgradeScripts.ascx.designer.cs | 24 ---- .../Install/UpgradeScripts/ContentPathFix.cs | 130 ------------------ .../Install/UpgradeScripts/IUpgradeScript.cs | 7 - .../UpgradeScripts/UpgradeScriptManager.cs | 84 ----------- .../UpgradeScripts/UpgradeScriptRegistrar.cs | 28 ---- .../Install/UpgradeScripts/VersionRange.cs | 40 ------ src/Umbraco.Web/Umbraco.Web.csproj | 10 +- src/Umbraco.Web/WebBootManager.cs | 2 - .../install/default.aspx.cs | 1 - .../install/steps/Definitions/Database.cs | 11 +- .../steps/Definitions/UpgradeScripts.cs | 78 ----------- 15 files changed, 7 insertions(+), 481 deletions(-) delete mode 100644 src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx delete mode 100644 src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.cs delete mode 100644 src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.designer.cs delete mode 100644 src/Umbraco.Web/Install/UpgradeScripts/ContentPathFix.cs delete mode 100644 src/Umbraco.Web/Install/UpgradeScripts/IUpgradeScript.cs delete mode 100644 src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptManager.cs delete mode 100644 src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptRegistrar.cs delete mode 100644 src/Umbraco.Web/Install/UpgradeScripts/VersionRange.cs delete mode 100644 src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/UpgradeScripts.cs diff --git a/src/Umbraco.Core/Configuration/GlobalSettings.cs b/src/Umbraco.Core/Configuration/GlobalSettings.cs index b837293016..7e6e2d53b5 100644 --- a/src/Umbraco.Core/Configuration/GlobalSettings.cs +++ b/src/Umbraco.Core/Configuration/GlobalSettings.cs @@ -201,30 +201,6 @@ namespace Umbraco.Core.Configuration } } - /// - /// Returns the configuration status version as a versoin object or null if it cannot parse - /// - /// - internal static Version GetConfigurationVersion() - { - //create a real version out of the one stored in the settings - var configVersion = ConfigurationStatus.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries); - if (configVersion.Length == 0) - return null; - - int major; - var minor = 0; - var patch = 0; - int currentPart; - if (configVersion.Length > 0 && int.TryParse(configVersion[0], out currentPart)) - major = currentPart; - else - return null; //couldn't parse, no valid version - if (configVersion.Length > 1 && int.TryParse(configVersion[1], out currentPart)) minor = currentPart; - if (configVersion.Length > 2 && int.TryParse(configVersion[2], out currentPart)) patch = currentPart; - - return new Version(major, minor, patch); - } /// /// Saves a setting into the configuration file. diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 1547e770e8..d8f16edbd6 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -275,13 +275,6 @@ loadStarterKits.ascx - - UpgradeScripts.ascx - ASPXCodeBehind - - - UpgradeScripts.ascx - PartialViewMacro.ascx diff --git a/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx b/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx deleted file mode 100644 index 2728a12f66..0000000000 --- a/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx +++ /dev/null @@ -1,14 +0,0 @@ -<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="UpgradeScripts.ascx.cs" Inherits="Umbraco.Web.UI.Install.Steps.UpgradeScripts" %> -
-
-

Upgrade scripts

-

- We need to run a few upgrade scripts, press Continue to execute these scripts and continue to the next step. -

-
- -
-
 
- Continue -
-
\ No newline at end of file diff --git a/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.cs b/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.cs deleted file mode 100644 index 0d94b30821..0000000000 --- a/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.UI; -using System.Web.UI.WebControls; -using Umbraco.Core.Configuration; -using umbraco.presentation.install; -using Umbraco.Web.Install.UpgradeScripts; - -namespace Umbraco.Web.UI.Install.Steps -{ - public partial class UpgradeScripts : System.Web.UI.UserControl - { - protected void Page_Load(object sender, EventArgs e) - { - - } - - protected void RunScripts(object sender, EventArgs e) - { - //run the scripts and then go to the next step - UpgradeScriptManager.ExecuteScriptsForVersion(GlobalSettings.GetConfigurationVersion()); - - Helper.RedirectToNextStep(Page); - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.designer.cs b/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.designer.cs deleted file mode 100644 index a55927fd35..0000000000 --- a/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.designer.cs +++ /dev/null @@ -1,24 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Umbraco.Web.UI.Install.Steps { - - - public partial class UpgradeScripts { - - /// - /// btnNext control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.LinkButton btnNext; - } -} diff --git a/src/Umbraco.Web/Install/UpgradeScripts/ContentPathFix.cs b/src/Umbraco.Web/Install/UpgradeScripts/ContentPathFix.cs deleted file mode 100644 index f52ae5078d..0000000000 --- a/src/Umbraco.Web/Install/UpgradeScripts/ContentPathFix.cs +++ /dev/null @@ -1,130 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using Umbraco.Core; -using Umbraco.Core.IO; -using umbraco.cms.businesslogic; -using umbraco.cms.businesslogic.web; - -namespace Umbraco.Web.Install.UpgradeScripts -{ - /// - /// An upgrade script to fix a moving issue in 4.10+ - /// http://issues.umbraco.org/issue/U4-1491 - /// - public class ContentPathFix : IUpgradeScript - { - private readonly StringBuilder _report = new StringBuilder(); - - public void Execute() - { - //return; - if (ApplicationContext.Current == null) return; - if (HasBeenFixed()) return; - Fix(); - WriteReport(); - } - - private void Fix() - { - AddReportLine("Starting fix paths script"); - - //fix content - AddReportLine("Fixing content"); - foreach (var d in Document.GetRootDocuments()) - { - FixPathsForChildren(d, content => ((Document)content).Children); - } - AddReportLine("Fixing content recycle bin"); - var contentRecycleBin = new RecycleBin(RecycleBin.RecycleBinType.Content); - foreach (var d in contentRecycleBin.Children) - { - FixPathsForChildren(new Document(d.Id), content => ((Document)content).Children); - } - - //fix media - AddReportLine("Fixing media"); - foreach (var d in global::umbraco.cms.businesslogic.media.Media.GetRootMedias()) - { - FixPathsForChildren(d, media => ((global::umbraco.cms.businesslogic.media.Media)media).Children); - } - AddReportLine("Fixing media recycle bin"); - var mediaRecycleBin = new RecycleBin(RecycleBin.RecycleBinType.Media); - foreach (var d in mediaRecycleBin.Children) - { - FixPathsForChildren(new global::umbraco.cms.businesslogic.media.Media(d.Id), media => ((global::umbraco.cms.businesslogic.media.Media)media).Children); - } - AddReportLine("Complete!"); - } - - /// - /// Returns true if this script has run based on a temp file written to - /// ~/App_Data/TEMP/FixPaths/report.txt - /// - /// - private bool HasBeenFixed() - { - return File.Exists(IOHelper.MapPath("~/App_Data/TEMP/FixPaths/report.txt")); - } - - /// - /// Creates the report - /// - private void WriteReport() - { - var filePath = IOHelper.MapPath("~/App_Data/TEMP/FixPaths/report.txt"); - Directory.CreateDirectory(Path.GetDirectoryName(filePath)); - using (var writer = File.CreateText(IOHelper.MapPath("~/App_Data/TEMP/FixPaths/report.txt"))) - { - writer.Write(_report.ToString()); - } - } - - /// - /// Recursively iterates over the children of the document and fixes the path - /// - /// - /// Callback to get the children of the conent item - /// - /// We cannot use GetDescendants() because that is based on the paths of documents and if they are invalid then - /// we cannot use that method. - /// - private void FixPathsForChildren(Content d, Func> getChildren) - { - AddReportLine("Fixing paths for children of " + d.Id); - foreach (var c in getChildren(d)) - { - FixPath(c); - if (c.HasChildren) - { - FixPathsForChildren(c, getChildren); - } - } - } - - /// - /// Check if the path is correct based on the document's parent if it is not correct, then fix it - /// - /// - private void FixPath(CMSNode d) - { - AddReportLine("Checking path for " + d.Id + ". Current = " + d.Path); - //check if the path is correct - var correctpath = d.Parent.Path + "," + d.Id.ToString(); - if (d.Path != correctpath) - { - AddReportLine(" INVALID PATH DETECTED. Path for " + d.Id + " changed to: " + d.Parent.Path + "," + d.Id.ToString()); - d.Path = correctpath; - d.Level = d.Parent.Level + 1; - } - } - - private void AddReportLine(string str) - { - _report.AppendLine(string.Format("{0} - " + str, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"))); - } - - - } -} \ No newline at end of file diff --git a/src/Umbraco.Web/Install/UpgradeScripts/IUpgradeScript.cs b/src/Umbraco.Web/Install/UpgradeScripts/IUpgradeScript.cs deleted file mode 100644 index 339dbd4ac2..0000000000 --- a/src/Umbraco.Web/Install/UpgradeScripts/IUpgradeScript.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Umbraco.Web.Install.UpgradeScripts -{ - internal interface IUpgradeScript - { - void Execute(); - } -} \ No newline at end of file diff --git a/src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptManager.cs b/src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptManager.cs deleted file mode 100644 index 472415598d..0000000000 --- a/src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptManager.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Umbraco.Core.Configuration; -using umbraco.DataLayer.Utility.Installer; - -namespace Umbraco.Web.Install.UpgradeScripts -{ - /// - /// Class used to register and execute upgrade scripts during install if they are required. - /// - internal static class UpgradeScriptManager - { - /// - /// Returns true if there are scripts to execute for the version - /// - /// - /// - public static bool HasScriptsForVersion(Version version) - { - return Scripts.Any(x => x.Item2.InRange(version)); - } - - /// - /// Executes all of the scripts for a database version - /// - /// - /// - public static void ExecuteScriptsForVersion(Version version) - { - var types = Scripts.Where(x => x.Item2.InRange(version)).Select(x => x.Item1); - foreach (var instance in types.Select(x => x())) - { - instance.Execute(); - } - } - - public static void AddUpgradeScript(Func script, VersionRange version) - { - Scripts.Add(new Tuple, VersionRange>(script, version)); - } - - ///// - ///// Adds a script to execute for a database version - ///// - ///// - ///// - //public static void AddUpgradeScript(string assemblyQualifiedTypeName, VersionRange version) - //{ - // AddUpgradeScript(new Lazy(() => Type.GetType(assemblyQualifiedTypeName)), version); - //} - - ///// - ///// Adds a script to execute for a database version - ///// - ///// - ///// - //public static void AddUpgradeScript(VersionRange version) - //{ - // AddUpgradeScript(new Lazy(() => typeof(T)), version); - //} - - /// - /// Used for testing - /// - internal static void Clear() - { - Scripts.Clear(); - } - - ///// - ///// Adds a script to execute for a database version - ///// - ///// - ///// - //public static void AddUpgradeScript(Lazy type, VersionRange version) - //{ - // Scripts.Add(new Tuple, VersionRange>(type, version)); - //} - - private static readonly List, VersionRange>> Scripts = new List, VersionRange>>(); - //private static readonly List, VersionRange>> Scripts = new List, VersionRange>>(); - } -} \ No newline at end of file diff --git a/src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptRegistrar.cs b/src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptRegistrar.cs deleted file mode 100644 index 611703b7d8..0000000000 --- a/src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptRegistrar.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using Umbraco.Core; - -namespace Umbraco.Web.Install.UpgradeScripts -{ - internal class UpgradeScriptRegistrar : IApplicationEventHandler - { - public void OnApplicationInitialized(UmbracoApplication httpApplication, ApplicationContext applicationContext) - { - //Add contnet path fixup for any version from 4.10 up to 4.11.4 - UpgradeScriptManager.AddUpgradeScript( - () => new ContentPathFix(), - new VersionRange( - new Version(4, 10), - new Version(4, 11, 4))); - } - - public void OnApplicationStarting(UmbracoApplication httpApplication, ApplicationContext applicationContext) - { - - } - - public void OnApplicationStarted(UmbracoApplication httpApplication, ApplicationContext applicationContext) - { - - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Web/Install/UpgradeScripts/VersionRange.cs b/src/Umbraco.Web/Install/UpgradeScripts/VersionRange.cs deleted file mode 100644 index adafd7691a..0000000000 --- a/src/Umbraco.Web/Install/UpgradeScripts/VersionRange.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; - -namespace Umbraco.Web.Install.UpgradeScripts -{ - internal class VersionRange - { - private readonly Version _specificVersion; - private readonly Version _startVersion; - private readonly Version _endVersion; - - public VersionRange(Version specificVersion) - { - _specificVersion = specificVersion; - } - - public VersionRange(Version startVersion, Version endVersion) - { - _startVersion = startVersion; - _endVersion = endVersion; - } - - /// - /// Checks if the versionCheck is in the range (in between) the start and end version - /// - /// - /// - /// - /// For example if our version range is 4.10 -> 4.11.4, we want to return true if the version being checked is: - /// greater than or equal to the start version but less than the end version. - /// - public bool InRange(Version versionCheck) - { - //if it is a specific version - if (_specificVersion != null) - return versionCheck == _specificVersion; - - return versionCheck >= _startVersion && versionCheck < _endVersion; - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index cac8e5c3f6..5edeb5f919 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -257,11 +257,6 @@ - - - - - @@ -351,7 +346,6 @@ ASPXCodeBehind - ASPXCodeBehind @@ -2048,7 +2042,9 @@ ASPXCodeBehind - + + ASPXCodeBehind + diff --git a/src/Umbraco.Web/WebBootManager.cs b/src/Umbraco.Web/WebBootManager.cs index 5ea02da00e..2c7fd2d023 100644 --- a/src/Umbraco.Web/WebBootManager.cs +++ b/src/Umbraco.Web/WebBootManager.cs @@ -10,7 +10,6 @@ using Umbraco.Core.Dynamics; using Umbraco.Core.ObjectResolution; using Umbraco.Core.PropertyEditors; using Umbraco.Web.Dictionary; -using Umbraco.Web.Install.UpgradeScripts; using Umbraco.Web.Media; using Umbraco.Web.Media.ThumbnailProviders; using Umbraco.Web.Models; @@ -71,7 +70,6 @@ namespace Umbraco.Web //set model binder ModelBinders.Binders.Add(new KeyValuePair(typeof(RenderModel), new RenderModelBinder())); - ApplicationEventsResolver.Current.AddType(); return this; } diff --git a/src/Umbraco.Web/umbraco.presentation/install/default.aspx.cs b/src/Umbraco.Web/umbraco.presentation/install/default.aspx.cs index 16ceb1195f..479cb474c6 100644 --- a/src/Umbraco.Web/umbraco.presentation/install/default.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/install/default.aspx.cs @@ -136,7 +136,6 @@ namespace umbraco.presentation.install ics.Add(new install.steps.Definitions.Welcome()); ics.Add(new install.steps.Definitions.License()); ics.Add(new install.steps.Definitions.FilePermissions()); - ics.Add(new install.steps.Definitions.UpgradeScripts()); ics.Add(new install.steps.Definitions.Database()); ics.Add(new install.steps.Definitions.DefaultUser()); ics.Add(new install.steps.Definitions.Skinning()); diff --git a/src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/Database.cs b/src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/Database.cs index 8377000db7..54bdc0c721 100644 --- a/src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/Database.cs +++ b/src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/Database.cs @@ -1,4 +1,5 @@ -using Umbraco.Core; +using System; +using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.IO; using umbraco.cms.businesslogic.installer; @@ -26,10 +27,7 @@ namespace umbraco.presentation.install.steps.Definitions public override bool MoveToNextStepAutomaticly { - get - { - return true; - } + get { return true; } } //here we determine if the installer should skip this step... @@ -42,7 +40,6 @@ namespace umbraco.presentation.install.steps.Definitions var result = ApplicationContext.Current.DatabaseContext.ValidateDatabaseSchema(); var determinedVersion = result.DetermineInstalledVersion(); if (determinedVersion.Equals(new Version(0, 0, 0))) - { return false; return UmbracoVersion.Current < determinedVersion; @@ -50,7 +47,7 @@ namespace umbraco.presentation.install.steps.Definitions var configuredVersion = new Version(Umbraco.Core.Configuration.GlobalSettings.ConfigurationStatus); var targetVersion = UmbracoVersion.Current; - + return targetVersion < configuredVersion; } } diff --git a/src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/UpgradeScripts.cs b/src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/UpgradeScripts.cs deleted file mode 100644 index 57d4cf9d9b..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/UpgradeScripts.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; -using Umbraco.Core; -using Umbraco.Core.IO; -using Umbraco.Web.Install.UpgradeScripts; -using umbraco.DataLayer.Utility.Installer; -using umbraco.cms.businesslogic.installer; - -namespace umbraco.presentation.install.steps.Definitions -{ - internal class UpgradeScripts : InstallerStep - { - - - - public override string Alias - { - get { return "upgradeScripts"; } - } - - public override bool HideFromNavigation - { - get { return true; } - } - - /// - /// If there are no scripts for this version the skip - /// - /// - public override bool Completed() - { - var canConnect = CanConnectToDb(); - //if we cannot connect to the db, then we cannot run the script and most likely the database doesn't exist yet anyways. - if (!canConnect) return true; //skip - - //if the version is empty then it's probably a new installation, we cannot run scripts - if (GlobalSettings.CurrentVersion.IsNullOrWhiteSpace()) return true; //skip - var currentUmbVersion = Umbraco.Core.Configuration.GlobalSettings.GetConfigurationVersion(); - if (currentUmbVersion == null) - return true; //skip, could not get a version - - //check if we have upgrade script to run for this version - var hasScripts = UpgradeScriptManager.HasScriptsForVersion(currentUmbVersion); - return !hasScripts; - } - - public override string Name - { - get { return "Upgrade scripts"; } - } - - public override string UserControl - { - get { return SystemDirectories.Install + "/steps/UpgradeScripts.ascx"; } - } - - public override bool MoveToNextStepAutomaticly - { - get - { - return true; - } - } - - private bool CanConnectToDb() - { - try - { - var installer = BusinessLogic.Application.SqlHelper.Utility.CreateInstaller(); - var latest = installer.IsLatestVersion; - return true; //if we got this far, we can connect. - } - catch - { - return false; - } - } - } -} \ No newline at end of file From 1da27e6c2b95301a516f4a13448498059af0e581 Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Fri, 1 Feb 2013 06:42:42 +0600 Subject: [PATCH 43/43] Removes all upgrade script stuff since we've deployed the fix in a package. --- .../Configuration/GlobalSettings.cs | 27 +--- .../Install/UpgradeScriptsTests.cs | 68 --------- src/Umbraco.Tests/Umbraco.Tests.csproj | 1 - src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 8 -- .../install/steps/UpgradeScripts.ascx | 14 -- .../install/steps/UpgradeScripts.ascx.cs | 28 ---- .../steps/UpgradeScripts.ascx.designer.cs | 24 ---- .../Install/UpgradeScripts/ContentPathFix.cs | 130 ------------------ .../Install/UpgradeScripts/IUpgradeScript.cs | 7 - .../UpgradeScripts/UpgradeScriptManager.cs | 84 ----------- .../UpgradeScripts/UpgradeScriptRegistrar.cs | 28 ---- .../Install/UpgradeScripts/VersionRange.cs | 40 ------ src/Umbraco.Web/Umbraco.Web.csproj | 10 +- src/Umbraco.Web/WebBootManager.cs | 2 - .../install/default.aspx.cs | 1 - .../steps/Definitions/UpgradeScripts.cs | 78 ----------- .../install/utills/p.aspx.cs | 1 - 17 files changed, 4 insertions(+), 547 deletions(-) delete mode 100644 src/Umbraco.Tests/Install/UpgradeScriptsTests.cs delete mode 100644 src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx delete mode 100644 src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.cs delete mode 100644 src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.designer.cs delete mode 100644 src/Umbraco.Web/Install/UpgradeScripts/ContentPathFix.cs delete mode 100644 src/Umbraco.Web/Install/UpgradeScripts/IUpgradeScript.cs delete mode 100644 src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptManager.cs delete mode 100644 src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptRegistrar.cs delete mode 100644 src/Umbraco.Web/Install/UpgradeScripts/VersionRange.cs delete mode 100644 src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/UpgradeScripts.cs diff --git a/src/Umbraco.Core/Configuration/GlobalSettings.cs b/src/Umbraco.Core/Configuration/GlobalSettings.cs index 8728bb30ff..7086b67c7a 100644 --- a/src/Umbraco.Core/Configuration/GlobalSettings.cs +++ b/src/Umbraco.Core/Configuration/GlobalSettings.cs @@ -181,32 +181,7 @@ namespace Umbraco.Core.Configuration SaveSetting("umbracoConfigurationStatus", value); } } - - /// - /// Returns the configuration status version as a versoin object or null if it cannot parse - /// - /// - internal static Version GetConfigurationVersion() - { - //create a real version out of the one stored in the settings - var configVersion = ConfigurationStatus.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries); - if (configVersion.Length == 0) - return null; - - int major; - var minor = 0; - var patch = 0; - int currentPart; - if (configVersion.Length > 0 && int.TryParse(configVersion[0], out currentPart)) - major = currentPart; - else - return null; //couldn't parse, no valid version - if (configVersion.Length > 1 && int.TryParse(configVersion[1], out currentPart)) minor = currentPart; - if (configVersion.Length > 2 && int.TryParse(configVersion[2], out currentPart)) patch = currentPart; - - return new Version(major, minor, patch); - } - + /// /// Saves a setting into the configuration file. /// diff --git a/src/Umbraco.Tests/Install/UpgradeScriptsTests.cs b/src/Umbraco.Tests/Install/UpgradeScriptsTests.cs deleted file mode 100644 index daf95b2241..0000000000 --- a/src/Umbraco.Tests/Install/UpgradeScriptsTests.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using NUnit.Framework; -using Umbraco.Web.Install.UpgradeScripts; - -namespace Umbraco.Tests.Install -{ - [TestFixture] - public class UpgradeScriptsTests - { - [TearDown] - public void TearDown() - { - UpgradeScriptManager.Clear(); - } - - [TestCase("0.0.0", "6.0.0", "4.10.0", true)] - [TestCase("4.10.0", "6.0.0", "4.10.0", true)] - [TestCase("4.10.0", "4.11.4", "4.10.0", true)] - [TestCase("4.11.0", "4.11.4", "4.10.0", false)] - [TestCase("4.11.0", "6.0.0", "4.10.0", false)] - [TestCase("6.0.0", "6.0.0", "6.0.0", false)] //this is not in range because it is up to 6.0 but not including 6.0 - [TestCase("6.0.0", "6.0.0", "6.0.1", false)] - public void Test_Version_Range(string startVersion, string endVersion, string current, bool inRange) - { - var currVersionParts = current.Split('.').Select(int.Parse).ToArray(); - var currentVersion = new Version(currVersionParts[0], currVersionParts[1], currVersionParts[2]); - - var startVersionParts = startVersion.Split('.').Select(int.Parse).ToArray(); - var endVersionParts = endVersion.Split('.').Select(int.Parse).ToArray(); - - UpgradeScriptManager.AddUpgradeScript( - () => new UpgradeScript1(), - new VersionRange( - new Version(startVersionParts[0], startVersionParts[1], startVersionParts[2]), - new Version(endVersionParts[0], endVersionParts[1], endVersionParts[2]))); - - Assert.AreEqual(inRange, UpgradeScriptManager.HasScriptsForVersion(currentVersion)); - } - - [Test] - public void Test_Specific_Version() - { - var currentVersion = new Version(4, 10, 0); - - UpgradeScriptManager.AddUpgradeScript( - () => new UpgradeScript1(), - new VersionRange( - new Version(4, 10, 0))); - - Assert.IsTrue(UpgradeScriptManager.HasScriptsForVersion(currentVersion)); - Assert.IsFalse(UpgradeScriptManager.HasScriptsForVersion(new Version(4, 10, 11))); - Assert.IsFalse(UpgradeScriptManager.HasScriptsForVersion(new Version(4, 11, 0))); - } - - public class UpgradeScript1 : IUpgradeScript - { - public void Execute() - { - Debug.WriteLine("Executing!"); - } - } - - } -} diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 0634e58db7..c7bfb8cba0 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -63,7 +63,6 @@ - diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index b99a660c02..09d081e51f 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -289,13 +289,6 @@ loadStarterKits.ascx - - UpgradeScripts.ascx - ASPXCodeBehind - - - UpgradeScripts.ascx - editMacro.aspx @@ -425,7 +418,6 @@ UI.xml - diff --git a/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx b/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx deleted file mode 100644 index 2728a12f66..0000000000 --- a/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx +++ /dev/null @@ -1,14 +0,0 @@ -<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="UpgradeScripts.ascx.cs" Inherits="Umbraco.Web.UI.Install.Steps.UpgradeScripts" %> -
-
-

Upgrade scripts

-

- We need to run a few upgrade scripts, press Continue to execute these scripts and continue to the next step. -

-
- -
-
 
- Continue -
-
\ No newline at end of file diff --git a/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.cs b/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.cs deleted file mode 100644 index 0d94b30821..0000000000 --- a/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.UI; -using System.Web.UI.WebControls; -using Umbraco.Core.Configuration; -using umbraco.presentation.install; -using Umbraco.Web.Install.UpgradeScripts; - -namespace Umbraco.Web.UI.Install.Steps -{ - public partial class UpgradeScripts : System.Web.UI.UserControl - { - protected void Page_Load(object sender, EventArgs e) - { - - } - - protected void RunScripts(object sender, EventArgs e) - { - //run the scripts and then go to the next step - UpgradeScriptManager.ExecuteScriptsForVersion(GlobalSettings.GetConfigurationVersion()); - - Helper.RedirectToNextStep(Page); - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.designer.cs b/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.designer.cs deleted file mode 100644 index a55927fd35..0000000000 --- a/src/Umbraco.Web.UI/install/steps/UpgradeScripts.ascx.designer.cs +++ /dev/null @@ -1,24 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Umbraco.Web.UI.Install.Steps { - - - public partial class UpgradeScripts { - - /// - /// btnNext control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.LinkButton btnNext; - } -} diff --git a/src/Umbraco.Web/Install/UpgradeScripts/ContentPathFix.cs b/src/Umbraco.Web/Install/UpgradeScripts/ContentPathFix.cs deleted file mode 100644 index f52ae5078d..0000000000 --- a/src/Umbraco.Web/Install/UpgradeScripts/ContentPathFix.cs +++ /dev/null @@ -1,130 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using Umbraco.Core; -using Umbraco.Core.IO; -using umbraco.cms.businesslogic; -using umbraco.cms.businesslogic.web; - -namespace Umbraco.Web.Install.UpgradeScripts -{ - /// - /// An upgrade script to fix a moving issue in 4.10+ - /// http://issues.umbraco.org/issue/U4-1491 - /// - public class ContentPathFix : IUpgradeScript - { - private readonly StringBuilder _report = new StringBuilder(); - - public void Execute() - { - //return; - if (ApplicationContext.Current == null) return; - if (HasBeenFixed()) return; - Fix(); - WriteReport(); - } - - private void Fix() - { - AddReportLine("Starting fix paths script"); - - //fix content - AddReportLine("Fixing content"); - foreach (var d in Document.GetRootDocuments()) - { - FixPathsForChildren(d, content => ((Document)content).Children); - } - AddReportLine("Fixing content recycle bin"); - var contentRecycleBin = new RecycleBin(RecycleBin.RecycleBinType.Content); - foreach (var d in contentRecycleBin.Children) - { - FixPathsForChildren(new Document(d.Id), content => ((Document)content).Children); - } - - //fix media - AddReportLine("Fixing media"); - foreach (var d in global::umbraco.cms.businesslogic.media.Media.GetRootMedias()) - { - FixPathsForChildren(d, media => ((global::umbraco.cms.businesslogic.media.Media)media).Children); - } - AddReportLine("Fixing media recycle bin"); - var mediaRecycleBin = new RecycleBin(RecycleBin.RecycleBinType.Media); - foreach (var d in mediaRecycleBin.Children) - { - FixPathsForChildren(new global::umbraco.cms.businesslogic.media.Media(d.Id), media => ((global::umbraco.cms.businesslogic.media.Media)media).Children); - } - AddReportLine("Complete!"); - } - - /// - /// Returns true if this script has run based on a temp file written to - /// ~/App_Data/TEMP/FixPaths/report.txt - /// - /// - private bool HasBeenFixed() - { - return File.Exists(IOHelper.MapPath("~/App_Data/TEMP/FixPaths/report.txt")); - } - - /// - /// Creates the report - /// - private void WriteReport() - { - var filePath = IOHelper.MapPath("~/App_Data/TEMP/FixPaths/report.txt"); - Directory.CreateDirectory(Path.GetDirectoryName(filePath)); - using (var writer = File.CreateText(IOHelper.MapPath("~/App_Data/TEMP/FixPaths/report.txt"))) - { - writer.Write(_report.ToString()); - } - } - - /// - /// Recursively iterates over the children of the document and fixes the path - /// - /// - /// Callback to get the children of the conent item - /// - /// We cannot use GetDescendants() because that is based on the paths of documents and if they are invalid then - /// we cannot use that method. - /// - private void FixPathsForChildren(Content d, Func> getChildren) - { - AddReportLine("Fixing paths for children of " + d.Id); - foreach (var c in getChildren(d)) - { - FixPath(c); - if (c.HasChildren) - { - FixPathsForChildren(c, getChildren); - } - } - } - - /// - /// Check if the path is correct based on the document's parent if it is not correct, then fix it - /// - /// - private void FixPath(CMSNode d) - { - AddReportLine("Checking path for " + d.Id + ". Current = " + d.Path); - //check if the path is correct - var correctpath = d.Parent.Path + "," + d.Id.ToString(); - if (d.Path != correctpath) - { - AddReportLine(" INVALID PATH DETECTED. Path for " + d.Id + " changed to: " + d.Parent.Path + "," + d.Id.ToString()); - d.Path = correctpath; - d.Level = d.Parent.Level + 1; - } - } - - private void AddReportLine(string str) - { - _report.AppendLine(string.Format("{0} - " + str, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"))); - } - - - } -} \ No newline at end of file diff --git a/src/Umbraco.Web/Install/UpgradeScripts/IUpgradeScript.cs b/src/Umbraco.Web/Install/UpgradeScripts/IUpgradeScript.cs deleted file mode 100644 index 339dbd4ac2..0000000000 --- a/src/Umbraco.Web/Install/UpgradeScripts/IUpgradeScript.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Umbraco.Web.Install.UpgradeScripts -{ - internal interface IUpgradeScript - { - void Execute(); - } -} \ No newline at end of file diff --git a/src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptManager.cs b/src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptManager.cs deleted file mode 100644 index 472415598d..0000000000 --- a/src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptManager.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Umbraco.Core.Configuration; -using umbraco.DataLayer.Utility.Installer; - -namespace Umbraco.Web.Install.UpgradeScripts -{ - /// - /// Class used to register and execute upgrade scripts during install if they are required. - /// - internal static class UpgradeScriptManager - { - /// - /// Returns true if there are scripts to execute for the version - /// - /// - /// - public static bool HasScriptsForVersion(Version version) - { - return Scripts.Any(x => x.Item2.InRange(version)); - } - - /// - /// Executes all of the scripts for a database version - /// - /// - /// - public static void ExecuteScriptsForVersion(Version version) - { - var types = Scripts.Where(x => x.Item2.InRange(version)).Select(x => x.Item1); - foreach (var instance in types.Select(x => x())) - { - instance.Execute(); - } - } - - public static void AddUpgradeScript(Func script, VersionRange version) - { - Scripts.Add(new Tuple, VersionRange>(script, version)); - } - - ///// - ///// Adds a script to execute for a database version - ///// - ///// - ///// - //public static void AddUpgradeScript(string assemblyQualifiedTypeName, VersionRange version) - //{ - // AddUpgradeScript(new Lazy(() => Type.GetType(assemblyQualifiedTypeName)), version); - //} - - ///// - ///// Adds a script to execute for a database version - ///// - ///// - ///// - //public static void AddUpgradeScript(VersionRange version) - //{ - // AddUpgradeScript(new Lazy(() => typeof(T)), version); - //} - - /// - /// Used for testing - /// - internal static void Clear() - { - Scripts.Clear(); - } - - ///// - ///// Adds a script to execute for a database version - ///// - ///// - ///// - //public static void AddUpgradeScript(Lazy type, VersionRange version) - //{ - // Scripts.Add(new Tuple, VersionRange>(type, version)); - //} - - private static readonly List, VersionRange>> Scripts = new List, VersionRange>>(); - //private static readonly List, VersionRange>> Scripts = new List, VersionRange>>(); - } -} \ No newline at end of file diff --git a/src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptRegistrar.cs b/src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptRegistrar.cs deleted file mode 100644 index 611703b7d8..0000000000 --- a/src/Umbraco.Web/Install/UpgradeScripts/UpgradeScriptRegistrar.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using Umbraco.Core; - -namespace Umbraco.Web.Install.UpgradeScripts -{ - internal class UpgradeScriptRegistrar : IApplicationEventHandler - { - public void OnApplicationInitialized(UmbracoApplication httpApplication, ApplicationContext applicationContext) - { - //Add contnet path fixup for any version from 4.10 up to 4.11.4 - UpgradeScriptManager.AddUpgradeScript( - () => new ContentPathFix(), - new VersionRange( - new Version(4, 10), - new Version(4, 11, 4))); - } - - public void OnApplicationStarting(UmbracoApplication httpApplication, ApplicationContext applicationContext) - { - - } - - public void OnApplicationStarted(UmbracoApplication httpApplication, ApplicationContext applicationContext) - { - - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Web/Install/UpgradeScripts/VersionRange.cs b/src/Umbraco.Web/Install/UpgradeScripts/VersionRange.cs deleted file mode 100644 index adafd7691a..0000000000 --- a/src/Umbraco.Web/Install/UpgradeScripts/VersionRange.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; - -namespace Umbraco.Web.Install.UpgradeScripts -{ - internal class VersionRange - { - private readonly Version _specificVersion; - private readonly Version _startVersion; - private readonly Version _endVersion; - - public VersionRange(Version specificVersion) - { - _specificVersion = specificVersion; - } - - public VersionRange(Version startVersion, Version endVersion) - { - _startVersion = startVersion; - _endVersion = endVersion; - } - - /// - /// Checks if the versionCheck is in the range (in between) the start and end version - /// - /// - /// - /// - /// For example if our version range is 4.10 -> 4.11.4, we want to return true if the version being checked is: - /// greater than or equal to the start version but less than the end version. - /// - public bool InRange(Version versionCheck) - { - //if it is a specific version - if (_specificVersion != null) - return versionCheck == _specificVersion; - - return versionCheck >= _startVersion && versionCheck < _endVersion; - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 5c7a263b12..480b4eff6b 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -252,11 +252,6 @@ - - - - - @@ -334,7 +329,6 @@ ASPXCodeBehind - ASPXCodeBehind @@ -2028,7 +2022,9 @@ UserControl
- + + ASPXCodeBehind + diff --git a/src/Umbraco.Web/WebBootManager.cs b/src/Umbraco.Web/WebBootManager.cs index 915144efcf..b4aed9339d 100644 --- a/src/Umbraco.Web/WebBootManager.cs +++ b/src/Umbraco.Web/WebBootManager.cs @@ -9,7 +9,6 @@ using Umbraco.Core.Dictionary; using Umbraco.Core.Dynamics; using Umbraco.Core.PropertyEditors; using Umbraco.Web.Dictionary; -using Umbraco.Web.Install.UpgradeScripts; using Umbraco.Web.Media; using Umbraco.Web.Media.ThumbnailProviders; using Umbraco.Web.Models; @@ -91,7 +90,6 @@ namespace Umbraco.Web //add the internal types since we don't want to mark these public ApplicationEventsResolver.Current.AddType(); ApplicationEventsResolver.Current.AddType(); - ApplicationEventsResolver.Current.AddType(); //now we need to call the initialize methods ApplicationEventsResolver.Current.ApplicationEventHandlers diff --git a/src/Umbraco.Web/umbraco.presentation/install/default.aspx.cs b/src/Umbraco.Web/umbraco.presentation/install/default.aspx.cs index 16ceb1195f..479cb474c6 100644 --- a/src/Umbraco.Web/umbraco.presentation/install/default.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/install/default.aspx.cs @@ -136,7 +136,6 @@ namespace umbraco.presentation.install ics.Add(new install.steps.Definitions.Welcome()); ics.Add(new install.steps.Definitions.License()); ics.Add(new install.steps.Definitions.FilePermissions()); - ics.Add(new install.steps.Definitions.UpgradeScripts()); ics.Add(new install.steps.Definitions.Database()); ics.Add(new install.steps.Definitions.DefaultUser()); ics.Add(new install.steps.Definitions.Skinning()); diff --git a/src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/UpgradeScripts.cs b/src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/UpgradeScripts.cs deleted file mode 100644 index 57d4cf9d9b..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/install/steps/Definitions/UpgradeScripts.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; -using Umbraco.Core; -using Umbraco.Core.IO; -using Umbraco.Web.Install.UpgradeScripts; -using umbraco.DataLayer.Utility.Installer; -using umbraco.cms.businesslogic.installer; - -namespace umbraco.presentation.install.steps.Definitions -{ - internal class UpgradeScripts : InstallerStep - { - - - - public override string Alias - { - get { return "upgradeScripts"; } - } - - public override bool HideFromNavigation - { - get { return true; } - } - - /// - /// If there are no scripts for this version the skip - /// - /// - public override bool Completed() - { - var canConnect = CanConnectToDb(); - //if we cannot connect to the db, then we cannot run the script and most likely the database doesn't exist yet anyways. - if (!canConnect) return true; //skip - - //if the version is empty then it's probably a new installation, we cannot run scripts - if (GlobalSettings.CurrentVersion.IsNullOrWhiteSpace()) return true; //skip - var currentUmbVersion = Umbraco.Core.Configuration.GlobalSettings.GetConfigurationVersion(); - if (currentUmbVersion == null) - return true; //skip, could not get a version - - //check if we have upgrade script to run for this version - var hasScripts = UpgradeScriptManager.HasScriptsForVersion(currentUmbVersion); - return !hasScripts; - } - - public override string Name - { - get { return "Upgrade scripts"; } - } - - public override string UserControl - { - get { return SystemDirectories.Install + "/steps/UpgradeScripts.ascx"; } - } - - public override bool MoveToNextStepAutomaticly - { - get - { - return true; - } - } - - private bool CanConnectToDb() - { - try - { - var installer = BusinessLogic.Application.SqlHelper.Utility.CreateInstaller(); - var latest = installer.IsLatestVersion; - return true; //if we got this far, we can connect. - } - catch - { - return false; - } - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Web/umbraco.presentation/install/utills/p.aspx.cs b/src/Umbraco.Web/umbraco.presentation/install/utills/p.aspx.cs index 8576f12366..d7c99e7f47 100644 --- a/src/Umbraco.Web/umbraco.presentation/install/utills/p.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/install/utills/p.aspx.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; -using Umbraco.Web.Install.UpgradeScripts; using umbraco.DataLayer.Utility.Installer; using umbraco.DataLayer;