diff --git a/umbraco/cms/businesslogic/CMSNode.cs b/umbraco/cms/businesslogic/CMSNode.cs
index de624c73a4..0d099fd145 100644
--- a/umbraco/cms/businesslogic/CMSNode.cs
+++ b/umbraco/cms/businesslogic/CMSNode.cs
@@ -805,7 +805,6 @@ order by level,sortOrder";
HasChildren = hasChildren;
}
-
///
/// Updates the temp path for the content tree.
///
diff --git a/umbraco/cms/businesslogic/Content.cs b/umbraco/cms/businesslogic/Content.cs
index f8834a588c..99febce984 100644
--- a/umbraco/cms/businesslogic/Content.cs
+++ b/umbraco/cms/businesslogic/Content.cs
@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
-
+using System.Linq;
using System.Data;
using System.Xml;
@@ -12,27 +12,31 @@ using umbraco.cms.helpers;
namespace umbraco.cms.businesslogic
{
- ///
- /// Content is an intermediate layer between CMSNode and class'es which will use generic data.
- ///
- /// Content is a datastructure that holds generic data defined in its corresponding ContentType. Content can in some
- /// sence be compared to a row in a database table, it's contenttype hold a definition of the columns and the Content
- /// contains the data
- ///
- /// Note that Content data in umbraco is *not* tablular but in a treestructure.
- ///
- ///
- public class Content : CMSNode
- {
- private Guid _version;
- private DateTime _versionDate;
- private XmlNode _xml;
- private bool _versionDateInitialized;
+ ///
+ /// Content is an intermediate layer between CMSNode and class'es which will use generic data.
+ ///
+ /// Content is a datastructure that holds generic data defined in its corresponding ContentType. Content can in some
+ /// sence be compared to a row in a database table, it's contenttype hold a definition of the columns and the Content
+ /// contains the data
+ ///
+ /// Note that Content data in umbraco is *not* tablular but in a treestructure.
+ ///
+ ///
+ public class Content : CMSNode
+ {
+ #region Private Members
+
+ private Guid _version;
+ private DateTime _versionDate;
+ private XmlNode _xml;
+ private bool _versionDateInitialized;
private string _contentTypeIcon;
private ContentType _contentType;
- private bool _propertiesInitialized = false;
- private Properties _properties = new Properties();
+ private Properties m_LoadedProperties = null;
+ #endregion
+
+ #region Constructors
///
///
///
@@ -51,51 +55,71 @@ namespace umbraco.cms.businesslogic
///
///
protected Content(Guid id) : base(id) { }
+ #endregion
- ///
- /// 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)
+ #region Static Methods
+
+ ///
+ /// Retrive a list of Content sharing the ContentType
+ ///
+ /// The ContentType
+ /// A list of Content objects sharing the ContentType defined.
+ public static Content[] getContentOfContentType(ContentType ct)
{
- if (_contentType == null)
- _contentType = ContentType.GetContentType(InitContentType);
- _version = InitVersion;
- _versionDate = InitVersionDate;
- _contentTypeIcon = InitContentTypeIcon;
+ IRecordsReader dr = SqlHelper.ExecuteReader("Select nodeId from cmsContent INNER JOIN umbracoNode ON cmsContent.nodeId = umbracoNode.id where ContentType = " + ct.Id + " ORDER BY umbracoNode.text ");
+ System.Collections.ArrayList tmp = new System.Collections.ArrayList();
+
+ while (dr.Read()) tmp.Add(dr.GetInt("nodeId"));
+ dr.Close();
+
+ Content[] retval = new Content[tmp.Count];
+ for (int i = 0; i < tmp.Count; i++) retval[i] = new Content((int)tmp[i]);
+
+ return retval;
}
- ///
+ ///
+ /// Initialize a contentobject given a version.
+ ///
+ /// The version identifier
+ /// The Content object from the given version
+ public static Content GetContentFromVersion(Guid version)
+ {
+ int tmpContentId = SqlHelper.ExecuteScalar("Select ContentId from cmsContentVersion where versionId = '" + version.ToString() + "'");
+ return new Content(tmpContentId);
+ }
+
+ #endregion
+
+ #region Public Properties
+
+ ///
/// The current Content objects ContentType, which defines the Properties of the Content (data)
///
public ContentType ContentType
{
get
{
- if (_contentType == null)
- {
- object o = SqlHelper.ExecuteScalar(
- "Select ContentType from cmsContent where nodeId=@nodeid",
- SqlHelper.CreateParameter("@nodeid", this.Id));
- if (o == null)
- return null;
- int contentTypeId;
- if(!int.TryParse(o.ToString(), out contentTypeId))
- return null;
- try
- {
- _contentType = new ContentType(contentTypeId);
- }
- catch
- {
- return null;
- }
- }
- return _contentType;
+ if (_contentType == null)
+ {
+ object o = SqlHelper.ExecuteScalar(
+ "Select ContentType from cmsContent where nodeId=@nodeid",
+ SqlHelper.CreateParameter("@nodeid", this.Id));
+ if (o == null)
+ return null;
+ int contentTypeId;
+ if (!int.TryParse(o.ToString(), out contentTypeId))
+ return null;
+ try
+ {
+ _contentType = new ContentType(contentTypeId);
+ }
+ catch
+ {
+ return null;
+ }
+ }
+ return _contentType;
}
set
{
@@ -103,16 +127,130 @@ namespace umbraco.cms.businesslogic
}
}
- public Properties GenericProperties
- {
+ ///
+ /// 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
{
- if (!_propertiesInitialized)
- InitializeProperties();
-
- return _properties;
+ if (_contentTypeIcon == null && this.ContentType != null)
+ _contentTypeIcon = this.ContentType.IconUrl;
+ return _contentTypeIcon;
}
- }
+ set
+ {
+ _contentTypeIcon = value;
+ }
+ }
+
+ ///
+ /// The createtimestamp on this version
+ ///
+ public DateTime VersionDate
+ {
+ get
+ {
+ if (!_versionDateInitialized)
+ {
+ object o = SqlHelper.ExecuteScalar(
+ "select VersionDate from cmsContentVersion where versionId = '" + this.Version.ToString() + "'");
+ if (o == null)
+ {
+ _versionDate = DateTime.Now;
+ }
+ else
+ {
+ _versionDateInitialized = DateTime.TryParse(o.ToString(), out _versionDate);
+ }
+ }
+ return _versionDate;
+ }
+ set
+ {
+ _versionDate = value;
+ _versionDateInitialized = true;
+ }
+ }
+
+ ///
+ /// Retrieve a list of generic properties of the content
+ ///
+ public Properties GenericProperties
+ {
+ get
+ {
+ EnsureProperties();
+ return m_LoadedProperties;
+ }
+ }
+
+ ///
+ /// Retrieve a list of generic properties of the content
+ ///
+ [Obsolete("Use the GenericProperties property instead")]
+ public Property[] getProperties
+ {
+ get
+ {
+ //EnsureProperties();
+ //return m_LoadedProperties.ToArray();
+
+ if (this.ContentType == null)
+ return new Property[0];
+
+ List result = new List();
+ foreach (PropertyType prop in this.ContentType.PropertyTypes)
+ {
+ if (prop == null)
+ continue;
+ Property p = getProperty(prop);
+ if (p == null)
+ continue;
+ result.Add(p);
+ }
+
+ return result.ToArray();
+ }
+ }
+
+ ///
+ /// Content is under version control, you are able to programatically create new versions
+ ///
+ public Guid Version
+ {
+ get
+ {
+ if (_version == Guid.Empty)
+ {
+ string sql = "Select versionId from cmsContentVersion where contentID = " + this.Id +
+ " order by id desc ";
+
+ using (IRecordsReader dr = SqlHelper.ExecuteReader(sql))
+ {
+ if (!dr.Read())
+ _version = Guid.Empty;
+ else
+ _version = dr.GetGuid("versionId");
+ }
+ }
+ return _version;
+ }
+ set { _version = value; }
+ }
+
+ #endregion
+
+ #region Public Methods
///
/// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility
@@ -122,297 +260,81 @@ namespace umbraco.cms.businesslogic
base.Save();
}
- ///
- /// 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
- {
- if (_contentTypeIcon == null && this.ContentType != null)
- _contentTypeIcon = this.ContentType.IconUrl;
- return _contentTypeIcon;
- }
- set
- {
- _contentTypeIcon = value;
- }
- }
-
- ///
- /// Retrieve a Property given the alias
- ///
- /// Propertyalias (defined in the documenttype)
- /// The property with the given alias
- public Property getProperty(string alias)
- {
- ContentType ct = this.ContentType;
- if(ct == null)
- return null;
- propertytype.PropertyType pt = ct.getPropertyType(alias);
- if(pt == null)
- return null;
- return getProperty(pt);
- }
-
- ///
- /// Retrieve a property given the propertytype
- ///
- /// PropertyType
- /// The property with the given propertytype
- public Property getProperty(propertytype.PropertyType pt)
- {
- object o = SqlHelper.ExecuteScalar(
- "select id from cmsPropertyData where versionId=@version and propertyTypeId=@propertyTypeId",
- SqlHelper.CreateParameter("@version", this.Version),
- SqlHelper.CreateParameter("@propertyTypeId", pt.Id));
- if(o == null)
- return null;
- int propertyId;
- if(!int.TryParse(o.ToString(), out propertyId))
- return null;
- try
- {
- return new Property(propertyId, pt);
- }
- catch
- {
- return null;
- }
- }
-
- ///
- /// The createtimestamp on this version
- ///
- public DateTime VersionDate
- {
- get
- {
- if(!_versionDateInitialized)
- {
- object o = SqlHelper.ExecuteScalar(
- "select VersionDate from cmsContentVersion where versionId = '" + this.Version.ToString() + "'");
- if(o == null)
- {
- _versionDate = DateTime.Now;
- }
- else
- {
- _versionDateInitialized = DateTime.TryParse(o.ToString(), out _versionDate);
- }
- }
- return _versionDate;
- }
- set
- {
- _versionDate = value;
- _versionDateInitialized = true;
- }
- }
-
-
- ///
- /// Optimized method for bulk deletion of properties´on a Content object.
- ///
- private void deleteAllProperties()
- {
- SqlHelper.ExecuteNonQuery("Delete from cmsPropertyData where contentNodeId = @nodeId", SqlHelper.CreateParameter("@nodeId", this.Id));
- }
-
- ///
- /// Retrieve a list of generic properties of the content
- ///
- public Property[] getProperties
- {
- get
- {
- if (this.ContentType == null)
- return new Property[0];
-
- List result = new List();
- foreach(PropertyType prop in this.ContentType.PropertyTypes)
- {
- if (prop == null)
- continue;
- Property p = getProperty(prop);
- if(p == null)
- continue;
- result.Add(p);
- }
-
- return result.ToArray();
- }
- }
-
-
- private void InitializeProperties()
+ ///
+ /// Retrieve a Property given the alias
+ ///
+ /// Propertyalias (defined in the documenttype)
+ /// The property with the given alias
+ public Property getProperty(string alias)
{
- using(IRecordsReader dr = SqlHelper.ExecuteReader("select id from cmsPropertyData where versionId = @versionId",
- SqlHelper.CreateParameter("@versionId", Version)))
- {
- while(dr.Read())
- _properties.Add(new Property(dr.GetInt("id")));
- }
+ ContentType ct = this.ContentType;
+ if (ct == null)
+ return null;
+ propertytype.PropertyType pt = ct.getPropertyType(alias);
+ if (pt == null)
+ return null;
+ return getProperty(pt);
}
+ ///
+ /// Retrieve a property given the propertytype
+ ///
+ /// PropertyType
+ /// The property with the given propertytype
+ public Property getProperty(PropertyType pt)
+ {
- ///
- /// Retrive a list of Content sharing the ContentType
- ///
- /// The ContentType
- /// A list of Content objects sharing the ContentType defined.
- public static Content[] getContentOfContentType(ContentType ct) {
- IRecordsReader dr = SqlHelper.ExecuteReader("Select nodeId from cmsContent INNER JOIN umbracoNode ON cmsContent.nodeId = umbracoNode.id where ContentType = " + ct.Id + " ORDER BY umbracoNode.text ");
- System.Collections.ArrayList tmp = new System.Collections.ArrayList();
-
- while (dr.Read()) tmp.Add(dr.GetInt("nodeId"));
- dr.Close();
-
- Content[] retval = new Content[tmp.Count];
- for (int i = 0;i < tmp.Count; i++) retval[i] = new Content((int) tmp[i]);
-
- return retval;
- }
-
- ///
- /// Add a property to the Content
- ///
- /// The PropertyType of the Property
- /// The version of the document on which the property should be add'ed
- /// The new Property
- public property.Property addProperty(propertytype.PropertyType pt, Guid versionId) {
- return property.Property.MakeNew(pt, this, versionId);
- }
-
- ///
- /// Content is under version control, you are able to programatically create new versions
- ///
- public Guid Version {
- get{
- if (_version == Guid.Empty)
- {
- string sql = "Select versionId from cmsContentVersion where contentID = " + this.Id +
- " order by id desc ";
-
- using (IRecordsReader dr = SqlHelper.ExecuteReader(sql))
- {
- if (!dr.Read())
- _version = Guid.Empty;
- else
- _version = dr.GetGuid("versionId");
- }
- }
- return _version;
- }
- set{_version = value;}
- }
-
- ///
- /// Creates a new Content object from the ContentType.
- ///
- ///
- protected void CreateContent(ContentType ct) {
- SqlHelper.ExecuteNonQuery("insert into cmsContent (nodeId,ContentType) values ("+this.Id+","+ct.Id+")");
- createNewVersion();
- }
-
- ///
- /// Indication if the Content exists in at least one version.
- ///
- /// Returns true if the Content has a version
- private bool hasVersion()
- {
- int versionCount = SqlHelper.ExecuteScalar("select Count(Id) as tmp from cmsContentVersion where contentId = " + this.Id.ToString());
- return (versionCount > 0);
- }
-
- ///
- /// Method for creating a new version of the data associated to the Content.
- ///
- ///
- /// The new version Id
- protected Guid createNewVersion() {
- Guid newVersion = Guid.NewGuid();
- bool tempHasVersion = hasVersion();
- foreach (propertytype.PropertyType pt in this.ContentType.PropertyTypes)
- {
- object oldValue = "";
- if (tempHasVersion)
- {
- try
- {
- oldValue = this.getProperty(pt.Alias).Value;
- }
- catch {}
- }
- property.Property p = this.addProperty(pt, newVersion);
- if (oldValue != null && oldValue.ToString() != "") p.Value = oldValue;
- }
- SqlHelper.ExecuteNonQuery("Insert into cmsContentVersion (ContentId,versionId) values ("+ this.Id +",'"+newVersion+"')");
- this.Version = newVersion;
- return newVersion;
- }
-
- ///
- /// Deletes the current Content object, must be overridden in the child class.
- ///
- protected new void delete() {
-
- // Delete all data associated with this content
- this.deleteAllProperties();
-
- // Delete version history
- SqlHelper.ExecuteNonQuery("Delete from cmsContentVersion where ContentId = " + this.Id);
-
- // Delete Contentspecific data ()
- SqlHelper.ExecuteNonQuery("Delete from cmsContent where NodeId = " + this.Id);
-
- // Delete xml
- SqlHelper.ExecuteNonQuery("delete from cmsContentXml where nodeID = @nodeId", SqlHelper.CreateParameter("@nodeId", this.Id));
-
- // Delete Nodeinformation!!
- base.delete();
- }
-
- ///
- /// Initialize a contentobject given a version.
- ///
- /// The version identifier
- /// The Content object from the given version
- public static Content GetContentFromVersion(Guid version) {
- int tmpContentId = SqlHelper.ExecuteScalar("Select ContentId from cmsContentVersion where versionId = '" + version.ToString() + "'");
- return new Content(tmpContentId);
- }
+ object o = SqlHelper.ExecuteScalar(
+ "select id from cmsPropertyData where versionId=@version and propertyTypeId=@propertyTypeId",
+ SqlHelper.CreateParameter("@version", this.Version),
+ SqlHelper.CreateParameter("@propertyTypeId", pt.Id));
+ if (o == null)
+ return null;
+ int propertyId;
+ if (!int.TryParse(o.ToString(), out propertyId))
+ return null;
+ try
+ {
+ return new Property(propertyId, pt);
+ }
+ catch
+ {
+ return null;
+ }
- private XmlNode importXml()
- {
- XmlDocument xmlDoc = new XmlDocument();
- xmlDoc.Load(SqlHelper.ExecuteXmlReader("select xml from cmsContentXml where nodeID = " + this.Id.ToString()));
- return xmlDoc.FirstChild;
- }
+ //EnsureProperties();
- ///
- /// An Xmlrepresentation of a Content object.
- ///
- /// Xmldocument context
- /// If true, the Contents children are appended to the Xmlnode recursive
- /// The Xmlrepresentation of the data on the Content object
- public new virtual XmlNode ToXml(XmlDocument xd, bool Deep)
- {
- if (_xml == null)
- {
- XmlDocument xmlDoc = new XmlDocument();
+ //var prop = m_LoadedProperties
+ // .Where(x => x.PropertyType.Id == pt.Id)
+ // .SingleOrDefault();
+ //return prop;
+
+ }
+
+ ///
+ /// Add a property to the Content
+ ///
+ /// The PropertyType of the Property
+ /// The version of the document on which the property should be add'ed
+ /// The new Property
+ public Property addProperty(PropertyType pt, Guid versionId)
+ {
+ return property.Property.MakeNew(pt, this, versionId);
+ }
+
+ ///
+ /// An Xmlrepresentation of a Content object.
+ ///
+ /// Xmldocument context
+ /// If true, the Contents children are appended to the Xmlnode recursive
+ /// The Xmlrepresentation of the data on the Content object
+ public override XmlNode ToXml(XmlDocument xd, bool Deep)
+ {
+ if (_xml == null)
+ {
+ XmlDocument xmlDoc = new XmlDocument();
// we add a try/catch clause here, as the xmlreader will throw an exception if there's no xml in the table
// after the empty catch we'll generate the xml which is why we don't do anything in the catch part
try
@@ -430,19 +352,19 @@ namespace umbraco.cms.businesslogic
}
- // Generate xml if xml still null (then it hasn't been initialized before)
- if (_xml == null)
- {
- this.XmlGenerate(new XmlDocument());
- _xml = importXml();
- }
+ // Generate xml if xml still null (then it hasn't been initialized before)
+ if (_xml == null)
+ {
+ this.XmlGenerate(new XmlDocument());
+ _xml = importXml();
+ }
- }
+ }
- XmlNode x = xd.ImportNode(_xml, true);
+ XmlNode x = xd.ImportNode(_xml, true);
- if (Deep)
- {
+ if (Deep)
+ {
//store children array here because iterating over an Array object is very inneficient.
var childs = this.Children;
foreach (BusinessLogic.console.IconI c in childs)
@@ -455,30 +377,148 @@ namespace umbraco.cms.businesslogic
{
System.Web.HttpContext.Current.Trace.Warn("Content", "Error adding node to xml: " + mExp.ToString());
}
- }
- }
+ }
+ }
- return x;
+ return x;
- }
+ }
- ///
- /// Removes the Xml cached in the database - unpublish and cleaning
- ///
- public virtual void XmlRemoveFromDB()
- {
- SqlHelper.ExecuteNonQuery("delete from cmsContentXml where nodeId = @nodeId", SqlHelper.CreateParameter("@nodeId", this.Id));
- }
+ ///
+ /// Removes the Xml cached in the database - unpublish and cleaning
+ ///
+ public virtual void XmlRemoveFromDB()
+ {
+ SqlHelper.ExecuteNonQuery("delete from cmsContentXml where nodeId = @nodeId", SqlHelper.CreateParameter("@nodeId", this.Id));
+ }
- ///
- /// Generates the Content XmlNode
- ///
- ///
- public virtual void XmlGenerate(XmlDocument xd)
- {
+ ///
+ /// Generates the Content XmlNode
+ ///
+ ///
+ public virtual void XmlGenerate(XmlDocument xd)
+ {
XmlNode node = generateXmlWithoutSaving(xd);
SaveXmlDocument(node);
- }
+ }
+
+ public virtual void XmlPopulate(XmlDocument xd, ref XmlNode x, bool Deep)
+ {
+ var props = this.getProperties;
+ foreach (property.Property p in props)
+ if (p != null)
+ x.AppendChild(p.ToXml(xd));
+
+ // attributes
+ x.Attributes.Append(xmlHelper.addAttribute(xd, "id", this.Id.ToString()));
+ x.Attributes.Append(xmlHelper.addAttribute(xd, "version", this.Version.ToString()));
+ if (this.Level > 1)
+ x.Attributes.Append(xmlHelper.addAttribute(xd, "parentID", this.Parent.Id.ToString()));
+ else
+ x.Attributes.Append(xmlHelper.addAttribute(xd, "parentID", "-1"));
+ x.Attributes.Append(xmlHelper.addAttribute(xd, "level", this.Level.ToString()));
+ x.Attributes.Append(xmlHelper.addAttribute(xd, "writerID", this.User.Id.ToString()));
+ if (this.ContentType != null)
+ x.Attributes.Append(xmlHelper.addAttribute(xd, "nodeType", this.ContentType.Id.ToString()));
+ x.Attributes.Append(xmlHelper.addAttribute(xd, "template", "0"));
+ x.Attributes.Append(xmlHelper.addAttribute(xd, "sortOrder", this.sortOrder.ToString()));
+ x.Attributes.Append(xmlHelper.addAttribute(xd, "createDate", this.CreateDateTime.ToString("s")));
+ x.Attributes.Append(xmlHelper.addAttribute(xd, "updateDate", this.VersionDate.ToString("s")));
+ x.Attributes.Append(xmlHelper.addAttribute(xd, "nodeName", this.Text));
+ if (this.Text != null)
+ x.Attributes.Append(xmlHelper.addAttribute(xd, "urlName", this.Text.Replace(" ", "").ToLower()));
+ x.Attributes.Append(xmlHelper.addAttribute(xd, "writerName", this.User.Name));
+ if (this.ContentType != null)
+ x.Attributes.Append(xmlHelper.addAttribute(xd, "nodeTypeAlias", this.ContentType.Alias));
+ x.Attributes.Append(xmlHelper.addAttribute(xd, "path", this.Path));
+
+ 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)
+ x.AppendChild(c.ToXml(xd, true));
+ }
+ }
+ #endregion
+
+ #region Protected Methods
+ ///
+ /// 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)
+ {
+ if (_contentType == null)
+ _contentType = ContentType.GetContentType(InitContentType);
+ _version = InitVersion;
+ _versionDate = InitVersionDate;
+ _contentTypeIcon = InitContentTypeIcon;
+ }
+
+ ///
+ /// Creates a new Content object from the ContentType.
+ ///
+ ///
+ protected void CreateContent(ContentType ct)
+ {
+ SqlHelper.ExecuteNonQuery("insert into cmsContent (nodeId,ContentType) values (" + this.Id + "," + ct.Id + ")");
+ createNewVersion();
+ }
+
+ ///
+ /// Method for creating a new version of the data associated to the Content.
+ ///
+ ///
+ /// The new version Id
+ protected Guid createNewVersion()
+ {
+ Guid newVersion = Guid.NewGuid();
+ bool tempHasVersion = hasVersion();
+ foreach (propertytype.PropertyType pt in this.ContentType.PropertyTypes)
+ {
+ object oldValue = "";
+ if (tempHasVersion)
+ {
+ try
+ {
+ oldValue = this.getProperty(pt.Alias).Value;
+ }
+ catch { }
+ }
+ property.Property p = this.addProperty(pt, newVersion);
+ if (oldValue != null && oldValue.ToString() != "") p.Value = oldValue;
+ }
+ SqlHelper.ExecuteNonQuery("Insert into cmsContentVersion (ContentId,versionId) values (" + this.Id + ",'" + newVersion + "')");
+ this.Version = newVersion;
+ return newVersion;
+ }
+
+ ///
+ /// Deletes the current Content object, must be overridden in the child class.
+ ///
+ protected new void delete()
+ {
+
+ // Delete all data associated with this content
+ this.deleteAllProperties();
+
+ // Delete version history
+ SqlHelper.ExecuteNonQuery("Delete from cmsContentVersion where ContentId = " + this.Id);
+
+ // Delete Contentspecific data ()
+ SqlHelper.ExecuteNonQuery("Delete from cmsContent where NodeId = " + this.Id);
+
+ // Delete xml
+ SqlHelper.ExecuteNonQuery("delete from cmsContentXml where nodeID = @nodeId", SqlHelper.CreateParameter("@nodeId", this.Id));
+
+ // Delete Nodeinformation!!
+ base.delete();
+ }
protected virtual XmlNode generateXmlWithoutSaving(XmlDocument xd)
{
@@ -488,46 +528,6 @@ namespace umbraco.cms.businesslogic
return x;
}
-
- public virtual void XmlPopulate(XmlDocument xd, ref XmlNode x, bool Deep)
- {
- var props = this.getProperties;
- foreach (property.Property p in props)
- if (p != null)
- x.AppendChild(p.ToXml(xd));
-
- // attributes
- x.Attributes.Append(xmlHelper.addAttribute(xd, "id", this.Id.ToString()));
- x.Attributes.Append(xmlHelper.addAttribute(xd, "version", this.Version.ToString()));
- if (this.Level > 1)
- x.Attributes.Append(xmlHelper.addAttribute(xd, "parentID", this.Parent.Id.ToString()));
- else
- x.Attributes.Append(xmlHelper.addAttribute(xd, "parentID", "-1"));
- x.Attributes.Append(xmlHelper.addAttribute(xd, "level", this.Level.ToString()));
- x.Attributes.Append(xmlHelper.addAttribute(xd, "writerID", this.User.Id.ToString()));
- if (this.ContentType != null)
- x.Attributes.Append(xmlHelper.addAttribute(xd, "nodeType", this.ContentType.Id.ToString()));
- x.Attributes.Append(xmlHelper.addAttribute( xd, "template", "0"));
- x.Attributes.Append(xmlHelper.addAttribute(xd, "sortOrder", this.sortOrder.ToString()));
- x.Attributes.Append(xmlHelper.addAttribute(xd, "createDate", this.CreateDateTime.ToString("s")));
- x.Attributes.Append(xmlHelper.addAttribute(xd, "updateDate", this.VersionDate.ToString("s")));
- x.Attributes.Append(xmlHelper.addAttribute(xd, "nodeName", this.Text));
- if (this.Text != null)
- x.Attributes.Append(xmlHelper.addAttribute(xd, "urlName", this.Text.Replace(" ", "").ToLower()));
- x.Attributes.Append(xmlHelper.addAttribute(xd, "writerName", this.User.Name));
- if (this.ContentType != null)
- x.Attributes.Append(xmlHelper.addAttribute(xd, "nodeTypeAlias", this.ContentType.Alias));
- x.Attributes.Append(xmlHelper.addAttribute(xd, "path", this.Path));
-
- 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)
- x.AppendChild(c.ToXml(xd, true));
- }
- }
-
///
/// Saves the XML document to the data source.
///
@@ -548,6 +548,109 @@ namespace umbraco.cms.businesslogic
SqlHelper.CreateParameter("@xml", node.OuterXml));
}
+ #endregion
+
+ #region Private Methods
+
+ ///
+ /// Makes sure that the properties are initialized. If they are already initialized, this does nothing.
+ ///
+ private void EnsureProperties()
+ {
+ if (m_LoadedProperties == null)
+ {
+ InitializeProperties();
+ }
+ }
+
+ ///
+ /// Loads all properties from database into objects. If this method is re-called, it will re-query the database.
+ ///
+ ///
+ /// This optimizes sql calls. This will first check if all of the properties have been loaded. If not,
+ /// then it will query for all property types for the current version from the db. It will then iterate over each
+ /// cmdPropertyData row and store the id and propertyTypeId in a list for lookup later. Once the records have been
+ /// read, we iterate over the cached property types for this ContentType and create a new property based on
+ /// our stored list of proeprtyTypeIds. We then have a cached list of Property objects which will get returned
+ /// on all subsequent calls and is also used to return a property with calls to getProperty.
+ ///
+ private void InitializeProperties()
+ {
+ m_LoadedProperties = new Properties();
+
+ if (this.ContentType == null)
+ return;
+
+ //Create anonymous typed list with 2 props, Id and PropertyTypeId of type Int.
+ //This will still be an empty list since the props list is empty.
+ var propData = m_LoadedProperties.Select(x => new { Id = 0, PropertyTypeId = 0 }).ToList();
+
+ string sql = @"select id, propertyTypeId from cmsPropertyData where versionId=@versionId";
+
+ using (IRecordsReader dr = SqlHelper.ExecuteReader(sql,
+ SqlHelper.CreateParameter("@versionId", Version)))
+ {
+ while (dr.Read())
+ {
+ //add the item to our list
+ propData.Add(new { Id = dr.Get("id"), PropertyTypeId = dr.Get("propertyTypeId") });
+ }
+ }
+
+ foreach (PropertyType pt in this.ContentType.PropertyTypes)
+ {
+ if (pt == null)
+ continue;
+
+ //get the propertyId
+ var property = propData
+ .Where(x => x.PropertyTypeId == pt.Id)
+ .SingleOrDefault();
+ if (property == null)
+ continue;
+ var propertyId = property.Id;
+
+ Property p = null;
+ try
+ {
+ p = new Property(propertyId, pt);
+ }
+ catch
+ {
+ continue; //this remains from old code... not sure why we would do this?
+ }
+
+ m_LoadedProperties.Add(p);
+ }
+ }
+
+ ///
+ /// Optimized method for bulk deletion of properties´on a Content object.
+ ///
+ private void deleteAllProperties()
+ {
+ SqlHelper.ExecuteNonQuery("Delete from cmsPropertyData where contentNodeId = @nodeId", SqlHelper.CreateParameter("@nodeId", this.Id));
+ }
+
+ private XmlNode importXml()
+ {
+ XmlDocument xmlDoc = new XmlDocument();
+ xmlDoc.Load(SqlHelper.ExecuteXmlReader("select xml from cmsContentXml where nodeID = " + this.Id.ToString()));
+
+ return xmlDoc.FirstChild;
+ }
+
+ ///
+ /// Indication if the Content exists in at least one version.
+ ///
+ /// Returns true if the Content has a version
+ private bool hasVersion()
+ {
+ int versionCount = SqlHelper.ExecuteScalar("select Count(Id) as tmp from cmsContentVersion where contentId = " + this.Id.ToString());
+ return (versionCount > 0);
+ }
+
+ #endregion
#region XmlPreivew
@@ -566,16 +669,5 @@ namespace umbraco.cms.businesslogic
}
#endregion
- }
-
- ///
- /// Not implemented
- ///
- public interface ISaveHandlerContents
- {
- ///
- /// Not implemented
- ///
- bool Execute(cms.businesslogic.Content contentObject);
- }
+ }
}
\ No newline at end of file
diff --git a/umbraco/cms/businesslogic/ContentType.cs b/umbraco/cms/businesslogic/ContentType.cs
index d4ae4ae78a..e7647475b6 100644
--- a/umbraco/cms/businesslogic/ContentType.cs
+++ b/umbraco/cms/businesslogic/ContentType.cs
@@ -85,11 +85,13 @@ namespace umbraco.cms.businesslogic
#endregion
+ #region Constants
private const string m_SQLOptimizedGetAll = @"
SELECT id, createDate, trashed, parentId, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text,
masterContentType,Alias,icon,thumbnail,description
FROM umbracoNode INNER JOIN cmsContentType ON umbracoNode.id = cmsContentType.nodeId
- WHERE nodeObjectType = @nodeObjectType";
+ WHERE nodeObjectType = @nodeObjectType";
+ #endregion
#region Static Methods
@@ -181,7 +183,7 @@ namespace umbraco.cms.businesslogic
#region Private Members
- private bool _optimizedMode = false;
+ //private bool _optimizedMode = false;
private string _alias;
private string _iconurl;
private string _description;
@@ -195,9 +197,6 @@ namespace umbraco.cms.businesslogic
#endregion
- //private static Hashtable _analyzedContentTypes = new Hashtable();
- //private static Hashtable _optimizedContentTypes = new Hashtable();
-
#region Public Properties
///
@@ -238,15 +237,15 @@ namespace umbraco.cms.businesslogic
}
}
- ///
- /// Gets or sets a value indicating whether [optimized mode].
- ///
- /// true if [optimized mode]; otherwise, false .
- public bool OptimizedMode
- {
- get { return _optimizedMode; }
- set { _optimizedMode = value; }
- }
+ /////
+ ///// Gets or sets a value indicating whether [optimized mode].
+ /////
+ ///// true if [optimized mode]; otherwise, false .
+ //public bool OptimizedMode
+ //{
+ // get { return _optimizedMode; }
+ // set { _optimizedMode = value; }
+ //}
///
/// Human readable name/label
@@ -394,35 +393,7 @@ namespace umbraco.cms.businesslogic
{
get
{
- //optimize, lazy load the data only one time
- if (m_VirtualTabs == null)
- {
- m_VirtualTabs = new List();
- using (IRecordsReader dr = SqlHelper.ExecuteReader(
- string.Format(
- "Select Id,text,sortOrder from cmsTab where contenttypeNodeId = {0} order by sortOrder",
- Id)))
- {
- while (dr.Read())
- {
- m_VirtualTabs.Add(new Tab(dr.GetInt("id"), dr.GetString("text"), dr.GetInt("sortOrder"), this));
- }
- }
-
- // Master Content Type
- if (MasterContentType != 0)
- {
- foreach (TabI t in ContentType.GetContentType(MasterContentType).getVirtualTabs.ToList())
- {
- m_VirtualTabs.Add(t);
- }
- }
-
- // sort all tabs
- m_VirtualTabs.Sort((a, b) => a.SortOrder.CompareTo(b.SortOrder));
- }
-
-
+ EnsureVirtualTabs();
return m_VirtualTabs.ToArray();
}
}
@@ -750,17 +721,72 @@ namespace umbraco.cms.businesslogic
if (HttpRuntime.Cache[string.Format("ContentType_PropertyTypes_Content:{0}", Id.ToString())] != null)
HttpRuntime.Cache.Remove(string.Format("ContentType_PropertyTypes_Content:{0}", Id.ToString()));
+
+ ClearVirtualTabs();
}
protected void FlushAllFromCache()
{
cache.Cache.ClearCacheByKeySearch("UmbracoContentType");
cache.Cache.ClearCacheByKeySearch("ContentType_PropertyTypes_Content");
+
+ ClearVirtualTabs();
}
+
#endregion
#region Private Methods
+ ///
+ /// Clears the locally loaded tabs which forces them to be reloaded next time they requested
+ ///
+ private void ClearVirtualTabs()
+ {
+ m_VirtualTabs = null;
+ }
+
+ ///
+ /// Checks if we've loaded the virtual tabs into memory and if not gets them from the databse.
+ ///
+ private void EnsureVirtualTabs()
+ {
+ //optimize, lazy load the data only one time
+ if (m_VirtualTabs == null)
+ {
+ InitializeVirtualTabs();
+ }
+ }
+
+ ///
+ /// Loads the tabs into memory from the database and stores them in a local list for retreival
+ ///
+ private void InitializeVirtualTabs()
+ {
+ m_VirtualTabs = new List();
+ using (IRecordsReader dr = SqlHelper.ExecuteReader(
+ string.Format(
+ "Select Id,text,sortOrder from cmsTab where contenttypeNodeId = {0} order by sortOrder",
+ Id)))
+ {
+ while (dr.Read())
+ {
+ m_VirtualTabs.Add(new Tab(dr.GetInt("id"), dr.GetString("text"), dr.GetInt("sortOrder"), this));
+ }
+ }
+
+ // Master Content Type
+ if (MasterContentType != 0)
+ {
+ foreach (TabI t in ContentType.GetContentType(MasterContentType).getVirtualTabs.ToList())
+ {
+ m_VirtualTabs.Add(t);
+ }
+ }
+
+ // sort all tabs
+ m_VirtualTabs.Sort((a, b) => a.SortOrder.CompareTo(b.SortOrder));
+ }
+
private void PopulateContentTypeNodeFromReader(IRecordsReader dr)
{
_alias = dr.GetString("Alias");
diff --git a/umbraco/cms/businesslogic/ISaveHandlerContents.cs b/umbraco/cms/businesslogic/ISaveHandlerContents.cs
new file mode 100644
index 0000000000..c1f495210d
--- /dev/null
+++ b/umbraco/cms/businesslogic/ISaveHandlerContents.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Xml;
+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
+{
+ ///
+ /// Not implemented
+ ///
+ public interface ISaveHandlerContents
+ {
+ ///
+ /// Not implemented
+ ///
+ bool Execute(cms.businesslogic.Content contentObject);
+ }
+}
diff --git a/umbraco/cms/businesslogic/Property/Properties.cs b/umbraco/cms/businesslogic/Property/Properties.cs
new file mode 100644
index 0000000000..8a683f45f4
--- /dev/null
+++ b/umbraco/cms/businesslogic/Property/Properties.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Runtime.CompilerServices;
+using System.Xml;
+using umbraco.DataLayer;
+using umbraco.BusinessLogic;
+
+namespace umbraco.cms.businesslogic.property
+{
+ public class Properties : List { }
+
+}
diff --git a/umbraco/cms/businesslogic/Property/Property.cs b/umbraco/cms/businesslogic/Property/Property.cs
index 8063836e82..23b51b4fc4 100644
--- a/umbraco/cms/businesslogic/Property/Property.cs
+++ b/umbraco/cms/businesslogic/Property/Property.cs
@@ -108,9 +108,4 @@ namespace umbraco.cms.businesslogic.property
}
}
- public class Properties : List
- {
-
- }
-
}
\ No newline at end of file
diff --git a/umbraco/cms/businesslogic/web/Document.cs b/umbraco/cms/businesslogic/web/Document.cs
index 2203eb31a5..e9889d12c4 100644
--- a/umbraco/cms/businesslogic/web/Document.cs
+++ b/umbraco/cms/businesslogic/web/Document.cs
@@ -223,8 +223,8 @@ namespace umbraco.cms.businesslogic.web
// special for tree performance
private int _userId = -1;
- private Dictionary _knownProperties = new Dictionary();
- private Func, string, bool> propertyTypeByAlias = (pt, alias) => pt.Key.PropertyType.Alias == alias;
+ //private Dictionary _knownProperties = new Dictionary();
+ //private Func, string, bool> propertyTypeByAlias = (pt, alias) => pt.Key.PropertyType.Alias == alias;
#endregion
///
@@ -232,41 +232,41 @@ namespace umbraco.cms.businesslogic.web
///
///
///
- public object this[string alias]
- {
- get
- {
- if (this._optimizedMode)
- {
- return this._knownProperties.Single(p => propertyTypeByAlias(p, alias)).Value;
- }
- else
- {
- return this.getProperty(alias).Value;
- }
- }
- set
- {
- if (this._optimizedMode)
- {
- if (this._knownProperties.SingleOrDefault(p => propertyTypeByAlias(p, alias)).Key == null)
- {
- var pt = this.getProperty(alias);
+ //public object this[string alias]
+ //{
+ // get
+ // {
+ // if (this._optimizedMode)
+ // {
+ // return this._knownProperties.Single(p => propertyTypeByAlias(p, alias)).Value;
+ // }
+ // else
+ // {
+ // return this.getProperty(alias).Value;
+ // }
+ // }
+ // set
+ // {
+ // if (this._optimizedMode)
+ // {
+ // if (this._knownProperties.SingleOrDefault(p => propertyTypeByAlias(p, alias)).Key == null)
+ // {
+ // var pt = this.getProperty(alias);
- this._knownProperties.Add(pt, pt.Value);
- }
- else
- {
- var pt = this._knownProperties.Single(p => propertyTypeByAlias(p, alias)).Key;
- this._knownProperties[pt] = value;
- }
- }
- else
- {
- this.getProperty(alias).Value = value;
- }
- }
- }
+ // this._knownProperties.Add(pt, pt.Value);
+ // }
+ // else
+ // {
+ // var pt = this._knownProperties.Single(p => propertyTypeByAlias(p, alias)).Key;
+ // this._knownProperties[pt] = value;
+ // }
+ // }
+ // else
+ // {
+ // this.getProperty(alias).Value = value;
+ // }
+ // }
+ //}
///
/// Gets a value indicating whether the document was constructed for the optimized mode
@@ -570,14 +570,14 @@ namespace umbraco.cms.businesslogic.web
if (!e.Cancel)
{
- if (this._optimizedMode)
- {
- foreach (var property in this._knownProperties)
- {
- var pt = property.Key;
- pt.Value = property.Value;
- }
- }
+ //if (this._optimizedMode)
+ //{
+ // foreach (var property in this._knownProperties)
+ // {
+ // var pt = property.Key;
+ // pt.Value = property.Value;
+ // }
+ //}
base.Save();
// update preview xml
diff --git a/umbraco/cms/umbraco.cms.csproj b/umbraco/cms/umbraco.cms.csproj
index 50a02676b1..5729b9c5b7 100644
--- a/umbraco/cms/umbraco.cms.csproj
+++ b/umbraco/cms/umbraco.cms.csproj
@@ -172,11 +172,13 @@
+
True
True
PackageFiles.resx
+
diff --git a/umbraco/presentation/web.config.SHANDEMVAIO.xslt b/umbraco/presentation/web.config.SHANDEMVAIO.xslt
index 192b891a82..9a8fe2197b 100644
--- a/umbraco/presentation/web.config.SHANDEMVAIO.xslt
+++ b/umbraco/presentation/web.config.SHANDEMVAIO.xslt
@@ -4,7 +4,7 @@
- server=.\sqlexpress;database=UmbracoTest5;user id=sa;password=test;Application Name=Umbraco41
+ server=.\sqlexpress;database=UmbracoTest4;user id=sa;password=test;Application Name=Umbraco41