From 3d087dc07fd2d9ee4642c7318db46ad0795260a5 Mon Sep 17 00:00:00 2001 From: Shandem Date: Mon, 31 Aug 2009 15:05:47 +0000 Subject: [PATCH] DO NOT DOWNLOAD. DOWNLOAD LATEST STABLE FROM RELEASE TAB Did someone say recycle bin in media? Works but needs one more tweak. Data layer optimizations for Document & Media. Database upgrade scripts (not created for Vista DB yet). YOU NEED TO RUN THE INSTALLER TO UPGRADE THE DB, AND MAKE SURE YOU DELETE ALL FILES IN ~/data/ClientDependency [TFS Changeset #58546] --- UpgradeReadme.txt | 4 +- umbraco/cms/businesslogic/Content.cs | 22 +- umbraco/cms/businesslogic/ContentType.cs | 24 ++ umbraco/cms/businesslogic/RecycleBin.cs | 36 ++- umbraco/cms/businesslogic/media/Media.cs | 205 ++++++++++++++---- umbraco/cms/businesslogic/web/Document.cs | 179 ++++++++------- umbraco/cms/umbraco.cms.csproj | 2 +- .../SqlHelpers/MySql/MySqlInstaller.cs | 9 +- .../SqlHelpers/MySql/Sql/Version4_Upgrade.sql | 45 ++++ .../SqlHelpers/MySql/SqlResources.Designer.cs | 31 ++- .../SqlHelpers/MySql/SqlResources.resx | 3 + .../SqlServer/Sql/Version4_Upgrade.sql | 49 +++++ .../SqlServer/SqlResources.Designer.cs | 23 +- .../SqlHelpers/SqlServer/SqlResources.resx | 3 + .../SqlServer/SqlServerInstaller.cs | 7 +- .../Utility/Installer/DatabaseVersion.cs | 4 +- .../Installer/DefaultInstallerUtility.cs | 37 +++- umbraco/datalayer/umbraco.datalayer.csproj | 4 + .../presentation/umbraco.presentation.csproj | 9 +- .../umbraco/Trees/BaseMediaTree.cs | 183 ++++++++++++++++ .../umbraco/Trees/ContentRecycleBin.cs | 4 +- .../umbraco/Trees/MediaRecycleBin.cs | 86 ++++++++ .../presentation/umbraco/Trees/loadContent.cs | 6 +- .../presentation/umbraco/Trees/loadMedia.cs | 140 +++--------- .../umbraco/controls/TreeControl.ascx | 2 +- .../Application/UmbracoApplicationActions.js | 10 + .../umbraco_client/Tree/UmbracoTree.js | 25 ++- .../umbraco_client/Tree/UmbracoTree.min.js | 15 +- 28 files changed, 894 insertions(+), 273 deletions(-) create mode 100644 umbraco/datalayer/SqlHelpers/MySql/Sql/Version4_Upgrade.sql create mode 100644 umbraco/datalayer/SqlHelpers/SqlServer/Sql/Version4_Upgrade.sql create mode 100644 umbraco/presentation/umbraco/Trees/BaseMediaTree.cs create mode 100644 umbraco/presentation/umbraco/Trees/MediaRecycleBin.cs diff --git a/UpgradeReadme.txt b/UpgradeReadme.txt index 541b216fbe..e43efd7e37 100644 --- a/UpgradeReadme.txt +++ b/UpgradeReadme.txt @@ -27,4 +27,6 @@ to use the UmbracoClientPath setting * Removed all IFormHandler dependencies and therefore removed the idea of FormHandlers all together: - IFormHandler - /umbraco/formhandler.cs -- StandardFormHandlers \ No newline at end of file +- StandardFormHandlers + +* So far only minor database upgrade (not structure just data) \ No newline at end of file diff --git a/umbraco/cms/businesslogic/Content.cs b/umbraco/cms/businesslogic/Content.cs index 5394606841..447b92baee 100644 --- a/umbraco/cms/businesslogic/Content.cs +++ b/umbraco/cms/businesslogic/Content.cs @@ -56,9 +56,18 @@ namespace umbraco.cms.businesslogic /// protected Content(Guid id) : base(id) { } + /// + /// Sets up the ContentType property for this content item and sets the addition content properties manually. + /// If the ContentType property is not already set, then this will get the ContentType from Cache. + /// + /// + /// + /// + /// protected void InitializeContent(int InitContentType, Guid InitVersion, DateTime InitVersionDate, string InitContentTypeIcon) { - _contentType = ContentType.GetContentType(InitContentType); + if (_contentType == null) + _contentType = ContentType.GetContentType(InitContentType); _version = InitVersion; _versionDate = InitVersionDate; _contentTypeIcon = InitContentTypeIcon; @@ -117,11 +126,18 @@ namespace umbraco.cms.businesslogic base.Save(); } - - // This is for performance only (used in tree) /// /// The icon used in the tree - placed in this layer for performance reasons. /// + /// + /// This is here for performance reasons only. If the _contentTypeIcon is manually set + /// then a database call is not made to initialize the ContentType. + /// + /// The data layer has slightly changed in 4.1 so that for Document and Media, the ContentType + /// is automatically initialized with one SQL call when creating the documents/medias so using this + /// method or the ContentType.IconUrl property when accessing the icon from Media or Document + /// won't affect performance. + /// public string ContentTypeIcon { get diff --git a/umbraco/cms/businesslogic/ContentType.cs b/umbraco/cms/businesslogic/ContentType.cs index d3d8631de4..8d3053581b 100644 --- a/umbraco/cms/businesslogic/ContentType.cs +++ b/umbraco/cms/businesslogic/ContentType.cs @@ -111,6 +111,30 @@ namespace umbraco.cms.businesslogic { } + /// + /// Creates a new content type object manually + /// + /// + /// + /// + /// + /// + /// + /// This is like creating a ContentType node using optimized mode but this lets you set + /// all of the properties that are initialized normally from the database. + /// This is used for performance reasons. + /// + public ContentType(int id, string alias, string icon, string thumbnail, int? masterContentType) + : base(id, true) + { + _alias = alias; + _iconurl = icon; + _thumbnail = thumbnail; + if (masterContentType.HasValue) + m_masterContentType = masterContentType.Value; + } + + /// /// Gets the raw text. /// diff --git a/umbraco/cms/businesslogic/RecycleBin.cs b/umbraco/cms/businesslogic/RecycleBin.cs index 307df59984..6172fb2f3b 100644 --- a/umbraco/cms/businesslogic/RecycleBin.cs +++ b/umbraco/cms/businesslogic/RecycleBin.cs @@ -6,13 +6,42 @@ using umbraco.DataLayer; namespace umbraco.cms.businesslogic { + public class RecycleBin : CMSNode { + /// + /// The types of Recycle Bins. + /// + /// + /// Each enum item represents the integer value of the node Id of the recycle bin in the database. + /// + public enum RecycleBinType + { + Content = -20, + Media = -21 + } + private Guid _nodeObjectType; - public RecycleBin(Guid nodeObjectType) : base(-20) { - _nodeObjectType = nodeObjectType; - } + /// + /// Constructor to create a new recycle bin + /// + /// + /// + public RecycleBin(Guid nodeObjectType, RecycleBinType type) + : base((int)type) + { + _nodeObjectType = nodeObjectType; + } + + /// + /// Old constructor to create a content recycle bin + /// + /// + [Obsolete("Use the other constructors instead")] + public RecycleBin(Guid nodeObjectType) + : this(nodeObjectType, RecycleBinType.Content) { } + /// /// If I smell, I'm not empty @@ -53,6 +82,7 @@ namespace umbraco.cms.businesslogic /// Get the number of items in the Recycle Bin /// /// The number of all items in the Recycle Bin + [Obsolete("Create a RecycleBin object to get the count per recycle bin type")] public static int Count() { return SqlHelper.ExecuteScalar("select count(id) from umbracoNode where path like '%,-20,%'"); diff --git a/umbraco/cms/businesslogic/media/Media.cs b/umbraco/cms/businesslogic/media/Media.cs index c259496b39..590389448c 100644 --- a/umbraco/cms/businesslogic/media/Media.cs +++ b/umbraco/cms/businesslogic/media/Media.cs @@ -1,4 +1,9 @@ using System; +using System.IO; +using umbraco.BusinessLogic.Actions; +using umbraco.DataLayer; +using System.Collections; +using System.Collections.Generic; namespace umbraco.cms.businesslogic.media { @@ -9,6 +14,19 @@ namespace umbraco.cms.businesslogic.media /// public class Media : Content { + private const string m_SQLOptimizedChildren = @" + select + count(children.id) as children, umbracoNode.id, umbracoNode.uniqueId, umbracoNode.level, umbracoNode.parentId, umbracoNode.path, umbracoNode.sortOrder, umbracoNode.createDate, umbracoNode.nodeUser, umbracoNode.text, + cmsContentType.icon, cmsContentType.alias, cmsContentType.thumbnail, cmsContentType.description, cmsContentType.masterContentType, cmsContentType.nodeId as contentTypeId + from umbracoNode + left join umbracoNode children on children.parentId = umbracoNode.id + inner join cmsContent on cmsContent.nodeId = umbracoNode.id + inner join cmsContentType on cmsContentType.nodeId = cmsContent.contentType + where {0} + group by umbracoNode.id, umbracoNode.uniqueId, umbracoNode.level, umbracoNode.parentId, umbracoNode.path, umbracoNode.sortOrder, umbracoNode.createDate, umbracoNode.nodeUser, umbracoNode.text, + cmsContentType.icon, cmsContentType.alias, cmsContentType.thumbnail, cmsContentType.description, cmsContentType.masterContentType, cmsContentType.nodeId + order by {1}"; + /// /// Contructs a media object given the Id /// @@ -24,6 +42,11 @@ namespace umbraco.cms.businesslogic.media public Media(Guid id) : base(id) {} + public Media(int id, bool noSetup) + : base(id, noSetup) + { + + } /// /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility @@ -98,13 +121,65 @@ namespace umbraco.cms.businesslogic.media { get { - BusinessLogic.console.IconI[] tmp = base.Children; - Media[] retval = new Media[tmp.Length]; - for (int i = 0; i < tmp.Length; i++) retval[i] = new Media(tmp[i].UniqueId); - return retval; + //SD: Removed old, non-optimized method! + //BusinessLogic.console.IconI[] tmp = base.Children; + //Media[] retval = new Media[tmp.Length]; + //for (int i = 0; i < tmp.Length; i++) retval[i] = new Media(tmp[i].UniqueId); + //return retval; + + //return refactored optimized method + return Media.GetChildrenForTree(this.Id).ToArray(); } } + public static List GetChildrenForTree(int nodeId) + { + List tmp = new List(); + using (IRecordsReader dr = + SqlHelper.ExecuteReader( + string.Format(m_SQLOptimizedChildren, "umbracoNode.parentID = @parentId", "umbracoNode.sortOrder"), + SqlHelper.CreateParameter("@parentId", nodeId))) + { + + while (dr.Read()) + { + Media d = new Media(dr.GetInt("id"), true); + bool _hc = false; + if (dr.GetInt("children") > 0) + _hc = true; + int? masterContentType = null; + if (!dr.IsNull("masterContentType")) + masterContentType = dr.GetInt("masterContentType"); + d.SetupMediaForTree(dr.GetGuid("uniqueId") + , dr.GetShort("level") + , dr.GetInt("parentId") + , dr.GetInt("nodeUser") + , dr.GetString("path") + , dr.GetString("text") + , dr.GetDateTime("createDate") + , dr.GetString("icon") + , _hc + , dr.GetString("alias") + , dr.GetString("thumbnail") + , dr.GetString("description") + , masterContentType + , dr.GetInt("contentTypeId")); + tmp.Add(d); + } + + } + return tmp; + } + + private void SetupMediaForTree(Guid uniqueId, int level, int parentId, int user, string path, + string text, DateTime createDate, string icon, bool hasChildren, string contentTypeAlias, string contentTypeThumb, + string contentTypeDesc, int? masterContentType, int contentTypeId) + { + SetupNodeForTree(uniqueId, _objectType, level, parentId, user, path, text, createDate, hasChildren); + ContentType = new ContentType(contentTypeId, contentTypeAlias, icon, contentTypeThumb, masterContentType); + ContentTypeIcon = icon; + } + /// /// Deletes all medias of the given type, used when deleting a mediatype /// @@ -128,48 +203,72 @@ namespace umbraco.cms.businesslogic.media /// new public void delete() { - DeleteEventArgs e = new DeleteEventArgs(); + // Check for recyle bin + if (!Path.Contains("," + RecycleBin.RecycleBinType.Media.ToString() + ",")) + { + MoveToTrashEventArgs e = new MoveToTrashEventArgs(); + FireBeforeMoveToTrash(e); - FireBeforeDelete(e); + if (!e.Cancel) + { + Move((int)RecycleBin.RecycleBinType.Media); - if (!e.Cancel) { - foreach (Media d in this.Children) { - d.delete(); - } + //TODO: Now that we've moved it to trash, we need to move the actual files so they are no longer accessible + //from the original URL. - // Remove all files - interfaces.IDataType uploadField = new cms.businesslogic.datatype.controls.Factory().GetNewObject(new Guid("5032a6e6-69e3-491d-bb28-cd31cd11086c")); - foreach (cms.businesslogic.property.Property p in this.getProperties) - if (p.PropertyType.DataTypeDefinition.DataType.Id == uploadField.Id && - p.Value.ToString() != "" && - System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath(p.Value.ToString())) - ) - { - - System.IO.File.Delete(System.Web.HttpContext.Current.Server.MapPath(p.Value.ToString())); + FireAfterMoveToTrash(e); + } + } + else + { + DeleteEventArgs e = new DeleteEventArgs(); - string file = p.Value.ToString(); - string extension = ((string)file.Substring(file.LastIndexOf(".") + 1, file.Length - file.LastIndexOf(".") - 1)).ToLower(); - - //check for thumbnail - if (",jpeg,jpg,gif,bmp,png,tiff,tif,".IndexOf("," + extension + ",") > -1) - { - string thumbnailfile = file.Replace("." + extension, "_thumb"); + FireBeforeDelete(e); - if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath(thumbnailfile + ".jpg"))) - System.IO.File.Delete(System.Web.HttpContext.Current.Server.MapPath(thumbnailfile + ".jpg")); + if (!e.Cancel) + { + foreach (Media d in this.Children) + { + d.delete(); + } - //should also delete extra thumbnails - } + // Remove all files + interfaces.IDataType uploadField = new cms.businesslogic.datatype.controls.Factory().GetNewObject(new Guid("5032a6e6-69e3-491d-bb28-cd31cd11086c")); + foreach (cms.businesslogic.property.Property p in this.getProperties) + { + FileInfo mediaFile = new FileInfo(System.Web.HttpContext.Current.Server.MapPath(p.Value.ToString())); - } + if (p.PropertyType.DataTypeDefinition.DataType.Id == uploadField.Id + && p.Value.ToString() != "" + && mediaFile.Exists) + { - - - base.delete(); + mediaFile.Delete(); - FireAfterDelete(e); - } + string file = p.Value.ToString(); + string extension = ((string)file.Substring(file.LastIndexOf(".") + 1, file.Length - file.LastIndexOf(".") - 1)).ToLower(); + + //check for thumbnail + if (",jpeg,jpg,gif,bmp,png,tiff,tif,".IndexOf("," + extension + ",") > -1) + { + string thumbnailfile = file.Replace("." + extension, "_thumb"); + + if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath(thumbnailfile + ".jpg"))) + System.IO.File.Delete(System.Web.HttpContext.Current.Server.MapPath(thumbnailfile + ".jpg")); + + //should also delete extra thumbnails + } + + } + + } + + base.delete(); + + FireAfterDelete(e); + } + } + } @@ -252,6 +351,38 @@ namespace umbraco.cms.businesslogic.media if (AfterDelete != null) AfterDelete(this, e); } + + /// + /// The Move to trash event handler + /// + public delegate void MoveToTrashEventHandler(Media sender, MoveToTrashEventArgs e); + /// + /// Occurs when [before delete]. + /// + public static event MoveToTrashEventHandler BeforeMoveToTrash; + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void FireBeforeMoveToTrash(MoveToTrashEventArgs e) + { + if (BeforeMoveToTrash != null) + BeforeMoveToTrash(this, e); + } + + /// + /// Occurs when [after move to trash]. + /// + public static event MoveToTrashEventHandler AfterMoveToTrash; + /// + /// Fires the after move to trash. + /// + /// The instance containing the event data. + protected virtual void FireAfterMoveToTrash(MoveToTrashEventArgs e) + { + if (AfterMoveToTrash != null) + AfterMoveToTrash(this, e); + } } } diff --git a/umbraco/cms/businesslogic/web/Document.cs b/umbraco/cms/businesslogic/web/Document.cs index 682e1527d3..0a168e06fb 100644 --- a/umbraco/cms/businesslogic/web/Document.cs +++ b/umbraco/cms/businesslogic/web/Document.cs @@ -27,6 +27,54 @@ namespace umbraco.cms.businesslogic.web /// public class Document : Content { + private const string m_SQLOptimizedSingle = @" + Select + (select count(id) from umbracoNode where parentId = @id) as Children, + (select Count(published) as tmp from cmsDocument where published = 1 And nodeId = @id) 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 + where + {0} + order by + {1} + "; + private const string m_SQLOptimizedChildren = @" + select + count(children.id) as children, umbracoNode.id, umbracoNode.uniqueId, umbracoNode.level, umbracoNode.parentId, cmsDocument.documentUser, umbracoNode.path, umbracoNode.sortOrder, coalesce(publishCheck.published,0) as published, umbracoNode.createDate, cmsDocument.text, cmsDocument.updateDate, cmsContentVersion.versionDate, cmsContentType.icon, cmsContentType.alias, cmsContentType.thumbnail, cmsContentType.description, cmsContentType.masterContentType, cmsContentType.nodeId as contentTypeId + from umbracoNode + left join umbracoNode children on children.parentId = umbracoNode.id + inner join cmsContent on cmsContent.nodeId = umbracoNode.id + inner join cmsContentType on cmsContentType.nodeId = cmsContent.contentType + inner join (select contentId, max(versionDate) AS versionDate from cmsContentVersion + inner join umbracoNode on umbracoNode.id = cmsContentVersion.contentId and umbracoNode.parentId = @parentId + group by contentId) AS temp + on temp.contentId = cmsContent.nodeId + inner join cmsContentVersion on cmsContentVersion.contentId = temp.contentId and cmsContentVersion.versionDate = temp.versionDate + inner join cmsDocument on cmsDocument.versionId = cmsContentversion.versionId + left join cmsDocument publishCheck on publishCheck.nodeId = cmsContent.nodeID and publishCheck.published = 1 + where {0} + group by umbracoNode.id, umbracoNode.uniqueId, umbracoNode.level, umbracoNode.parentId, cmsDocument.documentUser, umbracoNode.path, umbracoNode.sortOrder, coalesce(publishCheck.published,0), umbracoNode.createDate, cmsDocument.text, cmsDocument.updateDate, cmsContentVersion.versionDate, cmsContentType.icon, cmsContentType.alias, cmsContentType.thumbnail, cmsContentType.description, cmsContentType.masterContentType, cmsContentType.nodeId + order by {1} + "; + public static Guid _objectType = new Guid("c66ba18e-eaf3-4cff-8a22-41b16d66a972"); private DateTime _updated; private DateTime _release; @@ -317,10 +365,7 @@ namespace umbraco.cms.businesslogic.web /// true if the data shouldn't loaded from the db public Document(Guid id, bool noSetup) : base(id) { - //SD: added the following as noSetup actually didn't do anything!?! - if (!noSetup) - setupDocument(); //This should call the below method, but for some reason no inheritance is happening here....? - //setupNode(); + } /// @@ -370,39 +415,9 @@ namespace umbraco.cms.businesslogic.web if (OptimizedMode) { + using (IRecordsReader dr = - SqlHelper.ExecuteReader( - @" - Select - (select count(id) from umbracoNode where parentId = @id) as Children, - (select Count(published) as tmp from cmsDocument where published = 1 And nodeId = @id) as Published, - cmsContentVersion.VersionId, - cmsContentVersion.versionDate, - cmsContent.ContentType, - contentTypeNode.uniqueId as ContentTypeGuid, - cmsContentType.alias, - cmsContentType.icon, - 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 - where - umbracoNode.id = @id - order by - cmsContentVersion.id desc - ", + SqlHelper.ExecuteReader(string.Format(m_SQLOptimizedSingle, "umbracoNode.id = @id", "cmsContentVersion.id desc"), SqlHelper.CreateParameter("@id", id))) { if (dr.Read()) @@ -411,13 +426,26 @@ namespace umbraco.cms.businesslogic.web bool _hc = false; if (dr.GetInt("children") > 0) _hc = true; - SetupDocumentForTree(dr.GetGuid("uniqueId"), dr.GetShort("level"), - dr.GetInt("parentId"), dr.GetInt("documentUser"), - dr.GetBoolean("published"), - dr.GetString("path"), dr.GetString("text"), - dr.GetDateTime("createDate"), - dr.GetDateTime("updateDate"), - dr.GetDateTime("versionDate"), dr.GetString("icon"), _hc); + int? masterContentType = null; + if (!dr.IsNull("masterContentType")) + masterContentType = dr.GetInt("masterContentType"); + SetupDocumentForTree(dr.GetGuid("uniqueId") + , dr.GetShort("level") + , dr.GetInt("parentId") + , dr.GetInt("documentUser") + , dr.GetBoolean("published") + , dr.GetString("path") + , dr.GetString("text") + , dr.GetDateTime("createDate") + , dr.GetDateTime("updateDate") + , dr.GetDateTime("versionDate") + , dr.GetString("icon") + , _hc + , dr.GetString("alias") + , dr.GetString("thumbnail") + , dr.GetString("description") + , masterContentType + , dr.GetInt("contentTypeId")); // initialize content object InitializeContent(dr.GetInt("ContentType"), dr.GetGuid("versionId"), @@ -818,10 +846,13 @@ namespace umbraco.cms.businesslogic.web { get { - IconI[] tmp = base.Children; - Document[] retval = new Document[tmp.Length]; - for (int i = 0; i < tmp.Length; i++) retval[i] = new Document(tmp[i].Id); - return retval; + //SD: Removed old, non-optimized method! + //IconI[] tmp = base.Children; + //Document[] retval = new Document[tmp.Length]; + //for (int i = 0; i < tmp.Length; i++) retval[i] = new Document(tmp[i].Id); + //return retval; + + return Document.GetChildrenForTree(this.Id); } } @@ -1121,25 +1152,7 @@ namespace umbraco.cms.businesslogic.web ArrayList tmp = new ArrayList(); using (IRecordsReader dr = SqlHelper.ExecuteReader( -// Ruben Verborgh: Rewrote this without temporary table, but we really should make a view of this - @" -select - count(children.id) as children, umbracoNode.id, umbracoNode.uniqueId, umbracoNode.level, umbracoNode.parentId, cmsDocument.documentUser, umbracoNode.path, umbracoNode.sortOrder, coalesce(publishCheck.published,0) as published, umbracoNode.createDate, cmsDocument.text, cmsDocument.updateDate, cmsContentVersion.versionDate, cmsContentType.icon -from umbracoNode -left join umbracoNode children on children.parentId = umbracoNode.id -inner join cmsContent on cmsContent.nodeId = umbracoNode.id -inner join cmsContentType on cmsContentType.nodeId = cmsContent.contentType -inner join (select contentId, max(versionDate) AS versionDate from cmsContentVersion - inner join umbracoNode on umbracoNode.id = cmsContentVersion.contentId and umbracoNode.parentId = @parentId - group by contentId) AS temp -on temp.contentId = cmsContent.nodeId -inner join cmsContentVersion on cmsContentVersion.contentId = temp.contentId and cmsContentVersion.versionDate = temp.versionDate -inner join cmsDocument on cmsDocument.versionId = cmsContentversion.versionId -left join cmsDocument publishCheck on publishCheck.nodeId = cmsContent.nodeID and publishCheck.published = 1 -where umbracoNode.parentID = @parentId -group by umbracoNode.id, umbracoNode.uniqueId, umbracoNode.level, umbracoNode.parentId, cmsDocument.documentUser, umbracoNode.path, umbracoNode.sortOrder, coalesce(publishCheck.published,0), umbracoNode.createDate, cmsDocument.text, cmsDocument.updateDate, cmsContentVersion.versionDate, cmsContentType.icon -order by umbracoNode.sortOrder -", + string.Format(m_SQLOptimizedChildren, "umbracoNode.parentID = @parentId", "umbracoNode.sortOrder"), SqlHelper.CreateParameter("@parentId", NodeId))) { while (dr.Read()) @@ -1148,14 +1161,26 @@ order by umbracoNode.sortOrder bool _hc = false; if (dr.GetInt("children") > 0) _hc = true; - d.SetupDocumentForTree(dr.GetGuid("uniqueId"), dr.GetShort("level"), - dr.GetInt("parentId"), - dr.GetInt("documentUser"), - (dr.GetInt("published")==1), - dr.GetString("path"), dr.GetString("text"), - dr.GetDateTime("createDate"), - dr.GetDateTime("updateDate"), - dr.GetDateTime("versionDate"), dr.GetString("icon"), _hc); + int? masterContentType = null; + if (!dr.IsNull("masterContentType")) + masterContentType = dr.GetInt("masterContentType"); + d.SetupDocumentForTree(dr.GetGuid("uniqueId") + , dr.GetShort("level") + , dr.GetInt("parentId") + , dr.GetInt("documentUser") + , (dr.GetInt("published")==1) + , dr.GetString("path") + , dr.GetString("text") + , dr.GetDateTime("createDate") + , dr.GetDateTime("updateDate") + , dr.GetDateTime("versionDate") + , dr.GetString("icon") + , _hc + , dr.GetString("alias") + , dr.GetString("thumbnail") + , dr.GetString("description") + , masterContentType + , dr.GetInt("contentTypeId")); tmp.Add(d); } } @@ -1170,13 +1195,15 @@ order by umbracoNode.sortOrder private void SetupDocumentForTree(Guid uniqueId, int level, int parentId, int user, bool publish, string path, string text, DateTime createDate, DateTime updateDate, - DateTime versionDate, string icon, bool hasChildren) + DateTime versionDate, string icon, bool hasChildren, string contentTypeAlias, string contentTypeThumb, + string contentTypeDesc, int? masterContentType, int contentTypeId) { SetupNodeForTree(uniqueId, _objectType, level, parentId, user, path, text, createDate, hasChildren); _published = publish; _updated = updateDate; - ContentTypeIcon = icon; + ContentType = new ContentType(contentTypeId, contentTypeAlias, icon, contentTypeThumb, masterContentType); + ContentTypeIcon = icon; VersionDate = versionDate; } diff --git a/umbraco/cms/umbraco.cms.csproj b/umbraco/cms/umbraco.cms.csproj index a0567e7f26..9a1ac1dceb 100644 --- a/umbraco/cms/umbraco.cms.csproj +++ b/umbraco/cms/umbraco.cms.csproj @@ -244,7 +244,7 @@ Code - + Code diff --git a/umbraco/datalayer/SqlHelpers/MySql/MySqlInstaller.cs b/umbraco/datalayer/SqlHelpers/MySql/MySqlInstaller.cs index 79a50c8456..bf9c379273 100644 --- a/umbraco/datalayer/SqlHelpers/MySql/MySqlInstaller.cs +++ b/umbraco/datalayer/SqlHelpers/MySql/MySqlInstaller.cs @@ -25,6 +25,7 @@ namespace umbraco.DataLayer.SqlHelpers.MySql /// The specifications to determine the database version. private static readonly VersionSpecs[] m_VersionSpecs = new VersionSpecs[] { + new VersionSpecs("id","umbracoNode", "-21", DatabaseVersion.Version4_1), new VersionSpecs("action","umbracoAppTree",DatabaseVersion.Version4), new VersionSpecs("version()","",DatabaseVersion.None) }; @@ -39,7 +40,13 @@ namespace umbraco.DataLayer.SqlHelpers.MySql /// true if the installer can upgrade the data source; otherwise, false. /// /// Empty data sources can't be upgraded, just installed. - public override bool CanUpgrade { get { return false; } } + public override bool CanUpgrade + { + get + { + return CurrentVersion == DatabaseVersion.Version4; + } + } #endregion diff --git a/umbraco/datalayer/SqlHelpers/MySql/Sql/Version4_Upgrade.sql b/umbraco/datalayer/SqlHelpers/MySql/Sql/Version4_Upgrade.sql new file mode 100644 index 0000000000..321ddec245 --- /dev/null +++ b/umbraco/datalayer/SqlHelpers/MySql/Sql/Version4_Upgrade.sql @@ -0,0 +1,45 @@ +/******************************************************************************************* + + + + + + + + Umbraco database installation script for SQL Server (upgrade from Umbraco 4.0.x) + +IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT + + Database version: 4.1.0.0 + + Please increment this version number if ANY change is made to this script, + so compatibility with scripts for other database systems can be verified easily. + The first 3 digits depict the Umbraco version, the last digit is the database version. + (e.g. version 4.0.0.3 means "Umbraco version 4.0.0, database version 3") + + Check-in policy: only commit this script if + * you ran the Umbraco installer completely; + * you ran it on the targetted database system; + * you ran the Runway and Module installations; + * you were able to browse the Boost site; + * you were able to open the Umbraco administration panel; + * you have documented the code change in this script; + * you have incremented the version number in this script. + +IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT + + + + + + + +********************************************************************************************/ + +/* INSERT NEW MEDIA RECYCLE BIN NODE */ +INSERT INTO umbracoNode (id, trashed, parentID, nodeUser, level, path, sortOrder, uniqueID, text, nodeObjectType, createDate) +VALUES (-21, 0, -1, 0, 0, '-1,-21', 0, 'BF7C7CBC-952F-4518-97A2-69E9C7B33842', 'Recycle Bin', 'CF3D8E34-1C1C-41e9-AE56-878B57B32113', '2009/08/28 00:28:28.920') +; +INSERT IGNORE INTO umbracoAppTree (treeSilent, treeInitialize, treeSortOrder, appAlias, treeAlias, treeTitle, treeIconClosed, treeIconOpen, treeHandlerAssembly, treeHandlerType) +VALUES (0, 0, 0, 'media', 'mediaRecycleBin', 'RecycleBin', 'folder.gif', 'folder_o.gif', 'umbraco', 'cms.presentation.Trees.MediaRecycleBin') +; \ No newline at end of file diff --git a/umbraco/datalayer/SqlHelpers/MySql/SqlResources.Designer.cs b/umbraco/datalayer/SqlHelpers/MySql/SqlResources.Designer.cs index 1662c1fdc0..ad4dcb8e65 100644 --- a/umbraco/datalayer/SqlHelpers/MySql/SqlResources.Designer.cs +++ b/umbraco/datalayer/SqlHelpers/MySql/SqlResources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:2.0.50727.1433 +// Runtime Version:2.0.50727.3082 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -73,16 +73,41 @@ namespace umbraco.DataLayer.SqlHelpers.MySql { /// ///IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT /// - /// Database version: 4.0.0.5 + /// Database version: 4.0.0.12 /// /// Please increment this version number if ANY change is made to this script, /// so compatibility with scripts for other database systems can be verified easily. - /// The first 3 digits depict the Umbraco version, t [rest of string was truncated]";. + /// The first 3 digits depict the Umbraco version, [rest of string was truncated]";. /// internal static string Total { get { return ResourceManager.GetString("Total", resourceCulture); } } + + /// + /// Looks up a localized string similar to /******************************************************************************************* + /// + /// + /// + /// + /// + /// + /// + /// Umbraco database installation script for SQL Server (upgrade from Umbraco 4.0.x) + /// + ///IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT + /// + /// Database version: 4.1.0.0 + /// + /// Please increment this version number if ANY change is made to this script, + /// so compatibility with scripts for other database systems can be verified easily. + /// The first 3 di [rest of string was truncated]";. + /// + internal static string Version4_Upgrade { + get { + return ResourceManager.GetString("Version4_Upgrade", resourceCulture); + } + } } } diff --git a/umbraco/datalayer/SqlHelpers/MySql/SqlResources.resx b/umbraco/datalayer/SqlHelpers/MySql/SqlResources.resx index d813a13b07..c121124eb7 100644 --- a/umbraco/datalayer/SqlHelpers/MySql/SqlResources.resx +++ b/umbraco/datalayer/SqlHelpers/MySql/SqlResources.resx @@ -121,4 +121,7 @@ sql\total.sql;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + + sql\version4_upgrade.sql;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + \ No newline at end of file diff --git a/umbraco/datalayer/SqlHelpers/SqlServer/Sql/Version4_Upgrade.sql b/umbraco/datalayer/SqlHelpers/SqlServer/Sql/Version4_Upgrade.sql new file mode 100644 index 0000000000..4c0ecbfcf5 --- /dev/null +++ b/umbraco/datalayer/SqlHelpers/SqlServer/Sql/Version4_Upgrade.sql @@ -0,0 +1,49 @@ +/******************************************************************************************* + + + + + + + + Umbraco database installation script for SQL Server (upgrade from Umbraco 4.0.x) + +IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT + + Database version: 4.1.0.0 + + Please increment this version number if ANY change is made to this script, + so compatibility with scripts for other database systems can be verified easily. + The first 3 digits depict the Umbraco version, the last digit is the database version. + (e.g. version 4.0.0.3 means "Umbraco version 4.0.0, database version 3") + + Check-in policy: only commit this script if + * you ran the Umbraco installer completely; + * you ran it on the targetted database system; + * you ran the Runway and Module installations; + * you were able to browse the Boost site; + * you were able to open the Umbraco administration panel; + * you have documented the code change in this script; + * you have incremented the version number in this script. + +IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT + + + + + + + +********************************************************************************************/ + +/* INSERT NEW MEDIA RECYCLE BIN NODE */ +SET IDENTITY_INSERT [umbracoNode] ON +INSERT INTO umbracoNode (id, trashed, parentID, nodeUser, level, path, sortOrder, uniqueID, text, nodeObjectType) +VALUES (-21, 0, -1, 0, 0, '-1,-21', 0, 'BF7C7CBC-952F-4518-97A2-69E9C7B33842', 'Recycle Bin', 'CF3D8E34-1C1C-41e9-AE56-878B57B32113') +SET IDENTITY_INSERT [umbracoNode] OFF +; +/* Add the mediaRecycleBin tree type */ +IF NOT EXISTS (SELECT treeAlias FROM umbracoAppTree WHERE treeAlias='mediaRecycleBin') +INSERT INTO umbracoAppTree (treeSilent, treeInitialize, treeSortOrder, appAlias, treeAlias, treeTitle, treeIconClosed, treeIconOpen, treeHandlerAssembly, treeHandlerType) +VALUES (0, 0, 0, 'media', 'mediaRecycleBin', 'RecycleBin', 'folder.gif', 'folder_o.gif', 'umbraco', 'cms.presentation.Trees.MediaRecycleBin') +; \ No newline at end of file diff --git a/umbraco/datalayer/SqlHelpers/SqlServer/SqlResources.Designer.cs b/umbraco/datalayer/SqlHelpers/SqlServer/SqlResources.Designer.cs index 811a8ae518..c3195162de 100644 --- a/umbraco/datalayer/SqlHelpers/SqlServer/SqlResources.Designer.cs +++ b/umbraco/datalayer/SqlHelpers/SqlServer/SqlResources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:2.0.50727.1433 +// Runtime Version:2.0.50727.3082 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -73,11 +73,11 @@ namespace umbraco.DataLayer.SqlHelpers.SqlServer { /// ///IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT /// - /// Database version: 4.0.0.5 + /// Database version: 4.0.0.12 /// /// Please increment this version number if ANY change is made to this script, /// so compatibility with scripts for other database systems can be verified easily. - /// The first 3 digits depict the Umbraco versi [rest of string was truncated]";. + /// The first 3 digits depict the Umbraco vers [rest of string was truncated]";. /// internal static string Total { get { @@ -98,16 +98,29 @@ namespace umbraco.DataLayer.SqlHelpers.SqlServer { /// ///IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT /// - /// Database version: 4.0.0.5 + /// Database version: 4.0.0.12 /// /// Please increment this version number if ANY change is made to this script, /// so compatibility with scripts for other database systems can be verified easily. - /// The first 3 digi [rest of string was truncated]";. + /// The first 3 dig [rest of string was truncated]";. /// internal static string Version3_Upgrade { get { return ResourceManager.GetString("Version3_Upgrade", resourceCulture); } } + + /// + /// Looks up a localized string similar to --INSERT NEW MEDIA RECYCLE BIN NODE + ///SET IDENTITY_INSERT umbracoNode ON + ///INSERT INTO umbracoNode (id, trashed, parentID, nodeUser, level, path, sortOrder, uniqueID, text, nodeObjectType) + ///VALUES (-20, 0, -1, 0, 0, '-1,-20', 0, '0F582A79-1E41-4CF0-BFA0-76340651891A', 'Recycle Bin', '01BB7FF2-24DC-4C0C-95A2-C24EF72BBAC8') + ///SET IDENTITY_INSERT OFF. + /// + internal static string Version4_Upgrade { + get { + return ResourceManager.GetString("Version4_Upgrade", resourceCulture); + } + } } } diff --git a/umbraco/datalayer/SqlHelpers/SqlServer/SqlResources.resx b/umbraco/datalayer/SqlHelpers/SqlServer/SqlResources.resx index 0563f0ff27..a232781057 100644 --- a/umbraco/datalayer/SqlHelpers/SqlServer/SqlResources.resx +++ b/umbraco/datalayer/SqlHelpers/SqlServer/SqlResources.resx @@ -124,4 +124,7 @@ sql\version3_upgrade.sql;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + + sql\version4_upgrade.sql;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + \ No newline at end of file diff --git a/umbraco/datalayer/SqlHelpers/SqlServer/SqlServerInstaller.cs b/umbraco/datalayer/SqlHelpers/SqlServer/SqlServerInstaller.cs index 1703fe8881..c3c5ad8021 100644 --- a/umbraco/datalayer/SqlHelpers/SqlServer/SqlServerInstaller.cs +++ b/umbraco/datalayer/SqlHelpers/SqlServer/SqlServerInstaller.cs @@ -20,11 +20,12 @@ namespace umbraco.DataLayer.SqlHelpers.SqlServer #region Private Constants /// The latest database version this installer supports. - private const DatabaseVersion LatestVersionSupported = DatabaseVersion.Version4; + private const DatabaseVersion LatestVersionSupported = DatabaseVersion.Version4_1; /// The specifications to determine the database version. private static readonly VersionSpecs[] m_VersionSpecs = new VersionSpecs[] { - new VersionSpecs("action","umbracoAppTree",DatabaseVersion.Version4), + new VersionSpecs("id","umbracoNode", "-21", DatabaseVersion.Version4_1), + new VersionSpecs("action","umbracoAppTree",DatabaseVersion.Version4), new VersionSpecs("description","cmsContentType",DatabaseVersion.Version3), new VersionSpecs("id","sysobjects",DatabaseVersion.None) }; @@ -43,7 +44,7 @@ namespace umbraco.DataLayer.SqlHelpers.SqlServer { get { - return CurrentVersion == DatabaseVersion.Version3; + return CurrentVersion == DatabaseVersion.Version4; } } diff --git a/umbraco/datalayer/Utility/Installer/DatabaseVersion.cs b/umbraco/datalayer/Utility/Installer/DatabaseVersion.cs index 7b80a32fd7..e2f34fab94 100644 --- a/umbraco/datalayer/Utility/Installer/DatabaseVersion.cs +++ b/umbraco/datalayer/Utility/Installer/DatabaseVersion.cs @@ -20,6 +20,8 @@ namespace umbraco.DataLayer.Utility.Installer /// Umbraco version 3.0. Version3, /// Umbraco version 4.0. - Version4 + Version4, + /// Umbraco version 4.1. + Version4_1 } } diff --git a/umbraco/datalayer/Utility/Installer/DefaultInstallerUtility.cs b/umbraco/datalayer/Utility/Installer/DefaultInstallerUtility.cs index 40449c1668..d1019476e6 100644 --- a/umbraco/datalayer/Utility/Installer/DefaultInstallerUtility.cs +++ b/umbraco/datalayer/Utility/Installer/DefaultInstallerUtility.cs @@ -185,10 +185,16 @@ namespace umbraco.DataLayer.Utility.Installer { try { - if (String.IsNullOrEmpty(v.Table)) - SqlHelper.ExecuteNonQuery(string.Format("SELECT {0}", v.Field)); - else - SqlHelper.ExecuteNonQuery(string.Format("SELECT {0} FROM {1}", v.Field, v.Table)); + if (!String.IsNullOrEmpty(v.Table) && !String.IsNullOrEmpty(v.Field) && !String.IsNullOrEmpty(v.Value)) + { + IRecordsReader reader = SqlHelper.ExecuteReader(string.Format("SELECT {0} FROM {1} WHERE {0}={2}", v.Field, v.Table, v.Value)); + if (!reader.HasRecords) + continue; + } + else if (String.IsNullOrEmpty(v.Table)) + SqlHelper.ExecuteNonQuery(string.Format("SELECT {0}", v.Field)); + else + SqlHelper.ExecuteNonQuery(string.Format("SELECT {0} FROM {1}", v.Field, v.Table)); return v.Version; } catch { } @@ -223,12 +229,20 @@ namespace umbraco.DataLayer.Utility.Installer /// 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 name of the field that should exist in order to have at least the specified version. public readonly string Field; /// The name of the table whose field should exist in order to have at least the specified version. public readonly string Table; + /// + /// The value to look for in the field, if this is left empty it will not be queried. + /// + public readonly string Value; + /// The minimum version number of a database that contains the specified field. public readonly DatabaseVersion Version; @@ -243,6 +257,21 @@ namespace umbraco.DataLayer.Utility.Installer Field = field; Table = table; Version = version; + Value = ""; } + + /// + /// Initializes a new instance of the struct. + /// + /// The field. + /// The table. + /// The version. + public VersionSpecs(string field, string table, string value, DatabaseVersion version) + { + Field = field; + Table = table; + Value = value; + Version = version; + } } } diff --git a/umbraco/datalayer/umbraco.datalayer.csproj b/umbraco/datalayer/umbraco.datalayer.csproj index 383bdb557c..32d7fab756 100644 --- a/umbraco/datalayer/umbraco.datalayer.csproj +++ b/umbraco/datalayer/umbraco.datalayer.csproj @@ -54,6 +54,8 @@ 3.5 + + False @@ -137,7 +139,9 @@ + +