diff --git a/umbraco/businesslogic/IO/SystemDirectories.cs b/umbraco/businesslogic/IO/SystemDirectories.cs index 4f73d81c62..b5df5bb911 100644 --- a/umbraco/businesslogic/IO/SystemDirectories.cs +++ b/umbraco/businesslogic/IO/SystemDirectories.cs @@ -123,7 +123,7 @@ namespace umbraco.IO return IOHelper.returnPath("umbracoXsltPath", "~/xslt"); } } - + public static string Packages { get @@ -133,6 +133,15 @@ namespace umbraco.IO } } + public static string Preview + { + get + { + //by default the packages folder should exist in the data folder + return IOHelper.returnPath("umbracoPreviewPath", Data + IOHelper.DirSepChar + "preview"); + } + } + public static string Root { get diff --git a/umbraco/businesslogic/UmbracoSettings.cs b/umbraco/businesslogic/UmbracoSettings.cs index f49b8ae06b..3e29d2e4f4 100644 --- a/umbraco/businesslogic/UmbracoSettings.cs +++ b/umbraco/businesslogic/UmbracoSettings.cs @@ -555,6 +555,31 @@ namespace umbraco } } + /// + /// If this is enabled, all Umbraco objects will generate data in the preview table (cmsPreviewXml). + /// If disabled, only documents will generate data. + /// This feature is useful if anyone would like to see how data looked at a given time + /// + public static bool EnableGlobalPreviewStorage + { + get + { + try + { + bool globalPreviewEnabled = false; + string value = GetKey("/settings/content/GlobalPreviewStorageEnabled"); + if (bool.TryParse(value, out globalPreviewEnabled)) + return !globalPreviewEnabled; + // Return default + return false; + } + catch + { + return false; + } + } + } + /// /// Whether to use the new 4.1 schema or the old legacy schema /// diff --git a/umbraco/businesslogic/Utils/TypeFinder.cs b/umbraco/businesslogic/Utils/TypeFinder.cs index 935ffc9577..c113aedd1d 100644 --- a/umbraco/businesslogic/Utils/TypeFinder.cs +++ b/umbraco/businesslogic/Utils/TypeFinder.cs @@ -48,7 +48,7 @@ namespace umbraco.BusinessLogic.Utils { if (useSeperateAppDomain) { - string binFolder = Path.Combine(HttpContext.Current.Request.PhysicalApplicationPath, "bin"); + string binFolder = Path.Combine(IO.IOHelper.MapPath("/", false), "bin"); string[] strTypes = TypeResolver.GetAssignablesFromType(binFolder, "*.dll"); List types = new List(); diff --git a/umbraco/cms/businesslogic/CMSNode.cs b/umbraco/cms/businesslogic/CMSNode.cs index 3eaf6fd2d9..9947dcca90 100644 --- a/umbraco/cms/businesslogic/CMSNode.cs +++ b/umbraco/cms/businesslogic/CMSNode.cs @@ -12,7 +12,8 @@ using System.Text.RegularExpressions; using System.ComponentModel; using umbraco.IO; -namespace umbraco.cms.businesslogic { +namespace umbraco.cms.businesslogic +{ /// /// CMSNode class serves as the base class for many of the other components in the cms.businesslogic.xx namespaces. /// Providing the basic hierarchical data structure and properties Text (name), Creator, Createdate, updatedate etc. @@ -21,7 +22,8 @@ namespace umbraco.cms.businesslogic { /// The child classes are required to implement an identifier (Guid) which is used as the objecttype identifier, for /// distinguishing the different types of CMSNodes (ex. Documents/Medias/Stylesheets/documenttypes and so forth). /// - public class CMSNode : BusinessLogic.console.IconI { + public class CMSNode : BusinessLogic.console.IconI + { private string _text; private int _id = 0; private Guid _uniqueID; @@ -46,8 +48,10 @@ namespace umbraco.cms.businesslogic { /// Gets the default icon classes. /// /// The default icon classes. - public static List DefaultIconClasses { - get { + public static List DefaultIconClasses + { + get + { if (m_DefaultIconClasses.Count == 0) initializeIconClasses(); @@ -55,11 +59,13 @@ namespace umbraco.cms.businesslogic { } } - private static void initializeIconClasses() { + private static void initializeIconClasses() + { StreamReader re = File.OpenText(m_DefaultIconCssFile); string content = string.Empty; string input = null; - while ((input = re.ReadLine()) != null) { + while ((input = re.ReadLine()) != null) + { content += input.Replace("\n", "") + "\n"; } re.Close(); @@ -67,7 +73,8 @@ namespace umbraco.cms.businesslogic { // parse the classes MatchCollection m = Regex.Matches(content, "([^{]*){([^}]*)}", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); - foreach (Match match in m) { + foreach (Match match in m) + { GroupCollection groups = match.Groups; string cssClass = groups[1].Value.Replace("\n", "").Replace("\r", "").Trim().Trim(Environment.NewLine.ToCharArray()); m_DefaultIconClasses.Add(cssClass); @@ -78,7 +85,8 @@ namespace umbraco.cms.businesslogic { /// Gets the SQL helper. /// /// The SQL helper. - protected static ISqlHelper SqlHelper { + protected static ISqlHelper SqlHelper + { get { return Application.SqlHelper; } } @@ -91,7 +99,8 @@ namespace umbraco.cms.businesslogic { /// Initializes a new instance of the class. /// /// The id. - public CMSNode(int Id) { + public CMSNode(int Id) + { _id = Id; setupNode(); } @@ -102,20 +111,22 @@ namespace umbraco.cms.businesslogic { /// /// The id. /// if set to true [no setup]. - public CMSNode(int id, bool noSetup) { + public CMSNode(int id, bool noSetup) + { _id = id; - - //TODO: add the following as noSetup currenlty doesn't actuall do anything!?? This can't happen until - //inheriting classes can override setupNode instead of using their own implementation (i.e. Document: setupDocument) - //if (!noSetup) - //setupNode(); + + //TODO: add the following as noSetup currenlty doesn't actuall do anything!?? This can't happen until + //inheriting classes can override setupNode instead of using their own implementation (i.e. Document: setupDocument) + //if (!noSetup) + //setupNode(); } /// /// Initializes a new instance of the class. /// /// The unique ID. - public CMSNode(Guid uniqueID) { + public CMSNode(Guid uniqueID) + { _id = SqlHelper.ExecuteScalar("SELECT id FROM umbracoNode WHERE uniqueID = @uniqueId", SqlHelper.CreateParameter("@uniqueId", uniqueID)); setupNode(); } @@ -123,10 +134,12 @@ namespace umbraco.cms.businesslogic { /// /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility /// - public virtual void Save() { + public virtual void Save() + { SaveEventArgs e = new SaveEventArgs(); this.FireBeforeSave(e); - if (!e.Cancel) { + if (!e.Cancel) + { //In the future there will be SQL stuff happening here... this.FireAfterSave(e); } @@ -136,11 +149,12 @@ namespace umbraco.cms.businesslogic { /// /// Sets up the internal data of the CMSNode, used by the various constructors /// - protected void setupNode() { + protected void setupNode() + { IRecordsReader dr = SqlHelper.ExecuteReader( "SELECT createDate, trashed, parentId, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text FROM umbracoNode WHERE id = " + this.Id ); - + bool noRecord = false; if (dr.Read()) @@ -165,7 +179,8 @@ namespace umbraco.cms.businesslogic { dr.Close(); - if (noRecord) { + if (noRecord) + { throw new ArgumentException(string.Format("No node exists with id '{0}'", Id)); } } @@ -183,7 +198,8 @@ namespace umbraco.cms.businesslogic { /// The create date. /// if set to true [has children]. protected void SetupNodeForTree(Guid uniqueID, Guid nodeObjectType, int Level, int ParentId, int UserId, string Path, string Text, - DateTime CreateDate, bool hasChildren) { + DateTime CreateDate, bool hasChildren) + { _uniqueID = uniqueID; _nodeObjectType = nodeObjectType; _level = Level; @@ -200,9 +216,11 @@ namespace umbraco.cms.businesslogic { /// Gets or sets the sort order. /// /// The sort order. - public int sortOrder { + public int sortOrder + { get { return _sortOrder; } - set { + set + { _sortOrder = value; SqlHelper.ExecuteNonQuery("update umbracoNode set sortOrder = '" + value + "' where id = " + this.Id.ToString()); } @@ -213,9 +231,11 @@ namespace umbraco.cms.businesslogic { /// Gets or sets the create date time. /// /// The create date time. - public DateTime CreateDateTime { + public DateTime CreateDateTime + { get { return _createDate; } - set { + set + { _createDate = value; SqlHelper.ExecuteNonQuery("update umbracoNode set createDate = @createDate where id = " + this.Id.ToString(), SqlHelper.CreateParameter("@createDate", _createDate)); } @@ -226,8 +246,10 @@ namespace umbraco.cms.businesslogic { /// Gets the creator /// /// The user. - public BusinessLogic.User User { - get { + public BusinessLogic.User User + { + get + { return BusinessLogic.User.GetUser(_userId); } } @@ -237,7 +259,8 @@ namespace umbraco.cms.businesslogic { /// /// Identifier /// True if there is a CMSNode with the given Guid - static public bool IsNode(Guid uniqueID) { + static public bool IsNode(Guid uniqueID) + { return (SqlHelper.ExecuteScalar("select count(id) from umbracoNode where uniqueID = @uniqueID", SqlHelper.CreateParameter("@uniqueId", uniqueID)) > 0); } @@ -246,7 +269,8 @@ namespace umbraco.cms.businesslogic { /// /// Identifier /// True if there is a CMSNode with the given id - static public bool IsNode(int Id) { + static public bool IsNode(int Id) + { return (SqlHelper.ExecuteScalar("select count(id) from umbracoNode where id = '" + Id + "'") > 0); } @@ -256,7 +280,8 @@ namespace umbraco.cms.businesslogic { /// Gets the id. /// /// The id. - public int Id { + public int Id + { get { return _id; } } @@ -265,12 +290,15 @@ namespace umbraco.cms.businesslogic { /// Given the hierarchical tree structure a CMSNode has only one parent but can have many children /// /// The parent. - public CMSNode Parent { - get { + public CMSNode Parent + { + get + { if (Level == 1) throw new ArgumentException("No parent node"); return new CMSNode(_parentid); } - set { + set + { _parentid = value.Id; SqlHelper.ExecuteNonQuery("update umbracoNode set parentId = " + value.Id.ToString() + " where id = " + this.Id.ToString()); } @@ -282,16 +310,19 @@ namespace umbraco.cms.businesslogic { /// /// Unique identifier of the CMSNode, used when locating data. /// - public Guid UniqueId { + public Guid UniqueId + { get { return _uniqueID; } } /// /// Human readable name/label /// - public virtual string Text { + public virtual string Text + { get { return _text; } - set { + set + { _text = value; SqlHelper.ExecuteNonQuery("UPDATE umbracoNode SET text = @text WHERE id = @id", SqlHelper.CreateParameter("@text", value), @@ -304,21 +335,24 @@ namespace umbraco.cms.businesslogic { /// The menu items used in the tree view /// [Obsolete("this is not used anywhere")] - public virtual BusinessLogic.console.MenuItemI[] MenuItems { + public virtual BusinessLogic.console.MenuItemI[] MenuItems + { get { return new BusinessLogic.console.MenuItemI[0]; } } /// /// Not implemented, always returns "about:blank" /// - public virtual string DefaultEditorURL { + public virtual string DefaultEditorURL + { get { return "about:blank"; } } /// /// The icon in the tree /// - public virtual string Image { + public virtual string Image + { get { return m_image; } set { m_image = value; } @@ -327,7 +361,8 @@ namespace umbraco.cms.businesslogic { /// /// The "open/active" icon in the tree /// - public virtual string OpenImage { + public virtual string OpenImage + { get { return ""; } } @@ -339,9 +374,11 @@ namespace umbraco.cms.businesslogic { /// that indicates the path from the topmost node to the given node /// /// The path. - public string Path { + public string Path + { get { return _path; } - set { + set + { _path = value; SqlHelper.ExecuteNonQuery("update umbracoNode set path = '" + _path + "' where id = " + this.Id.ToString()); } @@ -352,7 +389,8 @@ namespace umbraco.cms.businesslogic { /// Updates the temp path for the content tree. /// /// The path. - protected void UpdateTempPathForTree(string Path) { + protected void UpdateTempPathForTree(string Path) + { this._path = Path; } @@ -362,11 +400,13 @@ namespace umbraco.cms.businesslogic { /// Moves the CMSNode from the current position in the hierarchy to the target /// /// Target CMSNode id - public void Move(int NewParentId) { + public void Move(int NewParentId) + { MoveEventArgs e = new MoveEventArgs(); FireBeforeMove(e); - if (!e.Cancel) { + if (!e.Cancel) + { int maxSortOrder = SqlHelper.ExecuteScalar( "select coalesce(max(sortOrder),0) from umbracoNode where parentid = @parentId", SqlHelper.CreateParameter("@parentId", NewParentId)); @@ -380,12 +420,14 @@ namespace umbraco.cms.businesslogic { this.sortOrder = maxSortOrder + 1; - if (n.nodeObjectType == web.Document._objectType) { + if (n.nodeObjectType == web.Document._objectType) + { Document d = new umbraco.cms.businesslogic.web.Document(n.Id); d.XmlGenerate(new XmlDocument()); - } else if (n.nodeObjectType == media.Media._objectType) + } + else if (n.nodeObjectType == media.Media._objectType) new umbraco.cms.businesslogic.media.Media(n.Id).XmlGenerate(new XmlDocument()); //store children array here because iterating over an Array property object is very inneficient. @@ -404,9 +446,11 @@ namespace umbraco.cms.businesslogic { /// tree structure the given node is /// /// The level. - public int Level { + public int Level + { get { return _level; } - set { + set + { _level = value; SqlHelper.ExecuteNonQuery("update umbracoNode set level = " + _level.ToString() + " where id = " + this.Id.ToString()); } @@ -417,7 +461,8 @@ namespace umbraco.cms.businesslogic { /// object types for for fast loading children to the tree. /// /// The type of the node object. - public Guid nodeObjectType { + public Guid nodeObjectType + { get { return _nodeObjectType; } } @@ -426,7 +471,8 @@ namespace umbraco.cms.businesslogic { /// non-strict hierarchy /// /// The relations. - public relation.Relation[] Relations { + public relation.Relation[] Relations + { get { return relation.Relation.GetRelations(this.Id); } } @@ -436,15 +482,19 @@ namespace umbraco.cms.businesslogic { /// /// true if this instance has children; otherwise, false. /// - public virtual bool HasChildren { - get { - if (!_hasChildrenInitialized) { + public virtual bool HasChildren + { + get + { + if (!_hasChildrenInitialized) + { int tmpChildrenCount = SqlHelper.ExecuteScalar("select count(id) from umbracoNode where ParentId = " + _id); HasChildren = (tmpChildrenCount > 0); } return _hasChildren; } - set { + set + { _hasChildrenInitialized = true; _hasChildren = value; } @@ -454,8 +504,10 @@ namespace umbraco.cms.businesslogic { /// The basic recursive tree pattern /// /// The children. - public virtual BusinessLogic.console.IconI[] Children { - get { + public virtual BusinessLogic.console.IconI[] Children + { + get + { System.Collections.ArrayList tmp = new System.Collections.ArrayList(); IRecordsReader dr = SqlHelper.ExecuteReader("select id from umbracoNode where ParentID = " + this.Id + " And nodeObjectType = @type order by sortOrder", SqlHelper.CreateParameter("@type", this.nodeObjectType)); @@ -479,8 +531,10 @@ namespace umbraco.cms.businesslogic { /// Use with care. /// /// The children of all object types. - public BusinessLogic.console.IconI[] ChildrenOfAllObjectTypes { - get { + public BusinessLogic.console.IconI[] ChildrenOfAllObjectTypes + { + get + { System.Collections.ArrayList tmp = new System.Collections.ArrayList(); IRecordsReader dr = SqlHelper.ExecuteReader("select id from umbracoNode where ParentID = " + this.Id + " order by sortOrder"); @@ -505,7 +559,8 @@ namespace umbraco.cms.businesslogic { /// /// A list of all top level nodes given the objecttype /// - protected static Guid[] TopMostNodeIds(Guid ObjectType) { + protected static Guid[] TopMostNodeIds(Guid ObjectType) + { IRecordsReader dr = SqlHelper.ExecuteReader("Select uniqueID from umbracoNode where nodeObjectType = @type And parentId = -1 order by sortOrder", SqlHelper.CreateParameter("@type", ObjectType)); System.Collections.ArrayList tmp = new System.Collections.ArrayList(); @@ -529,16 +584,19 @@ namespace umbraco.cms.businesslogic { /// The name of the CMSNode /// The unique identifier /// - protected static CMSNode MakeNew(int parentId, Guid objectType, int userId, int level, string text, Guid uniqueID) { + protected static CMSNode MakeNew(int parentId, Guid objectType, int userId, int level, string text, Guid uniqueID) + { CMSNode parent; string path = ""; int sortOrder = 0; - if (level > 0) { + if (level > 0) + { parent = new CMSNode(parentId); sortOrder = parent.Children.Length + 1; path = parent.Path; - } else + } + else path = "-1"; // Ruben 8/1/2007: I replace this with a parameterized version. @@ -558,7 +616,7 @@ namespace umbraco.cms.businesslogic { CMSNode retVal = new CMSNode(uniqueID); retVal.Path = path + "," + retVal.Id.ToString(); - + //event NewEventArgs e = new NewEventArgs(); retVal.FireAfterNew(e); @@ -573,7 +631,8 @@ namespace umbraco.cms.businesslogic { /// /// A list of all unique identifiers which each are associated to a CMSNode /// - public static Guid[] getAllUniquesFromObjectType(Guid objectType) { + public static Guid[] getAllUniquesFromObjectType(Guid objectType) + { IRecordsReader dr = SqlHelper.ExecuteReader("Select uniqueID from umbracoNode where nodeObjectType = @type", SqlHelper.CreateParameter("@type", objectType)); System.Collections.ArrayList tmp = new System.Collections.ArrayList(); @@ -593,7 +652,8 @@ namespace umbraco.cms.businesslogic { /// /// A list of all node ids which each are associated to a CMSNode /// - public static int[] getAllUniqueNodeIdsFromObjectType(Guid objectType) { + public static int[] getAllUniqueNodeIdsFromObjectType(Guid objectType) + { IRecordsReader dr = SqlHelper.ExecuteReader("Select id from umbracoNode where nodeObjectType = @type", SqlHelper.CreateParameter("@type", objectType)); System.Collections.ArrayList tmp = new System.Collections.ArrayList(); @@ -613,8 +673,10 @@ namespace umbraco.cms.businesslogic { /// /// A list of all CMSNodes which has the objecttype and a name that starts with the given letter /// - protected static int[] getUniquesFromObjectTypeAndFirstLetter(Guid objectType, char letter) { - using (IRecordsReader dr = SqlHelper.ExecuteReader("Select id from umbracoNode where nodeObjectType = @objectType AND text like @letter", SqlHelper.CreateParameter("@objectType", objectType), SqlHelper.CreateParameter("@letter", letter.ToString() + "%"))) { + protected static int[] getUniquesFromObjectTypeAndFirstLetter(Guid objectType, char letter) + { + using (IRecordsReader dr = SqlHelper.ExecuteReader("Select id from umbracoNode where nodeObjectType = @objectType AND text like @letter", SqlHelper.CreateParameter("@objectType", objectType), SqlHelper.CreateParameter("@letter", letter.ToString() + "%"))) + { List tmp = new List(); while (dr.Read()) tmp.Add(dr.GetInt("id")); return tmp.ToArray(); @@ -625,10 +687,12 @@ namespace umbraco.cms.businesslogic { /// /// Deletes this instance. /// - public void delete() { + public void delete() + { DeleteEventArgs e = new DeleteEventArgs(); FireBeforeDelete(e); - if (!e.Cancel) { + if (!e.Cancel) + { // remove relations var rels = Relations; foreach (relation.Relation rel in rels) @@ -648,7 +712,8 @@ namespace umbraco.cms.businesslogic { /// /// The number of CMSNodes of the given objecttype /// - public static int CountByObjectType(Guid objectType) { + public static int CountByObjectType(Guid objectType) + { return SqlHelper.ExecuteScalar("SELECT COUNT(*) from umbracoNode WHERE nodeObjectType = @type", SqlHelper.CreateParameter("@type", objectType)); } @@ -659,7 +724,8 @@ namespace umbraco.cms.businesslogic { /// /// The number of children from the given CMSNode /// - public static int CountSubs(int Id) { + public static int CountSubs(int Id) + { return SqlHelper.ExecuteScalar("SELECT COUNT(*) FROM umbracoNode WHERE ','+path+',' LIKE '%," + Id.ToString() + ",%'"); } @@ -669,13 +735,75 @@ namespace umbraco.cms.businesslogic { /// Xmldocument context /// If true the xml will append the CMSNodes child xml /// The CMSNode Xmlrepresentation - public virtual XmlNode ToXml(XmlDocument xd, bool Deep) { + public virtual XmlNode ToXml(XmlDocument xd, bool Deep) + { XmlNode x = xd.CreateNode(XmlNodeType.Element, "node", ""); XmlPopulate(xd, x, Deep); return x; } - private void XmlPopulate(XmlDocument xd, XmlNode x, bool Deep) { + public virtual XmlNode ToPreviewXml(XmlDocument xd) + { + // If xml already exists + if (!PreviewExists(UniqueId)) + { + savePreviewXml(ToXml(xd, false), UniqueId); + } + return GetPreviewXml(xd, UniqueId); + } + + public virtual List GetNodesForPreview(bool childrenOnly) + { + List nodes = new List(); + string sql = @" +select umbracoNode.id, umbracoNode.parentId, umbracoNode.level, umbracoNode.sortOrder, cmsPreviewXml.xml from umbracoNode +inner join cmsPreviewXml on cmsPreviewXml.nodeId = umbracoNode.id +where trashed = 0 and path like '{0}' +order by level,sortOrder"; + + string pathExp = childrenOnly ? Path + ",%" : Path; + + IRecordsReader dr = SqlHelper.ExecuteReader(String.Format(sql, pathExp)); + while (dr.Read()) + nodes.Add(new CMSPreviewNode(dr.GetInt("id"), dr.GetGuid("uniqueID"), dr.GetInt("parentId"), dr.GetShort("level"), dr.GetInt("sortOrder"), dr.GetString("xml"))); + dr.Close(); + + return nodes; + } + + protected virtual XmlNode GetPreviewXml(XmlDocument xd, Guid version) + { + + XmlDocument xmlDoc = new XmlDocument(); + XmlReader xmlRdr = SqlHelper.ExecuteXmlReader( + "select xml from cmsPreviewXml where nodeID = @nodeId and versionId = @versionId", + SqlHelper.CreateParameter("@nodeId", Id), + SqlHelper.CreateParameter("@versionId", version)); + xmlDoc.Load(xmlRdr); + + return xd.ImportNode(xmlDoc.FirstChild, true); + } + + protected virtual bool PreviewExists(Guid versionId) + { + return (SqlHelper.ExecuteScalar("SELECT COUNT(nodeId) FROM cmsPreviewXml WHERE nodeId=@nodeId and versionId = @versionId", + SqlHelper.CreateParameter("@nodeId", Id), SqlHelper.CreateParameter("@versionId", versionId)) != 0); + + } + + protected void savePreviewXml(XmlNode x, Guid versionId) + { + string sql = PreviewExists(versionId) ? "UPDATE cmsPreviewXml SET xml = @xml, timestamp = @timestamp WHERE nodeId=@nodeId AND versionId = @versionId" + : "INSERT INTO cmsPreviewXml(nodeId, versionId, timestamp, xml) VALUES (@nodeId, @versionId, @timestamp, @xml)"; + SqlHelper.ExecuteNonQuery(sql, + SqlHelper.CreateParameter("@nodeId", Id), + SqlHelper.CreateParameter("@versionId", versionId), + SqlHelper.CreateParameter("@timestamp", DateTime.Now), + SqlHelper.CreateParameter("@xml", x.OuterXml)); + } + + private void XmlPopulate(XmlDocument xd, XmlNode x, bool Deep) + { // attributes x.Attributes.Append(xmlHelper.addAttribute(xd, "id", this.Id.ToString())); if (this.Level > 1) @@ -689,7 +817,8 @@ namespace umbraco.cms.businesslogic { x.Attributes.Append(xmlHelper.addAttribute(xd, "nodeName", this.Text)); x.Attributes.Append(xmlHelper.addAttribute(xd, "path", this.Path)); - if (Deep) { + if (Deep) + { //store children array here because iterating over an Array property object is very inneficient. var children = this.Children; foreach (Content c in children) @@ -727,7 +856,8 @@ namespace umbraco.cms.businesslogic { /// Raises the event. /// /// The instance containing the event data. - protected virtual void FireBeforeSave(SaveEventArgs e) { + protected virtual void FireBeforeSave(SaveEventArgs e) + { FireCancelableEvent(BeforeSave, this, e); } @@ -740,8 +870,9 @@ namespace umbraco.cms.businesslogic { /// Raises the event. /// /// The instance containing the event data. - protected virtual void FireAfterSave(SaveEventArgs e) { - if (AfterSave!=null) + protected virtual void FireAfterSave(SaveEventArgs e) + { + if (AfterSave != null) AfterSave(this, e); } @@ -754,7 +885,8 @@ namespace umbraco.cms.businesslogic { /// Raises the event. /// /// The instance containing the event data. - protected virtual void FireAfterNew(NewEventArgs e) { + protected virtual void FireAfterNew(NewEventArgs e) + { if (AfterNew != null) AfterNew(this, e); } @@ -768,7 +900,8 @@ namespace umbraco.cms.businesslogic { /// Raises the event. /// /// The instance containing the event data. - protected virtual void FireBeforeDelete(DeleteEventArgs e) { + protected virtual void FireBeforeDelete(DeleteEventArgs e) + { FireCancelableEvent(BeforeDelete, this, e); } @@ -781,7 +914,8 @@ namespace umbraco.cms.businesslogic { /// Raises the event. /// /// The instance containing the event data. - protected virtual void FireAfterDelete(DeleteEventArgs e) { + protected virtual void FireAfterDelete(DeleteEventArgs e) + { if (AfterDelete != null) AfterDelete(this, e); } @@ -795,7 +929,8 @@ namespace umbraco.cms.businesslogic { /// Raises the event. /// /// The instance containing the event data. - protected virtual void FireBeforeMove(MoveEventArgs e) { + protected virtual void FireBeforeMove(MoveEventArgs e) + { FireCancelableEvent(BeforeMove, this, e); } @@ -808,9 +943,35 @@ namespace umbraco.cms.businesslogic { /// Raises the event. /// /// The instance containing the event data. - protected virtual void FireAfterMove(MoveEventArgs e) { + protected virtual void FireAfterMove(MoveEventArgs e) + { if (AfterMove != null) AfterMove(this, e); } } + + public class CMSPreviewNode + { + public int NodeId { get; set; } + public int Level { get; set; } + public Guid Version { get; set; } + public int ParentId { get; set; } + public int SortOrder { get; set; } + public string Xml { get; set; } + + public CMSPreviewNode() + { + + } + + public CMSPreviewNode(int nodeId, Guid version, int parentId, int level, int sortOrder, string xml) + { + NodeId = nodeId; + Version = version; + ParentId = parentId; + Level = level; + SortOrder = sortOrder; + Xml = xml; + } + } } diff --git a/umbraco/cms/businesslogic/Content.cs b/umbraco/cms/businesslogic/Content.cs index 602f3b6fe2..740f0129c9 100644 --- a/umbraco/cms/businesslogic/Content.cs +++ b/umbraco/cms/businesslogic/Content.cs @@ -8,6 +8,7 @@ using umbraco.cms.businesslogic.property; using umbraco.cms.businesslogic.propertytype; using umbraco.DataLayer; using System.Runtime.CompilerServices; +using umbraco.cms.helpers; namespace umbraco.cms.businesslogic { @@ -480,11 +481,19 @@ namespace umbraco.cms.businesslogic /// public virtual void XmlGenerate(XmlDocument xd) { - XmlNode node = xd.CreateNode(XmlNodeType.Element, "node", String.Empty); - XmlPopulate(xd, ref node, false); + XmlNode node = generateXmlWithoutSaving(xd); SaveXmlDocument(node); } + protected virtual XmlNode generateXmlWithoutSaving(XmlDocument xd) + { + string nodeName = UmbracoSettings.UseLegacyXmlSchema ? "node" : Casing.SafeAlias(ContentType.Alias); + XmlNode x = xd.CreateNode(XmlNodeType.Element, nodeName, ""); + XmlPopulate(xd, ref x, false); + return x; + } + + public virtual void XmlPopulate(XmlDocument xd, ref XmlNode x, bool Deep) { var props = this.getProperties; @@ -543,6 +552,25 @@ namespace umbraco.cms.businesslogic SqlHelper.CreateParameter("@nodeId", Id), SqlHelper.CreateParameter("@xml", node.OuterXml)); } + + + #region XmlPreivew + + public override XmlNode ToPreviewXml(XmlDocument xd) + { + if (!PreviewExists(Version)) + { + saveXmlPreview(xd); + } + return GetPreviewXml(xd, Version); + } + + private void saveXmlPreview(XmlDocument xd) + { + savePreviewXml(generateXmlWithoutSaving(xd), Version); + } + + #endregion } /// diff --git a/umbraco/cms/businesslogic/media/Media.cs b/umbraco/cms/businesslogic/media/Media.cs index e27f8a5d6e..596e58d4c2 100644 --- a/umbraco/cms/businesslogic/media/Media.cs +++ b/umbraco/cms/businesslogic/media/Media.cs @@ -5,6 +5,7 @@ using umbraco.DataLayer; using System.Collections; using System.Collections.Generic; using umbraco.IO; +using System.Xml; namespace umbraco.cms.businesslogic.media { @@ -69,6 +70,15 @@ namespace umbraco.cms.businesslogic.media base.Save(); + XmlDocument xd = new XmlDocument(); + XmlGenerate(xd); + + // generate preview for blame history? + if (UmbracoSettings.EnableGlobalPreviewStorage) + { + // Version as new guid to ensure different versions are generated as media are not versioned currently! + savePreviewXml(generateXmlWithoutSaving(xd), Guid.NewGuid()); + } FireAfterSave(e); } diff --git a/umbraco/cms/businesslogic/member/Member.cs b/umbraco/cms/businesslogic/member/Member.cs index b872ac6551..311c666c79 100644 --- a/umbraco/cms/businesslogic/member/Member.cs +++ b/umbraco/cms/businesslogic/member/Member.cs @@ -194,7 +194,15 @@ namespace umbraco.cms.businesslogic.member if (!e.Cancel) { // re-generate xml - XmlGenerate(new XmlDocument()); + XmlDocument xd = new XmlDocument(); + XmlGenerate(xd); + + // generate preview for blame history? + if (UmbracoSettings.EnableGlobalPreviewStorage) + { + // Version as new guid to ensure different versions are generated as members are not versioned currently! + savePreviewXml(generateXmlWithoutSaving(xd), Guid.NewGuid()); + } FireAfterSave(e); } @@ -332,14 +340,20 @@ namespace umbraco.cms.businesslogic.member /// /// public override void XmlGenerate(XmlDocument xd) + { + SaveXmlDocument(generateXmlWithoutSaving(xd)); + } + + protected override XmlNode generateXmlWithoutSaving(XmlDocument xd) { XmlNode node = xd.CreateNode(XmlNodeType.Element, "node", ""); XmlPopulate(xd, ref node, false); node.Attributes.Append(xmlHelper.addAttribute(xd, "loginName", LoginName)); node.Attributes.Append(xmlHelper.addAttribute(xd, "email", Email)); - SaveXmlDocument(node); + return node; } + /// /// Xmlrepresentation of a member /// diff --git a/umbraco/cms/businesslogic/web/Document.cs b/umbraco/cms/businesslogic/web/Document.cs index 190b63fa6d..4f978b2c0d 100644 --- a/umbraco/cms/businesslogic/web/Document.cs +++ b/umbraco/cms/businesslogic/web/Document.cs @@ -28,7 +28,7 @@ namespace umbraco.cms.businesslogic.web /// public class Document : Content { - private const string m_SQLOptimizedSingle = @" + 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, @@ -57,7 +57,7 @@ namespace umbraco.cms.businesslogic.web order by {1} "; - private const string m_SQLOptimizedChildren = @" + 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 @@ -76,6 +76,14 @@ namespace umbraco.cms.businesslogic.web order by {1} "; + private const string m_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 + where newest = 1 and trashed = 0 and path like '{0}' + order by level,sortOrder + "; + public static Guid _objectType = new Guid("c66ba18e-eaf3-4cff-8a22-41b16d66a972"); private DateTime _updated; private DateTime _release; @@ -130,15 +138,17 @@ namespace umbraco.cms.businesslogic.web /// Gets the user who created the document. /// /// The creator. - public User Creator { - get { return _creator;} + public User Creator + { + get { return _creator; } } /// /// Gets the writer. /// /// The writer. - public User Writer { + public User Writer + { get { return _writer; } } @@ -247,22 +257,26 @@ namespace umbraco.cms.businesslogic.web return true; } - else { + else + { return false; } } - public bool PublishWithChildrenWithResult(User u) { - if(PublishWithResult(u)) + public bool PublishWithChildrenWithResult(User u) + { + if (PublishWithResult(u)) { //store children array here because iterating over an Array object is very inneficient. - var c = this.Children; + var c = this.Children; foreach (cms.businesslogic.web.Document dc in c) { dc.PublishWithChildrenWithResult(u); } - }else{ + } + else + { return false; } @@ -280,7 +294,8 @@ namespace umbraco.cms.businesslogic.web RollBackEventArgs e = new RollBackEventArgs(); FireBeforeRollBack(e); - if (!e.Cancel) { + if (!e.Cancel) + { Guid newVersion = createNewVersion(); SqlHelper.ExecuteNonQuery("insert into cmsDocument (nodeId, published, documentUser, versionId, Text, TemplateId) values (" + Id + @@ -301,9 +316,12 @@ namespace umbraco.cms.businesslogic.web // Revert all properties var props = dOld.getProperties; foreach (Property p in props) - try { + try + { dNew.getProperty(p.PropertyType).Value = p.Value; - } catch { + } + catch + { // property doesn't exists } @@ -320,10 +338,11 @@ namespace umbraco.cms.businesslogic.web public void PublishWithSubs(User u) { - PublishEventArgs e = new PublishEventArgs(); + PublishEventArgs e = new PublishEventArgs(); FireBeforePublish(e); - if (!e.Cancel) { + if (!e.Cancel) + { _published = true; string tempVersion = Version.ToString(); Guid newVersion = createNewVersion(); @@ -373,7 +392,8 @@ namespace umbraco.cms.businesslogic.web FireBeforeUnPublish(e); - if (!e.Cancel) { + if (!e.Cancel) + { SqlHelper.ExecuteNonQuery(string.Format("update cmsDocument set published = 0 where nodeId = {0}", Id)); FireAfterUnPublish(e); } @@ -384,9 +404,10 @@ namespace umbraco.cms.businesslogic.web /// /// Id of the document /// true if the data shouldn't loaded from the db - public Document(Guid id, bool noSetup) : base(id) + public Document(Guid id, bool noSetup) + : base(id) { - + } /// @@ -395,8 +416,9 @@ namespace umbraco.cms.businesslogic.web /// therefor only data needed by the tree is initialized. /// /// Id of the document - /// true if the data shouldn't loaded from the db - public Document(int id, bool noSetup) : base(id, noSetup) + /// true if the data shouldn't loaded from the db + public Document(int id, bool noSetup) + : base(id, noSetup) { } @@ -406,7 +428,8 @@ namespace umbraco.cms.businesslogic.web /// /// The id of the document /// The version of the document - public Document(int id, Guid Version) : base(id) + public Document(int id, Guid Version) + : base(id) { this.Version = Version; setupDocument(); @@ -416,7 +439,8 @@ namespace umbraco.cms.businesslogic.web /// Initializes a new instance of the Document class. /// /// The id of the document - public Document(int id) : base(id) + public Document(int id) + : base(id) { setupDocument(); } @@ -425,20 +449,21 @@ namespace umbraco.cms.businesslogic.web /// Initialize the document /// /// The id of the document - public Document(Guid id) : base(id) + public Document(Guid id) + : base(id) { setupDocument(); } - //TODO: SD: Implement this EVERYWHERE (90 places apparently) - public Document(bool optimizedMode, int id) - : base(id, optimizedMode) + //TODO: SD: Implement this EVERYWHERE (90 places apparently) + public Document(bool optimizedMode, int id) + : base(id, optimizedMode) { this._optimizedMode = OptimizedMode; if (OptimizedMode) { - + using (IRecordsReader dr = SqlHelper.ExecuteReader(string.Format(m_SQLOptimizedSingle, "umbracoNode.id = @id", "cmsContentVersion.id desc"), SqlHelper.CreateParameter("@id", id))) @@ -449,26 +474,26 @@ namespace umbraco.cms.businesslogic.web bool _hc = false; if (dr.GetInt("children") > 0) _hc = true; - int? masterContentType = null; - if (!dr.IsNull("masterContentType")) - masterContentType = dr.GetInt("masterContentType"); + 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")); + , 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"), @@ -492,7 +517,7 @@ namespace umbraco.cms.businesslogic.web dr.GetDateTime("updateDate"), dr.GetBoolean("published") ); - } + } } } } @@ -510,7 +535,8 @@ namespace umbraco.cms.businesslogic.web SaveEventArgs e = new SaveEventArgs(); FireBeforeSave(e); - if (!e.Cancel) { + if (!e.Cancel) + { if (this._optimizedMode) { @@ -522,17 +548,19 @@ namespace umbraco.cms.businesslogic.web } base.Save(); + // update preview xml + SaveXmlPreview(new XmlDocument()); FireAfterSave(e); } } - //TODO: Perhaps this should override the setupNode method of the CMSNode so that constructors work properly! + //TODO: Perhaps this should override the setupNode method of the CMSNode so that constructors work properly! private void setupDocument() { IRecordsReader dr = SqlHelper.ExecuteReader("select published, documentUser, coalesce(templateId, cmsDocumentType.templateNodeId) as templateId, text, releaseDate, expireDate, updateDate from cmsDocument inner join cmsContent on cmsDocument.nodeId = cmsContent.Nodeid left join cmsDocumentType on cmsDocumentType.contentTypeNodeId = cmsContent.contentType and cmsDocumentType.IsDefault = 1 where versionId = @versionId", - SqlHelper.CreateParameter("@versionId",Version)); + SqlHelper.CreateParameter("@versionId", Version)); if (dr.Read()) { _creator = User; @@ -549,7 +577,7 @@ namespace umbraco.cms.businesslogic.web _updated = dr.GetDateTime("updateDate"); } dr.Close(); - _published = (SqlHelper.ExecuteScalar("select Count(published) as tmp from cmsDocument where published = 1 And nodeId ="+Id) > 0); + _published = (SqlHelper.ExecuteScalar("select Count(published) as tmp from cmsDocument where published = 1 And nodeId =" + Id) > 0); } protected void InitializeDocument(User InitUser, User InitWriter, string InitText, int InitTemplate, @@ -732,7 +760,8 @@ namespace umbraco.cms.businesslogic.web FireBeforeCopy(e); - if (!e.Cancel) { + if (!e.Cancel) + { // Make the new document Document NewDoc = MakeNew(Text, new DocumentType(ContentType.Id), u, CopyTo); @@ -745,7 +774,8 @@ namespace umbraco.cms.businesslogic.web NewDoc.getProperty(p.PropertyType.Alias).Value = p.Value; // Relate? - if (RelateToOrignal) { + if (RelateToOrignal) + { Relation.MakeNew(Id, NewDoc.Id, RelationType.GetByAlias("relateDocumentOnCopy"), ""); // Add to audit trail @@ -788,9 +818,9 @@ namespace umbraco.cms.businesslogic.web return null; } - + Guid newId = Guid.NewGuid(); - + // Updated to match level from base node CMSNode n = new CMSNode(ParentId); int newLevel = n.Level; @@ -823,6 +853,8 @@ namespace umbraco.cms.businesslogic.web // Run Handler umbraco.BusinessLogic.Actions.Action.RunActionHandlers(d, ActionNew.Instance); + // Save doc + d.Save(); return d; } @@ -852,15 +884,15 @@ namespace umbraco.cms.businesslogic.web { get { - //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; + //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; //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 = Document.GetChildrenForTree(this.Id); return this._children.ToArray(); } @@ -883,31 +915,35 @@ namespace umbraco.cms.businesslogic.web /// public new void delete() { - // Check for recyle bin - if (!Path.Contains("," + ((int)RecycleBin.RecycleBinType.Content).ToString() + ",")) + // Check for recyle bin + if (!Path.Contains("," + ((int)RecycleBin.RecycleBinType.Content).ToString() + ",")) + { + MoveToTrashEventArgs e = new MoveToTrashEventArgs(); + FireBeforeMoveToTrash(e); + + if (!e.Cancel) { - MoveToTrashEventArgs e = new MoveToTrashEventArgs(); - FireBeforeMoveToTrash(e); + umbraco.BusinessLogic.Actions.Action.RunActionHandlers(this, ActionDelete.Instance); + UnPublish(); + Move(-20); - if (!e.Cancel) { - umbraco.BusinessLogic.Actions.Action.RunActionHandlers(this, ActionDelete.Instance); - UnPublish(); - Move(-20); + FireAfterMoveToTrash(e); + } - FireAfterMoveToTrash(e); - } - - } else { + } + else + { - DeleteEventArgs e = new DeleteEventArgs(); + DeleteEventArgs e = new DeleteEventArgs(); - FireBeforeDelete(e); + FireBeforeDelete(e); - if (!e.Cancel) { + if (!e.Cancel) + { //store children array here because iterating over an Array object is very inneficient. var c = Children; - foreach (Document d in c) + foreach (Document d in c) { d.delete(); } @@ -921,19 +957,19 @@ namespace umbraco.cms.businesslogic.web if (p.PropertyType.DataTypeDefinition.DataType.Id == uploadField.Id && p.Value.ToString() != "" && - System.IO.File.Exists( IOHelper.MapPath(p.Value.ToString())) + System.IO.File.Exists(IOHelper.MapPath(p.Value.ToString())) ) - System.IO.File.Delete( IOHelper.MapPath(p.Value.ToString())); + System.IO.File.Delete(IOHelper.MapPath(p.Value.ToString())); - SqlHelper.ExecuteNonQuery("delete from cmsDocument where NodeId = " + Id); - HttpContext.Current.Trace.Write("documentdelete", "base delete"); - base.delete(); - HttpContext.Current.Trace.Write("documentdelete", "after base delete"); + SqlHelper.ExecuteNonQuery("delete from cmsDocument where NodeId = " + Id); + HttpContext.Current.Trace.Write("documentdelete", "base delete"); + base.delete(); + HttpContext.Current.Trace.Write("documentdelete", "after base delete"); - FireAfterDelete(e); - } + FireAfterDelete(e); } + } } /// @@ -971,14 +1007,12 @@ namespace umbraco.cms.businesslogic.web } /// - /// Creates an xmlrepresentation of the documet and saves it to the database + /// Creates an xmlrepresentation of the document and saves it to the database /// /// public new void XmlGenerate(XmlDocument xd) { - string nodeName = UmbracoSettings.UseLegacyXmlSchema ? "node" : Casing.SafeAlias(ContentType.Alias); - XmlNode x = xd.CreateNode(XmlNodeType.Element, nodeName, ""); - XmlPopulate(xd, ref x, false); + XmlNode x = generateXmlWithoutSaving(xd); /* if (!UmbracoSettings.UseFriendlyXmlSchema) { @@ -995,6 +1029,7 @@ namespace umbraco.cms.businesslogic.web saveXml(x); } + private void saveXml(XmlNode x) { bool exists = (SqlHelper.ExecuteScalar("SELECT COUNT(nodeId) FROM cmsContentXml WHERE nodeId=@nodeId", @@ -1051,7 +1086,7 @@ namespace umbraco.cms.businesslogic.web { if (d.Published) x.AppendChild(d.ToXml(xd, true)); - } + } } return x; @@ -1080,7 +1115,7 @@ namespace umbraco.cms.businesslogic.web // attributes x.Attributes.Append(addAttribute(xd, "id", Id.ToString())); -// x.Attributes.Append(addAttribute(xd, "version", Version.ToString())); + // x.Attributes.Append(addAttribute(xd, "version", Version.ToString())); if (Level > 1) x.Attributes.Append(addAttribute(xd, "parentID", Parent.Id.ToString())); else @@ -1088,8 +1123,8 @@ namespace umbraco.cms.businesslogic.web x.Attributes.Append(addAttribute(xd, "level", Level.ToString())); x.Attributes.Append(addAttribute(xd, "writerID", _writer.Id.ToString())); x.Attributes.Append(addAttribute(xd, "creatorID", _creator.Id.ToString())); - if (ContentType != null) - x.Attributes.Append(addAttribute(xd, "nodeType", ContentType.Id.ToString())); + if (ContentType != null) + x.Attributes.Append(addAttribute(xd, "nodeType", ContentType.Id.ToString())); x.Attributes.Append(addAttribute(xd, "template", _template.ToString())); x.Attributes.Append(addAttribute(xd, "sortOrder", sortOrder.ToString())); x.Attributes.Append(addAttribute(xd, "createDate", CreateDateTime.ToString("s"))); @@ -1098,8 +1133,8 @@ namespace umbraco.cms.businesslogic.web x.Attributes.Append(addAttribute(xd, "urlName", url.FormatUrl(urlName.ToLower()))); x.Attributes.Append(addAttribute(xd, "writerName", _writer.Name)); x.Attributes.Append(addAttribute(xd, "creatorName", _creator.Name.ToString())); - if (ContentType != null && UmbracoSettings.UseLegacyXmlSchema) - x.Attributes.Append(addAttribute(xd, "nodeTypeAlias", ContentType.Alias)); + if (ContentType != null && UmbracoSettings.UseLegacyXmlSchema) + x.Attributes.Append(addAttribute(xd, "nodeTypeAlias", ContentType.Alias)); x.Attributes.Append(addAttribute(xd, "path", Path)); if (!UmbracoSettings.UseLegacyXmlSchema) @@ -1115,7 +1150,7 @@ namespace umbraco.cms.businesslogic.web { x.AppendChild(d.ToXml(xd, true)); } - + } } @@ -1144,6 +1179,24 @@ namespace umbraco.cms.businesslogic.web } + #region XmlPreivew + + public override XmlNode ToPreviewXml(XmlDocument xd) + { + if (!PreviewExists(Version)) + { + SaveXmlPreview(xd); + } + return GetPreviewXml(xd, Version); + } + + protected void SaveXmlPreview(XmlDocument xd) + { + savePreviewXml(generateXmlWithoutSaving(xd), Version); + } + + #endregion + private XmlAttribute addAttribute(XmlDocument Xd, string Name, string Value) { XmlAttribute temp = Xd.CreateAttribute(Name); @@ -1161,7 +1214,7 @@ namespace umbraco.cms.businesslogic.web ArrayList tmp = new ArrayList(); using (IRecordsReader dr = SqlHelper.ExecuteReader( - string.Format(m_SQLOptimizedChildren, "umbracoNode.parentID = @parentId", "umbracoNode.sortOrder"), + string.Format(m_SQLOptimizedChildren, "umbracoNode.parentID = @parentId", "umbracoNode.sortOrder"), SqlHelper.CreateParameter("@parentId", NodeId))) { while (dr.Read()) @@ -1170,34 +1223,34 @@ namespace umbraco.cms.businesslogic.web bool _hc = false; if (dr.GetInt("children") > 0) _hc = true; - int? masterContentType = null; - if (!dr.IsNull("masterContentType")) - masterContentType = dr.GetInt("masterContentType"); + 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")); + , 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); } } Document[] retval = new Document[tmp.Count]; - for (int i = 0; i < tmp.Count; i ++) - retval[i] = (Document) tmp[i]; + for (int i = 0; i < tmp.Count; i++) + retval[i] = (Document)tmp[i]; return retval; } @@ -1205,14 +1258,14 @@ namespace umbraco.cms.businesslogic.web 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, string contentTypeAlias, string contentTypeThumb, - string contentTypeDesc, int? masterContentType, int contentTypeId) + string contentTypeDesc, int? masterContentType, int contentTypeId) { SetupNodeForTree(uniqueId, _objectType, level, parentId, user, path, text, createDate, hasChildren); _published = publish; _updated = updateDate; - ContentType = new ContentType(contentTypeId, contentTypeAlias, icon, contentTypeThumb, masterContentType); - ContentTypeIcon = icon; + ContentType = new ContentType(contentTypeId, contentTypeAlias, icon, contentTypeThumb, masterContentType); + ContentTypeIcon = icon; VersionDate = versionDate; } @@ -1221,7 +1274,7 @@ namespace umbraco.cms.businesslogic.web XmlDocument xd = new XmlDocument(); SqlHelper.ExecuteNonQuery("truncate table cmsContentXml"); IRecordsReader dr = SqlHelper.ExecuteReader("select nodeId from cmsDocument where published = 1"); - + while (dr.Read()) { try @@ -1237,6 +1290,26 @@ namespace umbraco.cms.businesslogic.web dr.Close(); } + public static void RegeneratePreviews() + { + XmlDocument xd = new XmlDocument(); + IRecordsReader dr = SqlHelper.ExecuteReader("select nodeId from cmsDocument"); + + while (dr.Read()) + { + try + { + new Document(dr.GetInt("nodeId")).SaveXmlPreview(xd); + } + catch (Exception ee) + { + Log.Add(LogTypes.Error, User.GetUser(0), dr.GetInt("nodeId"), + string.Format("Error generating preview xml: {0}", ee)); + } + } + dr.Close(); + } + /// /// Retrieve a list of documents with an expirationdate greater than today /// @@ -1252,7 +1325,7 @@ namespace umbraco.cms.businesslogic.web dr.Close(); Document[] retval = new Document[docs.Count]; - for (int i = 0; i < docs.Count; i++) retval[i] = new Document((int) docs[i]); + for (int i = 0; i < docs.Count; i++) retval[i] = new Document((int)docs[i]); return retval; } @@ -1268,14 +1341,28 @@ namespace umbraco.cms.businesslogic.web while (dr.Read()) docs.Add(dr.GetInt("nodeId")); dr.Close(); - + Document[] retval = new Document[docs.Count]; - for (int i = 0; i < docs.Count; i++) retval[i] = new Document((int) docs[i]); - + for (int i = 0; i < docs.Count; i++) retval[i] = new Document((int)docs[i]); + return retval; } + public override List GetNodesForPreview(bool childrenOnly) + { + List nodes = new List(); + + string pathExp = childrenOnly ? Path + ",%" : Path; + + IRecordsReader dr = SqlHelper.ExecuteReader(String.Format(m_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(); + + return nodes; + } + /// /// Imports (create) a document from a xmlrepresentation of a document, used by the packager /// @@ -1294,7 +1381,7 @@ namespace umbraco.cms.businesslogic.web // Properties foreach (XmlElement n in Source.SelectNodes("data")) - { + { Property prop = d.getProperty(n.GetAttribute("alias")); string propValue = xmlHelper.GetNodeValue(n); @@ -1338,7 +1425,7 @@ namespace umbraco.cms.businesslogic.web prop.Value = propValue; } } - + // Subpages foreach (XmlElement n in Source.SelectNodes("node")) Import(d.Id, Creator, n); @@ -1394,9 +1481,12 @@ namespace umbraco.cms.businesslogic.web /// Raises the event. /// /// The instance containing the event data. - protected internal new virtual void FireBeforeSave(SaveEventArgs e) { - if (BeforeSave != null) { - BeforeSave(this, e); } + protected internal new virtual void FireBeforeSave(SaveEventArgs e) + { + if (BeforeSave != null) + { + BeforeSave(this, e); + } } /// @@ -1407,8 +1497,10 @@ namespace umbraco.cms.businesslogic.web /// Raises the event. /// /// The instance containing the event data. - protected virtual void FireAfterSave(SaveEventArgs e) { - if (AfterSave != null) { + protected virtual void FireAfterSave(SaveEventArgs e) + { + if (AfterSave != null) + { AfterSave(this, e); } } @@ -1422,7 +1514,8 @@ namespace umbraco.cms.businesslogic.web /// Raises the event. /// /// The instance containing the event data. - protected virtual void OnNew(NewEventArgs e) { + protected virtual void OnNew(NewEventArgs e) + { if (New != null) New(this, e); } @@ -1445,7 +1538,8 @@ namespace umbraco.cms.businesslogic.web /// Raises the event. /// /// The instance containing the event data. - protected virtual void FireBeforeDelete(DeleteEventArgs e) { + protected virtual void FireBeforeDelete(DeleteEventArgs e) + { if (BeforeDelete != null) BeforeDelete(this, e); } @@ -1458,7 +1552,8 @@ namespace umbraco.cms.businesslogic.web /// Raises the event. /// /// The instance containing the event data. - protected virtual void FireAfterDelete(DeleteEventArgs e) { + protected virtual void FireAfterDelete(DeleteEventArgs e) + { if (AfterDelete != null) AfterDelete(this, e); } @@ -1472,7 +1567,8 @@ namespace umbraco.cms.businesslogic.web /// Raises the event. /// /// The instance containing the event data. - protected virtual void FireBeforeMoveToTrash(MoveToTrashEventArgs e) { + protected virtual void FireBeforeMoveToTrash(MoveToTrashEventArgs e) + { if (BeforeMoveToTrash != null) BeforeMoveToTrash(this, e); } @@ -1486,7 +1582,8 @@ namespace umbraco.cms.businesslogic.web /// Fires the after move to trash. /// /// The instance containing the event data. - protected virtual void FireAfterMoveToTrash(MoveToTrashEventArgs e) { + protected virtual void FireAfterMoveToTrash(MoveToTrashEventArgs e) + { if (AfterMoveToTrash != null) AfterMoveToTrash(this, e); } @@ -1555,7 +1652,8 @@ namespace umbraco.cms.businesslogic.web /// Raises the event. /// /// The instance containing the event data. - protected virtual void FireBeforeUnPublish(UnPublishEventArgs e) { + protected virtual void FireBeforeUnPublish(UnPublishEventArgs e) + { if (BeforeUnPublish != null) BeforeUnPublish(this, e); } @@ -1568,7 +1666,8 @@ namespace umbraco.cms.businesslogic.web /// Raises the event. /// /// The instance containing the event data. - protected virtual void FireAfterUnPublish(UnPublishEventArgs e) { + protected virtual void FireAfterUnPublish(UnPublishEventArgs e) + { if (AfterUnPublish != null) AfterUnPublish(this, e); } @@ -1581,7 +1680,8 @@ namespace umbraco.cms.businesslogic.web /// Raises the event. /// /// The instance containing the event data. - protected virtual void FireBeforeCopy(CopyEventArgs e) { + protected virtual void FireBeforeCopy(CopyEventArgs e) + { if (BeforeCopy != null) BeforeCopy(this, e); } @@ -1594,7 +1694,8 @@ namespace umbraco.cms.businesslogic.web /// Raises the event. /// /// The instance containing the event data. - protected virtual void FireAfterCopy(CopyEventArgs e) { + protected virtual void FireAfterCopy(CopyEventArgs e) + { if (AfterCopy != null) AfterCopy(this, e); } @@ -1607,7 +1708,8 @@ namespace umbraco.cms.businesslogic.web /// Raises the event. /// /// The instance containing the event data. - protected virtual void FireBeforeRollBack(RollBackEventArgs e) { + protected virtual void FireBeforeRollBack(RollBackEventArgs e) + { if (BeforeRollBack != null) BeforeRollBack(this, e); } @@ -1620,7 +1722,8 @@ namespace umbraco.cms.businesslogic.web /// Raises the event. /// /// The instance containing the event data. - protected virtual void FireAfterRollBack(RollBackEventArgs e) { + protected virtual void FireAfterRollBack(RollBackEventArgs e) + { if (AfterRollBack != null) AfterRollBack(this, e); } diff --git a/umbraco/datalayer/SqlHelpers/SqlServer/Sql/Total.sql b/umbraco/datalayer/SqlHelpers/SqlServer/Sql/Total.sql index 595f6bc53c..0741a970a0 100644 --- a/umbraco/datalayer/SqlHelpers/SqlServer/Sql/Total.sql +++ b/umbraco/datalayer/SqlHelpers/SqlServer/Sql/Total.sql @@ -997,3 +997,16 @@ IF NOT EXISTS (SELECT treeAlias from umbracoAppTree WHERE treeAlias='dynamicTree INSERT INTO umbracoAppTree (treeSilent, treeInitialize, treeSortOrder, appAlias, treeAlias, treeTitle, treeIconClosed, treeIconOpen, treeHandlerAssembly, treeHandlerType) VALUES (0, 0, 0, 'content', 'dynamicTree', 'DynamicTree', 'folder.gif', 'folder_o.gif', 'umbraco', 'cms.presentation.Trees.dynamicTree') ; +/* PREVIEW */ +CREATE TABLE [dbo].[cmsPreviewXml]( + [nodeId] [int] NOT NULL, + [versionId] [uniqueidentifier] NOT NULL, + [timestamp] [datetime] NOT NULL, + [xml] [ntext] NOT NULL, + CONSTRAINT [PK_cmsContentPreviewXml] PRIMARY KEY CLUSTERED +( + [nodeId] ASC, + [versionId] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] +; \ No newline at end of file diff --git a/umbraco/datalayer/SqlHelpers/SqlServer/Sql/Version4_1_Upgrade.sql b/umbraco/datalayer/SqlHelpers/SqlServer/Sql/Version4_1_Upgrade.sql new file mode 100644 index 0000000000..b0e29cd266 --- /dev/null +++ b/umbraco/datalayer/SqlHelpers/SqlServer/Sql/Version4_1_Upgrade.sql @@ -0,0 +1,11 @@ +CREATE TABLE [dbo].[cmsPreviewXml]( + [nodeId] [int] NOT NULL, + [versionId] [uniqueidentifier] NOT NULL, + [timestamp] [datetime] NOT NULL, + [xml] [ntext] NOT NULL, + CONSTRAINT [PK_cmsContentPreviewXml] PRIMARY KEY CLUSTERED +( + [nodeId] ASC, + [versionId] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] diff --git a/umbraco/datalayer/umbraco.datalayer.csproj b/umbraco/datalayer/umbraco.datalayer.csproj index 32d7fab756..452cda0059 100644 --- a/umbraco/datalayer/umbraco.datalayer.csproj +++ b/umbraco/datalayer/umbraco.datalayer.csproj @@ -141,6 +141,7 @@ + diff --git a/umbraco/presentation/UmbracoContext.cs b/umbraco/presentation/UmbracoContext.cs index 2479c664f1..7647fd23ec 100644 --- a/umbraco/presentation/UmbracoContext.cs +++ b/umbraco/presentation/UmbracoContext.cs @@ -4,6 +4,9 @@ using umbraco.presentation.LiveEditing; using umbraco.BasePages; using umbraco.cms.businesslogic.web; using System.Xml.Linq; +using umbraco.BusinessLogic; +using System.Xml; +using umbraco.presentation.preview; namespace umbraco.presentation { @@ -16,6 +19,7 @@ namespace umbraco.presentation private UmbracoRequest m_Request; private UmbracoResponse m_Response; private HttpContext m_HttpContext; + private XmlDocument previewDocument; /// /// Creates a new Umbraco context. @@ -63,6 +67,31 @@ namespace umbraco.presentation } } + /// + /// Determines whether the current user is in a preview mode + /// + public virtual bool InPreviewMode + { + get + { + return !String.IsNullOrEmpty(StateHelper.GetCookieValue("PreviewSet")); + } + } + + public XmlDocument GetXml() + { + if (InPreviewMode) + { + PreviewContent pc = new PreviewContent(new Guid(StateHelper.GetCookieValue("PreviewSet"))); + pc.LoadPreviewset(); + return pc.XmlContent; + } + else + { + return content.Instance.XmlContent; + } + } + /// /// Determines whether the current user has the specified permission on the current page. /// diff --git a/umbraco/presentation/content.cs b/umbraco/presentation/content.cs index ccd290d0c5..131f92df36 100644 --- a/umbraco/presentation/content.cs +++ b/umbraco/presentation/content.cs @@ -191,7 +191,7 @@ namespace umbraco } } - private void TransferValuesFromDocumentXmlToPublishedXml(XmlNode DocumentNode, XmlNode PublishedNode) + public static void TransferValuesFromDocumentXmlToPublishedXml(XmlNode DocumentNode, XmlNode PublishedNode) { // Remove all attributes and data nodes from the published node PublishedNode.Attributes.RemoveAll(); @@ -215,48 +215,15 @@ namespace umbraco /// /// /// - private void PublishNodeDo(Document d, XmlDocument xmlContentCopy) + public static void PublishNodeDo(Document d, XmlDocument xmlContentCopy, bool updateSitemapProvider) { // check if document *is* published, it could be unpublished by an event if (d.Published) { - - // Find the document in the xml cache - XmlNode x = xmlContentCopy.GetElementById(d.Id.ToString()); - - // Find the parent (used for sortering and maybe creation of new node) - XmlNode parentNode; - if (d.Level == 1) - parentNode = xmlContentCopy.DocumentElement; - else - parentNode = xmlContentCopy.GetElementById(d.Parent.Id.ToString()); - - if (parentNode != null) - { - if (x == null) - { - x = d.ToXml(xmlContentCopy, false); - parentNode.AppendChild(x); - } - else - TransferValuesFromDocumentXmlToPublishedXml(d.ToXml(xmlContentCopy, false), x); - - XmlNodeList childNodes = parentNode.SelectNodes("./node"); - - // Maybe sort the nodes if the added node has a lower sortorder than the last - if (childNodes.Count > 0) - { - int siblingSortOrder = int.Parse(childNodes[childNodes.Count - 1].Attributes.GetNamedItem("sortOrder").Value); - int currentSortOrder = int.Parse(x.Attributes.GetNamedItem("sortOrder").Value); - if (childNodes.Count > 1 && siblingSortOrder > currentSortOrder) - { - SortNodes(ref parentNode); - } - } - } + AppendDocumentXml(d.Id, d.Level, d.Parent.Id, getPreviewOrPublishedNode(d, xmlContentCopy, false), xmlContentCopy); // update sitemapprovider - if (SiteMap.Provider is presentation.nodeFactory.UmbracoSiteMapProvider) + if (updateSitemapProvider && SiteMap.Provider is presentation.nodeFactory.UmbracoSiteMapProvider) { presentation.nodeFactory.UmbracoSiteMapProvider prov = (presentation.nodeFactory.UmbracoSiteMapProvider)SiteMap.Provider; prov.UpdateNode(new umbraco.presentation.nodeFactory.Node(d.Id)); @@ -264,6 +231,59 @@ namespace umbraco } } + public static void AppendDocumentXml(int id, int level, int parentId, XmlNode docXml, XmlDocument xmlContentCopy) + { + + + // Find the document in the xml cache + XmlNode x = xmlContentCopy.GetElementById(id.ToString()); + + // Find the parent (used for sortering and maybe creation of new node) + XmlNode parentNode; + if (level == 1) + parentNode = xmlContentCopy.DocumentElement; + else + parentNode = xmlContentCopy.GetElementById(parentId.ToString()); + + if (parentNode != null) + { + if (x == null) + { + x = docXml; + parentNode.AppendChild(x); + } + else + TransferValuesFromDocumentXmlToPublishedXml(docXml, x); + + // TODO: Update with new schema! + string xpath = UmbracoSettings.UseLegacyXmlSchema ? "./node" : "./* [@id]"; + XmlNodeList childNodes = parentNode.SelectNodes(xpath); + + // Maybe sort the nodes if the added node has a lower sortorder than the last + if (childNodes.Count > 0) + { + int siblingSortOrder = int.Parse(childNodes[childNodes.Count - 1].Attributes.GetNamedItem("sortOrder").Value); + int currentSortOrder = int.Parse(x.Attributes.GetNamedItem("sortOrder").Value); + if (childNodes.Count > 1 && siblingSortOrder > currentSortOrder) + { + SortNodes(ref parentNode); + } + } + } + } + + private static XmlNode getPreviewOrPublishedNode(Document d, XmlDocument xmlContentCopy, bool isPreview) + { + if (isPreview) + { + return d.ToPreviewXml(xmlContentCopy); + } + else + { + return d.ToXml(xmlContentCopy, false); + } + } + /// /// Sorts the documents. /// @@ -273,12 +293,13 @@ namespace umbraco XmlNode n = parentNode.CloneNode(true); // remove all children from original node - foreach (XmlNode child in parentNode.SelectNodes("./node")) + string xpath = UmbracoSettings.UseLegacyXmlSchema ? "./node" : "./* [@id]"; + foreach (XmlNode child in parentNode.SelectNodes(xpath)) parentNode.RemoveChild(child); XPathNavigator nav = n.CreateNavigator(); - XPathExpression expr = nav.Compile("./node"); + XPathExpression expr = nav.Compile(xpath); expr.AddSort("@sortOrder", XmlSortOrder.Ascending, XmlCaseOrder.None, "", XmlDataType.Number); XPathNodeIterator iterator = nav.Select(expr); while (iterator.MoveNext()) @@ -322,12 +343,12 @@ namespace umbraco { XmlDocument xmlContentCopy = CloneXmlDoc(XmlContentInternal); - PublishNodeDo(d, xmlContentCopy); + PublishNodeDo(d, xmlContentCopy, true); XmlContentInternal = xmlContentCopy; } else { - PublishNodeDo(d, XmlContentInternal); + PublishNodeDo(d, XmlContentInternal, true); XmlContentInternal = _xmlContent; } @@ -372,7 +393,7 @@ namespace umbraco XmlDocument xmlContentCopy = CloneXmlDoc(XmlContentInternal); foreach (Document d in Documents) { - PublishNodeDo(d, xmlContentCopy); + PublishNodeDo(d, xmlContentCopy, true); } XmlContentInternal = xmlContentCopy; ClearContextCache(); @@ -797,7 +818,7 @@ order by umbracoNode.level, umbracoNode.sortOrder"; catch (OutOfMemoryException) { Log.Add(LogTypes.Error, User.GetUser(0), -1, - string.Format("Error Republishin: Out Of Memory. Parents: {0}, Nodes: {1}", + string.Format("Error Republishing: Out Of Memory. Parents: {0}, Nodes: {1}", parents.Count, nodes.Count)); } catch (Exception ee) diff --git a/umbraco/presentation/default.aspx.cs b/umbraco/presentation/default.aspx.cs index 979fd10488..8300fa15d3 100644 --- a/umbraco/presentation/default.aspx.cs +++ b/umbraco/presentation/default.aspx.cs @@ -109,7 +109,7 @@ namespace umbraco } else { - m_umbRequest = new requestHandler(content.Instance.XmlContent, m_tmp); + m_umbRequest = new requestHandler(UmbracoContext.Current.GetXml(), m_tmp); Trace.Write("umbracoInit", "Done handling request"); if (m_umbRequest.currentPage != null) { diff --git a/umbraco/presentation/install/steps/validatePermissions.ascx.cs b/umbraco/presentation/install/steps/validatePermissions.ascx.cs index c5c4434ccf..162a1b6d6a 100644 --- a/umbraco/presentation/install/steps/validatePermissions.ascx.cs +++ b/umbraco/presentation/install/steps/validatePermissions.ascx.cs @@ -10,7 +10,7 @@ namespace umbraco.presentation.install.steps /// public partial class validatePermissions : UserControl { - private string[] permissionDirs = {SystemDirectories.Css, SystemDirectories.Config, SystemDirectories.Data, SystemDirectories.Media, SystemDirectories.Masterpages, SystemDirectories.Xslt, SystemDirectories.Usercontrols}; + private string[] permissionDirs = {SystemDirectories.Css, SystemDirectories.Config, SystemDirectories.Data, SystemDirectories.Media, SystemDirectories.Masterpages, SystemDirectories.Xslt, SystemDirectories.Usercontrols, SystemDirectories.Preview}; private string[] permissionFiles = { }; private string[] packagesPermissionsDirs = {SystemDirectories.Bin, SystemDirectories.Umbraco, SystemDirectories.Usercontrols, SystemDirectories.Packages}; diff --git a/umbraco/presentation/library.cs b/umbraco/presentation/library.cs index bf7e30b0d8..c4b37db4f2 100644 --- a/umbraco/presentation/library.cs +++ b/umbraco/presentation/library.cs @@ -25,6 +25,7 @@ using umbraco.DataLayer; using System.Web.Security; using umbraco.cms.businesslogic.language; using umbraco.IO; +using umbraco.presentation; namespace umbraco { @@ -377,7 +378,6 @@ namespace umbraco private static string niceUrlDo(int nodeID, int startNodeDepth) { - XmlDocument umbracoXML = content.Instance.XmlContent; bool directoryUrls = GlobalSettings.UseDirectoryUrls; string baseUrl = SystemDirectories.Root; // SystemDirectories.Umbraco; //baseUrl = baseUrl.Substring(0, baseUrl.LastIndexOf("/")); @@ -390,14 +390,14 @@ namespace umbraco // Find path from nodeID String tempUrl = ""; - XmlElement node = umbracoXML.GetElementById(nodeID.ToString()); + XmlElement node = UmbracoContext.Current.GetXml().GetElementById(nodeID.ToString()); String[] splitpath = null; if (node != null) { try { splitpath = - umbracoXML.GetElementById(nodeID.ToString()).Attributes.GetNamedItem("path").Value.ToString(). + node.Attributes.GetNamedItem("path").Value.ToString(). Split(",".ToCharArray()); int startNode = startNodeDepth; @@ -471,7 +471,7 @@ namespace umbraco if (!UmbracoSettings.UseDomainPrefixes || domains.Length == 0) tempUrl += "/" + url.FormatUrl( - content.Instance.XmlContent.GetElementById(DocumentId.ToString()).Attributes.GetNamedItem + UmbracoContext.Current.GetXml().GetElementById(DocumentId.ToString()).Attributes.GetNamedItem ("urlName").Value); else { @@ -493,7 +493,7 @@ namespace umbraco else tempUrl = "/" + url.FormatUrl( - content.Instance.XmlContent.GetElementById(DocumentId.ToString()).Attributes. + UmbracoContext.Current.GetXml().GetElementById(DocumentId.ToString()).Attributes. GetNamedItem("urlName").Value); } else @@ -517,7 +517,7 @@ namespace umbraco /// Returns a string with the data from the given element of a node public static string GetItem(int nodeID, String alias) { - XmlDocument umbracoXML = content.Instance.XmlContent; + XmlDocument umbracoXML = UmbracoContext.Current.GetXml(); if (umbracoXML.GetElementById(nodeID.ToString()) != null) if ( @@ -1563,7 +1563,7 @@ namespace umbraco { try { - XPathNavigator xp = content.Instance.XmlContent.CreateNavigator(); + XPathNavigator xp = UmbracoContext.Current.GetXml().CreateNavigator(); xp.MoveToId(HttpContext.Current.Items["pageID"].ToString()); return xp.Select("."); } @@ -1583,9 +1583,9 @@ namespace umbraco /// Returns the node with the specified id as xml in the form of a XPathNodeIterator public static XPathNodeIterator GetXmlNodeById(string id) { - if (content.Instance.XmlContent.GetElementById(id) != null) + if (UmbracoContext.Current.GetXml().GetElementById(id) != null) { - XPathNavigator xp = content.Instance.XmlContent.CreateNavigator(); + XPathNavigator xp = UmbracoContext.Current.GetXml().CreateNavigator(); xp.MoveToId(id); return xp.Select("."); } @@ -1615,7 +1615,7 @@ namespace umbraco /// Returns the entire umbraco Xml cache as a XPathNodeIterator public static XPathNodeIterator GetXmlAll() { - XPathNavigator xp = content.Instance.XmlContent.CreateNavigator(); + XPathNavigator xp = UmbracoContext.Current.GetXml().CreateNavigator(); return xp.Select("/root"); } @@ -1708,10 +1708,10 @@ namespace umbraco public static string QueryForNode(string id) { string XPathQuery = string.Empty; - if (content.Instance.XmlContent.GetElementById(id) != null) + if (UmbracoContext.Current.GetXml().GetElementById(id) != null) { string[] path = - content.Instance.XmlContent.GetElementById(id).Attributes["path"].Value.Split((",").ToCharArray()); + UmbracoContext.Current.GetXml().GetElementById(id).Attributes["path"].Value.Split((",").ToCharArray()); for (int i = 1; i < path.Length; i++) { if (i > 1) diff --git a/umbraco/presentation/requestHandler.cs b/umbraco/presentation/requestHandler.cs index 79ebf3ac92..8f431d571f 100644 --- a/umbraco/presentation/requestHandler.cs +++ b/umbraco/presentation/requestHandler.cs @@ -163,7 +163,7 @@ namespace umbraco { return _tempQuery; } - public requestHandler(XmlDocument _umbracoContent, String url) { + public requestHandler(XmlDocument umbracoContent, String url) { HttpContext.Current.Trace.Write("request handler", "current url '" + url + "'"); bool getByID = false; string currentDomain = HttpContext.Current.Request.ServerVariables["SERVER_NAME"]; @@ -218,14 +218,14 @@ namespace umbraco { _pageXPathQuery)); if (getByID) - currentPage = content.Instance.XmlContent.GetElementById(_pageXPathQuery.Trim()); + currentPage = umbracoContent.GetElementById(_pageXPathQuery.Trim()); else { HttpContext.Current.Trace.Write("umbracoRequestHandler", "pageXPathQueryStart: '" + pageXPathQueryStart + "'"); - currentPage = content.Instance.XmlContent.SelectSingleNode(pageXPathQueryStart + _pageXPathQuery); + currentPage = umbracoContent.SelectSingleNode(pageXPathQueryStart + _pageXPathQuery); if (currentPage == null) { // If no node found, then try with a relative page query - currentPage = content.Instance.XmlContent.SelectSingleNode("/" + _pageXPathQuery); + currentPage = umbracoContent.SelectSingleNode("/" + _pageXPathQuery); } // Add to url cache @@ -277,7 +277,7 @@ namespace umbraco { typeInstance.Execute(url); if (typeInstance.redirectID > 0) { int redirectID = typeInstance.redirectID; - currentPage = content.Instance.XmlContent.GetElementById(redirectID.ToString()); + currentPage = umbracoContent.GetElementById(redirectID.ToString()); HttpContext.Current.Trace.Write("notFoundHandler", string.Format( "NotFoundHandler '{0}.{1} found node matching {2} with id: {3}", @@ -313,7 +313,7 @@ namespace umbraco { int internalRedirectId = 0; if (int.TryParse(internalRedirect.FirstChild.Value, out internalRedirectId) && internalRedirectId > 0) { currentPage = - content.Instance.XmlContent.GetElementById( + umbracoContent.GetElementById( internalRedirectId.ToString()); HttpContext.Current.Trace.Write("internalRedirection", "Redirecting to " + internalRedirect.FirstChild.Value); } else @@ -333,7 +333,7 @@ namespace umbraco { if (System.Web.Security.Membership.GetUser() == null || !library.IsLoggedOn()) { HttpContext.Current.Trace.Write("umbracoRequestHandler", "Not logged in - redirecting to login page..."); - currentPage = content.Instance.XmlContent.GetElementById(Access.GetLoginPage(currentPage.Attributes.GetNamedItem("path").Value).ToString()); + currentPage = umbracoContent.GetElementById(Access.GetLoginPage(currentPage.Attributes.GetNamedItem("path").Value).ToString()); } else { if (System.Web.Security.Membership.GetUser() != null && !Access.HasAccces(int.Parse(currentPage.Attributes.GetNamedItem("id").Value), System.Web.Security.Membership.GetUser().ProviderUserKey)) { diff --git a/umbraco/presentation/umbraco.presentation.csproj b/umbraco/presentation/umbraco.presentation.csproj index 622ac0312e..f72ff0c2b3 100644 --- a/umbraco/presentation/umbraco.presentation.csproj +++ b/umbraco/presentation/umbraco.presentation.csproj @@ -497,9 +497,17 @@ DLRScripting.ascx + + Preview.aspx + ASPXCodeBehind + + + Preview.aspx + Code + @@ -1461,6 +1469,8 @@ + + @@ -2795,6 +2805,8 @@ + + @@ -2832,4 +2844,4 @@ - \ No newline at end of file + diff --git a/umbraco/presentation/umbraco/dialogs/Preview.aspx b/umbraco/presentation/umbraco/dialogs/Preview.aspx new file mode 100644 index 0000000000..c93b21f8c8 --- /dev/null +++ b/umbraco/presentation/umbraco/dialogs/Preview.aspx @@ -0,0 +1,19 @@ +<%@ Page Language="C#" AutoEventWireup="true" MasterPageFile="../masterpages/umbracoDialog.Master" CodeBehind="Preview.aspx.cs" Inherits="umbraco.presentation.dialogs.Preview" %> +<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %> + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/umbraco/presentation/umbraco/dialogs/Preview.aspx.cs b/umbraco/presentation/umbraco/dialogs/Preview.aspx.cs new file mode 100644 index 0000000000..d0bf31aa25 --- /dev/null +++ b/umbraco/presentation/umbraco/dialogs/Preview.aspx.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Web; +using System.Web.Security; +using System.Web.UI; +using System.Web.UI.HtmlControls; +using System.Web.UI.WebControls; +using System.Web.UI.WebControls.WebParts; +using System.Xml.Linq; +using umbraco.cms.businesslogic.web; +using umbraco.presentation.preview; +using umbraco.BusinessLogic; + +namespace umbraco.presentation.dialogs +{ + public partial class Preview : BasePages.UmbracoEnsuredPage + { + protected void Page_Load(object sender, EventArgs e) + { + Document d = new Document(int.Parse(helper.Request("id"))); + bool includeChildren = !String.IsNullOrEmpty(UmbracoContext.Current.Request["children"]) ? true : false; + PreviewContent pc = new PreviewContent(Guid.NewGuid()); + pc.PrepareDocument(base.getUser(), d, includeChildren); + pc.SavePreviewSet(); + docLit.Text = d.Text; + changeSetUrl.Text = pc.PreviewsetPath; + StateHelper.SetCookieValue("PreviewSet", pc.PreviewSet.ToString()); + } + } +} diff --git a/umbraco/presentation/umbraco/dialogs/Preview.aspx.designer.cs b/umbraco/presentation/umbraco/dialogs/Preview.aspx.designer.cs new file mode 100644 index 0000000000..2d311c5655 --- /dev/null +++ b/umbraco/presentation/umbraco/dialogs/Preview.aspx.designer.cs @@ -0,0 +1,70 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.4927 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace umbraco.presentation.dialogs { + + + public partial class Preview { + + /// + /// feedback1 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::umbraco.uicontrols.Feedback feedback1; + + /// + /// pane_form control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::umbraco.uicontrols.Pane pane_form; + + /// + /// PropertyPanel1 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::umbraco.uicontrols.PropertyPanel PropertyPanel1; + + /// + /// docLit control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Literal docLit; + + /// + /// PropertyPanel2 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::umbraco.uicontrols.PropertyPanel PropertyPanel2; + + /// + /// changeSetUrl control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Literal changeSetUrl; + } +} diff --git a/umbraco/presentation/umbraco/dialogs/republish.aspx.cs b/umbraco/presentation/umbraco/dialogs/republish.aspx.cs index 2fda58d88e..0359343dce 100644 --- a/umbraco/presentation/umbraco/dialogs/republish.aspx.cs +++ b/umbraco/presentation/umbraco/dialogs/republish.aspx.cs @@ -18,17 +18,26 @@ namespace umbraco.cms.presentation { protected void go(object sender, EventArgs e) { // re-create xml - if (helper.Request("xml") != "") { + if (helper.Request("xml") != "") + { Server.ScriptTimeout = 100000; umbraco.cms.businesslogic.web.Document.RePublishAll(); - } else if (helper.Request("refreshNodes") != "") { + } + else if (helper.Request("previews") != "") + { + Server.ScriptTimeout = 100000; + umbraco.cms.businesslogic.web.Document.RegeneratePreviews(); + } + else if (helper.Request("refreshNodes") != "") + { Server.ScriptTimeout = 100000; System.Xml.XmlDocument xd = new System.Xml.XmlDocument(); //store children array here because iterating over an Array object is very inneficient. var doc = new cms.businesslogic.web.Document(int.Parse(helper.Request("refreshNodes"))); var c = doc.Children; - foreach (cms.businesslogic.web.Document d in c) { + foreach (cms.businesslogic.web.Document d in c) + { d.XmlGenerate(xd); Response.Write("
  • Creating xml for " + d.Text + "
  • "); Response.Flush(); diff --git a/umbraco/presentation/umbraco/nodeFactory/Page.cs b/umbraco/presentation/umbraco/nodeFactory/Page.cs index e54b03163c..86dbf4d720 100644 --- a/umbraco/presentation/umbraco/nodeFactory/Page.cs +++ b/umbraco/presentation/umbraco/nodeFactory/Page.cs @@ -201,7 +201,7 @@ namespace umbraco.presentation.nodeFactory { if (NodeId != -1) _pageXmlNode = ((IHasXmlNode)library.GetXmlNodeById(NodeId.ToString()).Current).GetNode(); else { - _pageXmlNode = content.Instance.XmlContent.DocumentElement; + _pageXmlNode = UmbracoContext.Current.GetXml().DocumentElement; } initializeStructure(); diff --git a/umbraco/presentation/umbraco/preview/Preview.cs b/umbraco/presentation/umbraco/preview/Preview.cs new file mode 100644 index 0000000000..3cc9db82f5 --- /dev/null +++ b/umbraco/presentation/umbraco/preview/Preview.cs @@ -0,0 +1,76 @@ +using System; +using System.Data; +using System.Configuration; +using System.Linq; +using System.Web; +using System.Web.Security; +using System.Web.UI; +using System.Web.UI.HtmlControls; +using System.Web.UI.WebControls; +using System.Web.UI.WebControls.WebParts; +using System.Xml.Linq; +using System.Xml; +using System.IO; +using umbraco.cms.businesslogic.web; +using umbraco.BusinessLogic; +using umbraco.cms.businesslogic; + +namespace umbraco.presentation.preview +{ + public class PreviewContent + { + public XmlDocument XmlContent { get; set; } + public Guid PreviewSet { get; set; } + public string PreviewsetPath { get; set; } + private int m_userId = 0; + public PreviewContent(User user) + { + m_userId = user.Id; + } + + public void PrepareDocument(User user, Document documentObject, bool includeSubs) + { + m_userId = user.Id; + + // clone xml + XmlContent = (XmlDocument) content.Instance.XmlContent.Clone(); + + // inject current document xml + content.AppendDocumentXml(documentObject.Id, documentObject.Level, documentObject.Parent.Id, documentObject.ToPreviewXml(XmlContent), XmlContent); + + if (includeSubs) + { + foreach (CMSPreviewNode prevNode in documentObject.GetNodesForPreview(true)) + { + content.AppendDocumentXml(prevNode.NodeId, prevNode.Level, prevNode.ParentId, XmlContent.ReadNode(XmlReader.Create(new StringReader(prevNode.Xml))), XmlContent); + } + } + + } + + public PreviewContent(Guid previewSet) + { + updatePreviewPaths(previewSet); + } + + private void updatePreviewPaths(Guid previewSet) + { + PreviewSet = previewSet; + PreviewsetPath = IO.IOHelper.MapPath( + Path.Combine( + Path.Combine(IO.SystemDirectories.Data, "previews"), + PreviewSet + ".config")); + } + + public void LoadPreviewset() + { + XmlContent = new XmlDocument(); + XmlContent.Load(PreviewsetPath); + } + + public void SavePreviewSet() + { + XmlContent.Save(PreviewsetPath); + } + } +} diff --git a/umbraco/presentation/web.config.UMBRACOHUMMER.xslt b/umbraco/presentation/web.config.UMBRACOHUMMER.xslt new file mode 100644 index 0000000000..ad0dfc9065 --- /dev/null +++ b/umbraco/presentation/web.config.UMBRACOHUMMER.xslt @@ -0,0 +1,25 @@ + + + + + + + server=.\sqlexpress;database=41beta2;integrated security=false;user id=DBUSER;pwd=DBPASSWORD + + + + 4.1.0.beta + + + + + + + + + + + + + +