1716 lines
69 KiB
C#
1716 lines
69 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Data;
|
|
using System.Web;
|
|
using System.Xml;
|
|
|
|
using umbraco.BusinessLogic;
|
|
using umbraco.BusinessLogic.Actions;
|
|
using umbraco.BusinessLogic.console;
|
|
using umbraco.cms.businesslogic.index;
|
|
using umbraco.cms.businesslogic.property;
|
|
using umbraco.cms.businesslogic.relation;
|
|
using umbraco.cms.helpers;
|
|
using umbraco.DataLayer;
|
|
using System.Collections.Generic;
|
|
using umbraco.cms.businesslogic.propertytype;
|
|
using System.Linq;
|
|
using System.ComponentModel;
|
|
|
|
namespace umbraco.cms.businesslogic.web
|
|
{
|
|
/// <summary>
|
|
/// Document represents a webpage,
|
|
/// type (umbraco.cms.businesslogic.web.DocumentType)
|
|
///
|
|
/// Pubished Documents are exposed to the runtime/the public website in a cached xml document.
|
|
/// </summary>
|
|
public class Document : Content
|
|
{
|
|
public static Guid _objectType = new Guid("c66ba18e-eaf3-4cff-8a22-41b16d66a972");
|
|
private DateTime _updated;
|
|
private DateTime _release;
|
|
private DateTime _expire;
|
|
private int _template;
|
|
private string _text;
|
|
private bool _published;
|
|
private XmlNode _xml;
|
|
private User _creator;
|
|
private User _writer;
|
|
private bool _optimizedMode;
|
|
|
|
// special for passing httpcontext object
|
|
private HttpContext _httpContext;
|
|
|
|
// special for tree performance
|
|
private int _userId = -1;
|
|
|
|
/// <summary>
|
|
/// The id of the user whom created the document
|
|
/// </summary>
|
|
public int UserId
|
|
{
|
|
get
|
|
{
|
|
if (_userId == -1)
|
|
_userId = User.Id;
|
|
|
|
return _userId;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the user who created the document.
|
|
/// </summary>
|
|
/// <value>The creator.</value>
|
|
public User Creator {
|
|
get { return _creator;}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the writer.
|
|
/// </summary>
|
|
/// <value>The writer.</value>
|
|
public User Writer {
|
|
get { return _writer; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The current HTTPContext
|
|
/// </summary>
|
|
public HttpContext HttpContext
|
|
{
|
|
set { _httpContext = value; }
|
|
get
|
|
{
|
|
if (_httpContext == null)
|
|
_httpContext = HttpContext.Current;
|
|
return _httpContext;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Executes handlers and events for the Send To Publication action.
|
|
/// </summary>
|
|
/// <param name="u">The User</param>
|
|
public bool SendToPublication(User u)
|
|
{
|
|
SendToPublishEventArgs e = new SendToPublishEventArgs();
|
|
FireBeforeSendToPublish(e);
|
|
if (!e.Cancel)
|
|
{
|
|
BusinessLogic.Log.Add(BusinessLogic.LogTypes.SendToPublish, u, this.Id, "");
|
|
|
|
BusinessLogic.Actions.Action.RunActionHandlers(this, ActionToPublish.Instance);
|
|
|
|
FireAfterSendToPublish(e);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Publishing a document
|
|
/// A xmlrepresentation of the document and its data are exposed to the runtime data
|
|
/// (an xmlrepresentation is added -or updated if the document previously are published) ,
|
|
/// this will lead to a new version of the document being created, for continuing editing of
|
|
/// the data.
|
|
/// </summary>
|
|
/// <param name="u">The usercontext under which the action are performed</param>
|
|
public void Publish(User u)
|
|
{
|
|
PublishWithResult(u);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Publishing a document
|
|
/// A xmlrepresentation of the document and its data are exposed to the runtime data
|
|
/// (an xmlrepresentation is added -or updated if the document previously are published) ,
|
|
/// this will lead to a new version of the document being created, for continuing editing of
|
|
/// the data.
|
|
/// </summary>
|
|
/// <param name="u">The usercontext under which the action are performed</param>
|
|
/// <returns>True if the publishing succeed. Possible causes for not publishing is if an event aborts the publishing</returns>
|
|
public bool PublishWithResult(User u)
|
|
{
|
|
PublishEventArgs e = new PublishEventArgs();
|
|
FireBeforePublish(e);
|
|
|
|
if (!e.Cancel)
|
|
{
|
|
|
|
_published = true;
|
|
string tempVersion = Version.ToString();
|
|
Guid newVersion = createNewVersion();
|
|
|
|
Log.Add(LogTypes.Publish, u, Id, "");
|
|
|
|
//PPH make sure that there is only 1 newest node, this is important in regard to schedueled publishing...
|
|
SqlHelper.ExecuteNonQuery("update cmsDocument set newest = 0 where nodeId = " + Id);
|
|
|
|
SqlHelper.ExecuteNonQuery("insert into cmsDocument (newest, nodeId, published, documentUser, versionId, Text, TemplateId) values (1," +
|
|
Id + ", 0, " + u.Id + ", @versionId, @text,"
|
|
+ _template + ")",
|
|
SqlHelper.CreateParameter("@versionId", newVersion),
|
|
SqlHelper.CreateParameter("@text", Text));
|
|
SqlHelper.ExecuteNonQuery("update cmsDocument set published = 0 where nodeId = " + Id);
|
|
SqlHelper.ExecuteNonQuery("update cmsDocument set published = 1, newest = 0 where versionId = @versionId",
|
|
SqlHelper.CreateParameter("@versionId", tempVersion));
|
|
|
|
// update release and expire dates
|
|
Document newDoc = new Document(Id, newVersion);
|
|
if (ReleaseDate != new DateTime())
|
|
newDoc.ReleaseDate = ReleaseDate;
|
|
if (ExpireDate != new DateTime())
|
|
newDoc.ExpireDate = ExpireDate;
|
|
|
|
// Update xml in db using the new document (has correct version date)
|
|
newDoc.XmlGenerate(new XmlDocument());
|
|
|
|
FireAfterPublish(e);
|
|
|
|
return true;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
public bool PublishWithChildrenWithResult(User u) {
|
|
if(PublishWithResult(u)){
|
|
foreach (cms.businesslogic.web.Document dc in this.Children) {
|
|
dc.PublishWithChildrenWithResult(u);
|
|
}
|
|
}else{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rollbacks a document to a previous version, this will create a new version of the document and copy
|
|
/// all of the old documents data.
|
|
/// </summary>
|
|
/// <param name="u">The usercontext under which the action are performed</param>
|
|
/// <param name="VersionId">The unique Id of the version to roll back to</param>
|
|
public void RollBack(Guid VersionId, User u)
|
|
{
|
|
RollBackEventArgs e = new RollBackEventArgs();
|
|
FireBeforeRollBack(e);
|
|
|
|
if (!e.Cancel) {
|
|
Guid newVersion = createNewVersion();
|
|
SqlHelper.ExecuteNonQuery("insert into cmsDocument (nodeId, published, documentUser, versionId, Text, TemplateId) values (" +
|
|
Id +
|
|
", 0, " + u.Id + ", @versionId, @text, " +
|
|
_template + ")",
|
|
SqlHelper.CreateParameter("@versionId", newVersion),
|
|
SqlHelper.CreateParameter("@text", Text));
|
|
|
|
// Get new version
|
|
Document dNew = new Document(Id, newVersion);
|
|
|
|
// Old version
|
|
Document dOld = new Document(Id, VersionId);
|
|
|
|
// Revert title
|
|
dNew.Text = dOld.Text;
|
|
|
|
// Revert all properties
|
|
foreach (Property p in dOld.getProperties)
|
|
try {
|
|
dNew.getProperty(p.PropertyType).Value = p.Value;
|
|
} catch {
|
|
// property doesn't exists
|
|
}
|
|
|
|
FireAfterRollBack(e);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recursive publishing.
|
|
///
|
|
/// Envoking this method will publish the documents and all children recursive.
|
|
/// </summary>
|
|
/// <param name="u">The usercontext under which the action are performed</param>
|
|
public void PublishWithSubs(User u)
|
|
{
|
|
|
|
PublishEventArgs e = new PublishEventArgs();
|
|
FireBeforePublish(e);
|
|
|
|
if (!e.Cancel) {
|
|
_published = true;
|
|
string tempVersion = Version.ToString();
|
|
Guid newVersion = createNewVersion();
|
|
|
|
SqlHelper.ExecuteNonQuery("insert into cmsDocument (nodeId, published, documentUser, versionId, Text) values (" +
|
|
Id + ", 0, " + u.Id +
|
|
", @versionId, @text)",
|
|
SqlHelper.CreateParameter("@versionId", newVersion),
|
|
SqlHelper.CreateParameter("@text", Text));
|
|
|
|
SqlHelper.ExecuteNonQuery("update cmsDocument set published = 0 where nodeId = " + Id);
|
|
SqlHelper.ExecuteNonQuery("update cmsDocument set published = 1 where versionId = @versionId", SqlHelper.CreateParameter("@versionId", tempVersion));
|
|
|
|
BusinessLogic.Log.Add(LogTypes.Debug, -1, newVersion.ToString() + " - " + Id.ToString());
|
|
|
|
// Update xml in db
|
|
XmlGenerate(new XmlDocument());
|
|
|
|
foreach (Document dc in Children)
|
|
dc.PublishWithSubs(u);
|
|
|
|
FireAfterPublish(e);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Published flag is on if the document are published
|
|
/// </summary>
|
|
public bool Published
|
|
{
|
|
get { return _published; }
|
|
|
|
set
|
|
{
|
|
// Esben Carlsen: ????? value never used ?? --> needs update
|
|
_published = false;
|
|
SqlHelper.ExecuteNonQuery(
|
|
string.Format("update cmsDocument set published = 0 where nodeId = {0}", Id));
|
|
}
|
|
}
|
|
|
|
public void UnPublish()
|
|
{
|
|
UnPublishEventArgs e = new UnPublishEventArgs();
|
|
|
|
FireBeforeUnPublish(e);
|
|
|
|
if (!e.Cancel) {
|
|
SqlHelper.ExecuteNonQuery(string.Format("update cmsDocument set published = 0 where nodeId = {0}", Id));
|
|
FireAfterUnPublish(e);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Constructs a new document
|
|
/// </summary>
|
|
/// <param name="id">Id of the document</param>
|
|
/// <param name="noSetup">true if the data shouldn't loaded from the db</param>
|
|
public Document(Guid id, bool noSetup) : base(id)
|
|
{
|
|
//SD: added the following as noSetup actually didn't do anything!?!
|
|
if (!noSetup)
|
|
setupDocument(); //This should call the below method, but for some reason no inheritance is happening here....?
|
|
//setupNode();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the Document class.
|
|
/// You can set an optional flag noSetup, used for optimizing for loading nodes in the tree,
|
|
/// therefor only data needed by the tree is initialized.
|
|
/// </summary>
|
|
/// <param name="id">Id of the document</param>
|
|
/// <param name="noSetup">true if the data shouldn't loaded from the db</param>
|
|
public Document(int id, bool noSetup) : base(id, noSetup)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the Document class to a specific version, used for rolling back data from a previous version
|
|
/// of the document.
|
|
/// </summary>
|
|
/// <param name="id">The id of the document</param>
|
|
/// <param name="Version">The version of the document</param>
|
|
public Document(int id, Guid Version) : base(id)
|
|
{
|
|
this.Version = Version;
|
|
setupDocument();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the Document class.
|
|
/// </summary>
|
|
/// <param name="id">The id of the document</param>
|
|
public Document(int id) : base(id)
|
|
{
|
|
setupDocument();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initialize the document
|
|
/// </summary>
|
|
/// <param name="id">The id of the document</param>
|
|
public Document(Guid id) : base(id)
|
|
{
|
|
setupDocument();
|
|
}
|
|
|
|
public Document(bool OptimizedMode, int id) : base(id, OptimizedMode)
|
|
{
|
|
this._optimizedMode = OptimizedMode;
|
|
|
|
if (OptimizedMode)
|
|
{
|
|
using (IRecordsReader dr =
|
|
SqlHelper.ExecuteReader(
|
|
@"
|
|
Select
|
|
(select count(id) from umbracoNode where parentId = @id) as Children,
|
|
(select Count(published) as tmp from cmsDocument where published = 1 And nodeId = @id) as Published,
|
|
cmsContentVersion.VersionId,
|
|
cmsContentVersion.versionDate,
|
|
cmsContent.ContentType,
|
|
contentTypeNode.uniqueId as ContentTypeGuid,
|
|
cmsContentType.alias,
|
|
cmsContentType.icon,
|
|
published, documentUser, coalesce(templateId, cmsDocumentType.templateNodeId) as templateId, cmsDocument.text as DocumentText, releaseDate, expireDate, updateDate,
|
|
umbracoNode.createDate, umbracoNode.trashed, umbracoNode.parentId, umbracoNode.nodeObjectType, umbracoNode.nodeUser, umbracoNode.level, umbracoNode.path, umbracoNode.sortOrder, umbracoNode.uniqueId, umbracoNode.text
|
|
from
|
|
umbracoNode
|
|
inner join
|
|
cmsContentVersion on cmsContentVersion.contentID = umbracoNode.id
|
|
inner join
|
|
cmsDocument on cmsDocument.versionId = cmsContentVersion.versionId
|
|
inner join
|
|
cmsContent on cmsDocument.nodeId = cmsContent.NodeId
|
|
inner join
|
|
cmsContentType on cmsContentType.nodeId = cmsContent.ContentType
|
|
inner join
|
|
umbracoNode contentTypeNode on contentTypeNode.id = cmsContentType.nodeId
|
|
left join cmsDocumentType on
|
|
cmsDocumentType.contentTypeNodeId = cmsContent.contentType and cmsDocumentType.IsDefault = 1
|
|
where
|
|
umbracoNode.id = @id
|
|
order by
|
|
cmsContentVersion.id desc
|
|
",
|
|
SqlHelper.CreateParameter("@id", id)))
|
|
{
|
|
if (dr.Read())
|
|
{
|
|
// Initialize node and basic document properties
|
|
bool _hc = false;
|
|
if (dr.GetInt("children") > 0)
|
|
_hc = true;
|
|
SetupDocumentForTree(dr.GetGuid("uniqueId"), dr.GetShort("level"),
|
|
dr.GetInt("parentId"), dr.GetInt("documentUser"),
|
|
dr.GetBoolean("published"),
|
|
dr.GetString("path"), dr.GetString("text"),
|
|
dr.GetDateTime("createDate"),
|
|
dr.GetDateTime("updateDate"),
|
|
dr.GetDateTime("versionDate"), dr.GetString("icon"), _hc);
|
|
|
|
// initialize content object
|
|
InitializeContent(dr.GetInt("ContentType"), dr.GetGuid("versionId"),
|
|
dr.GetDateTime("versionDate"), dr.GetString("icon"));
|
|
|
|
// initialize final document properties
|
|
DateTime tmpReleaseDate = new DateTime();
|
|
DateTime tmpExpireDate = new DateTime();
|
|
if (!dr.IsNull("releaseDate"))
|
|
tmpReleaseDate = dr.GetDateTime("releaseDate");
|
|
if (!dr.IsNull("expireDate"))
|
|
tmpExpireDate = dr.GetDateTime("expireDate");
|
|
|
|
InitializeDocument(
|
|
new User(dr.GetInt("nodeUser"), true),
|
|
new User(dr.GetInt("documentUser"), true),
|
|
dr.GetString("documentText"),
|
|
dr.GetInt("templateId"),
|
|
tmpReleaseDate,
|
|
tmpExpireDate,
|
|
dr.GetDateTime("updateDate"),
|
|
dr.GetBoolean("published")
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public Document()
|
|
{
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility
|
|
/// </summary>
|
|
public override void Save()
|
|
{
|
|
SaveEventArgs e = new SaveEventArgs();
|
|
FireBeforeSave(e);
|
|
|
|
if (!e.Cancel) {
|
|
|
|
if (this._optimizedMode)
|
|
{
|
|
|
|
|
|
//I'd like to see this work by making a single SQL query
|
|
//all in due time ;)
|
|
foreach (var property in this._knownProperties)
|
|
{
|
|
var pt = property.Key;
|
|
pt.Value = property.Value;
|
|
}
|
|
}
|
|
|
|
base.Save();
|
|
Index(true);
|
|
FireAfterSave(e);
|
|
}
|
|
}
|
|
|
|
//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));
|
|
if (dr.Read())
|
|
{
|
|
_creator = User;
|
|
_writer = User.GetUser(dr.GetInt("documentUser"));
|
|
|
|
_text = dr.GetString("text");
|
|
if (!dr.IsNull("templateId"))
|
|
_template = dr.GetInt("templateId");
|
|
if (!dr.IsNull("releaseDate"))
|
|
_release = dr.GetDateTime("releaseDate");
|
|
if (!dr.IsNull("expireDate"))
|
|
_expire = dr.GetDateTime("expireDate");
|
|
if (!dr.IsNull("updateDate"))
|
|
_updated = dr.GetDateTime("updateDate");
|
|
}
|
|
dr.Close();
|
|
_published = (SqlHelper.ExecuteScalar<int>("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,
|
|
DateTime InitReleaseDate, DateTime InitExpireDate, DateTime InitUpdateDate,
|
|
bool InitPublished)
|
|
{
|
|
_creator = InitUser;
|
|
_writer = InitWriter;
|
|
_text = InitText;
|
|
_template = InitTemplate;
|
|
_release = InitReleaseDate;
|
|
_expire = InitExpireDate;
|
|
_updated = InitUpdateDate;
|
|
_published = InitPublished;
|
|
}
|
|
|
|
/// <summary>
|
|
/// The name of the document, amongst other used in the nice url.
|
|
/// </summary>
|
|
public new string Text
|
|
{
|
|
get
|
|
{
|
|
if (_text == null || _text == "")
|
|
_text = SqlHelper.ExecuteScalar<string>(string.Format("select text from umbracoNode where id = {0}", Id));
|
|
return _text;
|
|
}
|
|
set
|
|
{
|
|
_text = value;
|
|
base.Text = value;
|
|
SqlHelper.ExecuteNonQuery("update cmsDocument set text = @text where versionId = @versionId",
|
|
SqlHelper.CreateParameter("@text", _text),
|
|
SqlHelper.CreateParameter("@versionId", Version));
|
|
CMSNode c = new CMSNode(Id);
|
|
c.Text = _text;
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The date of the last update of the document
|
|
/// </summary>
|
|
public DateTime UpdateDate
|
|
{
|
|
get { return _updated; }
|
|
set
|
|
{
|
|
_updated = value;
|
|
SqlHelper.ExecuteNonQuery("update cmsDocument set updateDate = @value where versionId = @versionId",
|
|
SqlHelper.CreateParameter("@value", value),
|
|
SqlHelper.CreateParameter("@versionId", Version));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// A datestamp which indicates when a document should be published, used in automated publish/unpublish scenarios
|
|
/// </summary>
|
|
public DateTime ReleaseDate
|
|
{
|
|
get { return _release; }
|
|
set
|
|
{
|
|
_release = value;
|
|
|
|
if (_release.Year != 1 || _release.Month != 1 || _release.Day != 1)
|
|
SqlHelper.ExecuteNonQuery("update cmsDocument set releaseDate = @value where versionId = @versionId",
|
|
SqlHelper.CreateParameter("@value", value),
|
|
SqlHelper.CreateParameter("@versionId", Version));
|
|
else
|
|
SqlHelper.ExecuteNonQuery("update cmsDocument set releaseDate = NULL where versionId = @versionId",
|
|
SqlHelper.CreateParameter("@versionId", Version));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// A datestamp which indicates when a document should be unpublished, used in automated publish/unpublish scenarios
|
|
/// </summary>
|
|
public DateTime ExpireDate
|
|
{
|
|
get { return _expire; }
|
|
set
|
|
{
|
|
_expire = value;
|
|
|
|
if (_expire.Year != 1 || _expire.Month != 1 || _expire.Day != 1)
|
|
SqlHelper.ExecuteNonQuery("update cmsDocument set expireDate = @value where versionId=@versionId",
|
|
SqlHelper.CreateParameter("@value", value),
|
|
SqlHelper.CreateParameter("@versionId", Version));
|
|
else
|
|
SqlHelper.ExecuteNonQuery("update cmsDocument set expireDate = NULL where versionId=@versionId",
|
|
SqlHelper.CreateParameter("@versionId", Version));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The id of the template associated to the document
|
|
///
|
|
/// When a document is created, it will get have default template given by it's documenttype,
|
|
/// an editor is able to assign alternative templates (allowed by it's the documenttype)
|
|
///
|
|
/// You are always able to override the template in the runtime by appending the following to the querystring to the Url:
|
|
///
|
|
/// ?altTemplate=[templatealias]
|
|
/// </summary>
|
|
public int Template
|
|
{
|
|
get { return _template; }
|
|
set
|
|
{
|
|
_template = value;
|
|
SqlHelper.ExecuteNonQuery("update cmsDocument set templateId = @value where versionId = @versionId",
|
|
SqlHelper.CreateParameter("@value", _template),
|
|
SqlHelper.CreateParameter("@versionId", Version));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Used for rolling back documents to a previous version
|
|
/// </summary>
|
|
/// <returns> Previous published versions of the document</returns>
|
|
public DocumentVersionList[] GetVersions()
|
|
{
|
|
ArrayList versions = new ArrayList();
|
|
using (IRecordsReader dr =
|
|
SqlHelper.ExecuteReader("select documentUser, versionId, updateDate, text from cmsDocument where nodeId = @nodeId order by updateDate",
|
|
SqlHelper.CreateParameter("@nodeId", Id)))
|
|
{
|
|
while (dr.Read())
|
|
{
|
|
DocumentVersionList dv =
|
|
new DocumentVersionList(dr.GetGuid("versionId"),
|
|
dr.GetDateTime("updateDate"),
|
|
dr.GetString("text"),
|
|
User.GetUser(dr.GetInt("documentUser")));
|
|
versions.Add(dv);
|
|
}
|
|
}
|
|
|
|
DocumentVersionList[] retVal = new DocumentVersionList[versions.Count];
|
|
int i = 0;
|
|
foreach (DocumentVersionList dv in versions)
|
|
{
|
|
retVal[i] = dv;
|
|
i++;
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <returns>Returns a breadcrumlike path for the document like: /ancestorname/ancestorname</returns>
|
|
public string GetTextPath()
|
|
{
|
|
string tempPath = "";
|
|
string[] splitPath = Path.Split(".".ToCharArray());
|
|
for (int i = 1; i < Level; i++)
|
|
{
|
|
tempPath += new Document(int.Parse(splitPath[i])).Text + "/";
|
|
}
|
|
if (tempPath.Length > 0)
|
|
tempPath = tempPath.Substring(0, tempPath.Length - 1);
|
|
return tempPath;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a new document of the same type and copies all data from the current onto it
|
|
/// </summary>
|
|
/// <param name="CopyTo">The parentid where the document should be copied to</param>
|
|
/// <param name="u">The usercontext under which the action are performed</param>
|
|
public void Copy(int CopyTo, User u)
|
|
{
|
|
Copy(CopyTo, u, false);
|
|
}
|
|
|
|
public void Copy(int CopyTo, User u, bool RelateToOrignal)
|
|
{
|
|
CopyEventArgs e = new CopyEventArgs();
|
|
|
|
FireBeforeCopy(e);
|
|
|
|
if (!e.Cancel) {
|
|
// Make the new document
|
|
Document NewDoc = MakeNew(Text, new DocumentType(ContentType.Id), u, CopyTo);
|
|
|
|
// update template
|
|
NewDoc.Template = Template;
|
|
|
|
// Copy the properties of the current document
|
|
foreach (Property p in getProperties)
|
|
NewDoc.getProperty(p.PropertyType.Alias).Value = p.Value;
|
|
|
|
// Relate?
|
|
if (RelateToOrignal) {
|
|
Relation.MakeNew(Id, NewDoc.Id, RelationType.GetByAlias("relateDocumentOnCopy"), "");
|
|
|
|
// Add to audit trail
|
|
Log.Add(LogTypes.Copy, u, NewDoc.Id, "Copied and related from " + Text + " (id: " + Id.ToString() + ")");
|
|
}
|
|
|
|
|
|
// Copy the children
|
|
foreach (Document c in Children)
|
|
c.Copy(NewDoc.Id, u, RelateToOrignal);
|
|
|
|
|
|
FireAfterCopy(e);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a new document
|
|
/// </summary>
|
|
/// <param name="Name">The name (.Text property) of the document</param>
|
|
/// <param name="dct">The documenttype</param>
|
|
/// <param name="u">The usercontext under which the action are performed</param>
|
|
/// <param name="ParentId">The id of the parent to the document</param>
|
|
/// <returns>The newly created document</returns>
|
|
public static Document MakeNew(string Name, DocumentType dct, User u, int ParentId)
|
|
{
|
|
//allows you to cancel a document before anything goes to the DB
|
|
var newingArgs = new DocumentNewingEventArgs()
|
|
{
|
|
Text = Name,
|
|
DocumentType = dct,
|
|
User = u,
|
|
ParentId = ParentId
|
|
};
|
|
Document.Newing(null, newingArgs);
|
|
if (newingArgs.Cancel)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
|
|
Guid newId = Guid.NewGuid();
|
|
Document tmp = new Document(newId, true);
|
|
|
|
// Updated to match level from base node
|
|
CMSNode n = new CMSNode(ParentId);
|
|
int newLevel = n.Level;
|
|
newLevel++;
|
|
MakeNew(ParentId, _objectType, u.Id, newLevel, Name, newId);
|
|
tmp.CreateContent(dct);
|
|
SqlHelper.ExecuteNonQuery("insert into cmsDocument (newest, nodeId, published, documentUser, versionId, Text) values (1, " +
|
|
tmp.Id + ", 0, " +
|
|
u.Id + ", @versionId, @text)",
|
|
SqlHelper.CreateParameter("@versionId", tmp.Version),
|
|
SqlHelper.CreateParameter("@text", tmp.Text));
|
|
|
|
// Update the sortOrder if the parent was the root!
|
|
if (ParentId == -1)
|
|
{
|
|
CMSNode c = new CMSNode(newId);
|
|
c.sortOrder = GetRootDocuments().Length + 1;
|
|
}
|
|
|
|
Document d = new Document(newId);
|
|
|
|
//event
|
|
NewEventArgs e = new NewEventArgs();
|
|
d.OnNew(e);
|
|
|
|
// Log
|
|
Log.Add(LogTypes.New, u, d.Id, "");
|
|
|
|
// Run Handler
|
|
umbraco.BusinessLogic.Actions.Action.RunActionHandlers(d, ActionNew.Instance);
|
|
|
|
// Index
|
|
AddToIndexEventArgs ie = new AddToIndexEventArgs();
|
|
d.FireBeforeAddToIndex(ie);
|
|
|
|
if (!ie.Cancel) {
|
|
System.Threading.ThreadPool.QueueUserWorkItem(
|
|
delegate
|
|
{
|
|
try {
|
|
|
|
Indexer.IndexNode(_objectType, d.Id, d.Text, d.User.Name, d.CreateDateTime, null, true);
|
|
|
|
|
|
} catch (Exception ee) {
|
|
Log.Add(LogTypes.Error, d.User, d.Id,
|
|
string.Format("Error indexing document: {0}", ee));
|
|
}
|
|
});
|
|
d.FireAfterAddToIndex(ie);
|
|
}
|
|
|
|
return d;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Used to get the firstlevel/root documents of the hierachy
|
|
/// </summary>
|
|
/// <returns>Root documents</returns>
|
|
public static Document[] GetRootDocuments()
|
|
{
|
|
Guid[] topNodeIds = TopMostNodeIds(_objectType);
|
|
|
|
Document[] retval = new Document[topNodeIds.Length];
|
|
for (int i = 0; i < topNodeIds.Length; i++)
|
|
{
|
|
Document d = new Document(topNodeIds[i]);
|
|
retval[i] = d;
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
/// <summary>
|
|
/// A collection of documents imidiately underneath this document ie. the childdocuments
|
|
/// </summary>
|
|
public new Document[] Children
|
|
{
|
|
get
|
|
{
|
|
IconI[] tmp = base.Children;
|
|
Document[] retval = new Document[tmp.Length];
|
|
for (int i = 0; i < tmp.Length; i++) retval[i] = new Document(tmp[i].Id);
|
|
return retval;
|
|
}
|
|
}
|
|
|
|
public static int CountSubs(int parentId, bool publishedOnly)
|
|
{
|
|
if (!publishedOnly)
|
|
{
|
|
return CountSubs(parentId);
|
|
}
|
|
else
|
|
{
|
|
return SqlHelper.ExecuteScalar<int>("SELECT COUNT(distinct nodeId) FROM umbracoNode INNER JOIN cmsDocument ON cmsDocument.published = 1 and cmsDocument.nodeId = umbracoNode.id WHERE ','+path+',' LIKE '%," + parentId.ToString() + ",%'");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deletes the current document (and all children recursive)
|
|
/// </summary>
|
|
public new void delete()
|
|
{
|
|
// Check for recyle bin
|
|
if (!Path.Contains(",-20,")) {
|
|
|
|
MoveToTrashEventArgs e = new MoveToTrashEventArgs();
|
|
FireBeforeMoveToTrash(e);
|
|
|
|
if (!e.Cancel) {
|
|
umbraco.BusinessLogic.Actions.Action.RunActionHandlers(this, ActionDelete.Instance);
|
|
UnPublish();
|
|
Move(-20);
|
|
|
|
FireAfterMoveToTrash(e);
|
|
}
|
|
|
|
} else {
|
|
|
|
DeleteEventArgs e = new DeleteEventArgs();
|
|
|
|
FireBeforeDelete(e);
|
|
|
|
if (!e.Cancel) {
|
|
|
|
try {
|
|
Indexer.RemoveNode(Id);
|
|
} catch {}
|
|
|
|
foreach (Document d in Children) {
|
|
d.delete();
|
|
}
|
|
|
|
umbraco.BusinessLogic.Actions.Action.RunActionHandlers(this, ActionDelete.Instance);
|
|
|
|
//delete files
|
|
interfaces.IDataType uploadField = new cms.businesslogic.datatype.controls.Factory().GetNewObject(new Guid("5032a6e6-69e3-491d-bb28-cd31cd11086c"));
|
|
|
|
foreach (cms.businesslogic.property.Property p in this.getProperties)
|
|
|
|
if (p.PropertyType.DataTypeDefinition.DataType.Id == uploadField.Id &&
|
|
p.Value.ToString() != "" &&
|
|
System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath(p.Value.ToString()))
|
|
)
|
|
System.IO.File.Delete(System.Web.HttpContext.Current.Server.MapPath(p.Value.ToString()));
|
|
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deletes all documents of a type, will be invoked if a documenttype is deleted.
|
|
///
|
|
/// Note: use with care: this method can result in wast amount of data being deleted.
|
|
/// </summary>
|
|
/// <param name="dt">The type of which documents should be deleted</param>
|
|
public static void DeleteFromType(DocumentType dt)
|
|
{
|
|
foreach (Content c in getContentOfContentType(dt))
|
|
{
|
|
// due to recursive structure document might already been deleted..
|
|
if (IsNode(c.UniqueId))
|
|
{
|
|
Document tmp = new Document(c.UniqueId);
|
|
tmp.delete();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Indexes the documents data for internal search
|
|
/// </summary>
|
|
/// <param name="Optimze">If on the indexer will optimize</param>
|
|
public void Index(bool Optimze)
|
|
{
|
|
AddToIndexEventArgs e = new AddToIndexEventArgs();
|
|
FireBeforeAddToIndex(e);
|
|
|
|
if (!e.Cancel) {
|
|
try {
|
|
|
|
|
|
Hashtable fields = new Hashtable();
|
|
foreach (Property p in getProperties)
|
|
fields.Add(p.PropertyType.Alias, p.Value.ToString());
|
|
// Indexer.IndexDirectory = HttpContext.Server.MapPath(Indexer.RelativeIndexDir);
|
|
Indexer.IndexNode(_objectType, Id, Text, User.Name, CreateDateTime, fields, Optimze);
|
|
|
|
FireAfterAddToIndex(e);
|
|
} catch (Exception ee) {
|
|
Log.Add(LogTypes.Error, User, Id,
|
|
string.Format("Error indexing node: {0}", ee));
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Refreshes the xml, used when publishing data on a document which already is published
|
|
/// </summary>
|
|
/// <param name="xd">The source xmldocument</param>
|
|
/// <param name="x">The previous xmlrepresentation of the document</param>
|
|
public void XmlNodeRefresh(XmlDocument xd, ref XmlNode x)
|
|
{
|
|
x.Attributes.RemoveAll();
|
|
foreach (XmlNode xDel in x.SelectNodes("./data"))
|
|
x.RemoveChild(xDel);
|
|
|
|
XmlPopulate(xd, ref x, false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates an xmlrepresentation of the documet and saves it to the database
|
|
/// </summary>
|
|
/// <param name="xd"></param>
|
|
public new void XmlGenerate(XmlDocument xd)
|
|
{
|
|
XmlNode x = xd.CreateNode(XmlNodeType.Element, "node", "");
|
|
XmlPopulate(xd, ref x, false);
|
|
|
|
// Save to db
|
|
saveXml(x);
|
|
}
|
|
|
|
private void saveXml(XmlNode x)
|
|
{
|
|
bool exists = (SqlHelper.ExecuteScalar<int>("SELECT COUNT(nodeId) FROM cmsContentXml WHERE nodeId=@nodeId",
|
|
SqlHelper.CreateParameter("@nodeId", Id)) != 0);
|
|
string sql = exists ? "UPDATE cmsContentXml SET xml = @xml WHERE nodeId=@nodeId"
|
|
: "INSERT INTO cmsContentXml(nodeId, xml) VALUES (@nodeId, @xml)";
|
|
SqlHelper.ExecuteNonQuery(sql,
|
|
SqlHelper.CreateParameter("@nodeId", Id),
|
|
SqlHelper.CreateParameter("@xml", x.OuterXml));
|
|
}
|
|
|
|
private XmlNode importXml()
|
|
{
|
|
XmlDocument xmlDoc = new XmlDocument();
|
|
XmlReader xmlRdr = SqlHelper.ExecuteXmlReader(string.Format(
|
|
"select xml from cmsContentXml where nodeID = {0}", Id));
|
|
xmlDoc.Load(xmlRdr);
|
|
|
|
return xmlDoc.FirstChild;
|
|
}
|
|
|
|
/// <summary>
|
|
/// A xmlrepresentaion of the document, used when publishing/exporting the document,
|
|
///
|
|
/// Optional: Recursive get childdocuments xmlrepresentation
|
|
/// </summary>
|
|
/// <param name="xd">The xmldocument</param>
|
|
/// <param name="Deep">Recursive add of childdocuments</param>
|
|
/// <returns></returns>
|
|
public new virtual XmlNode ToXml(XmlDocument xd, bool Deep)
|
|
{
|
|
if (Published)
|
|
{
|
|
if (_xml == null)
|
|
{
|
|
// Load xml from db if _xml hasn't been loaded yet
|
|
_xml = importXml();
|
|
|
|
// Generate xml if xml still null (then it hasn't been initialized before)
|
|
if (_xml == null)
|
|
{
|
|
XmlGenerate(new XmlDocument());
|
|
_xml = importXml();
|
|
}
|
|
}
|
|
|
|
XmlNode x = xd.ImportNode(_xml, true);
|
|
|
|
if (Deep)
|
|
{
|
|
foreach (Document d in Children)
|
|
if (d.Published)
|
|
x.AppendChild(d.ToXml(xd, true));
|
|
}
|
|
|
|
return x;
|
|
}
|
|
else
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Populate a documents xmlnode
|
|
/// </summary>
|
|
/// <param name="xd">Xmldocument context</param>
|
|
/// <param name="x">The node to fill with data</param>
|
|
/// <param name="Deep">If true the documents childrens xmlrepresentation will be appended to the Xmlnode recursive</param>
|
|
public override void XmlPopulate(XmlDocument xd, ref XmlNode x, bool Deep)
|
|
{
|
|
string urlName = this.Text;
|
|
foreach (Property p in getProperties)
|
|
if (p != null)
|
|
{
|
|
x.AppendChild(p.ToXml(xd));
|
|
if (p.PropertyType.Alias == "umbracoUrlName" && p.Value.ToString().Trim() != string.Empty)
|
|
urlName = p.Value.ToString();
|
|
}
|
|
|
|
// attributes
|
|
x.Attributes.Append(addAttribute(xd, "id", Id.ToString()));
|
|
x.Attributes.Append(addAttribute(xd, "version", Version.ToString()));
|
|
if (Level > 1)
|
|
x.Attributes.Append(addAttribute(xd, "parentID", Parent.Id.ToString()));
|
|
else
|
|
x.Attributes.Append(addAttribute(xd, "parentID", "-1"));
|
|
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()));
|
|
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")));
|
|
x.Attributes.Append(addAttribute(xd, "updateDate", VersionDate.ToString("s")));
|
|
x.Attributes.Append(addAttribute(xd, "nodeName", Text));
|
|
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)
|
|
x.Attributes.Append(addAttribute(xd, "nodeTypeAlias", ContentType.Alias));
|
|
x.Attributes.Append(addAttribute(xd, "path", Path));
|
|
|
|
if (Deep)
|
|
{
|
|
foreach (Document d in Children)
|
|
x.AppendChild(d.ToXml(xd, true));
|
|
}
|
|
}
|
|
|
|
public void refreshXmlSortOrder()
|
|
{
|
|
if (Published)
|
|
{
|
|
if (_xml == null)
|
|
// Load xml from db if _xml hasn't been loaded yet
|
|
_xml = importXml();
|
|
|
|
// Generate xml if xml still null (then it hasn't been initialized before)
|
|
if (_xml == null)
|
|
{
|
|
XmlGenerate(new XmlDocument());
|
|
_xml = importXml();
|
|
}
|
|
else
|
|
{
|
|
// Update the sort order attr
|
|
_xml.Attributes.GetNamedItem("sortOrder").Value = sortOrder.ToString();
|
|
saveXml(_xml);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private XmlAttribute addAttribute(XmlDocument Xd, string Name, string Value)
|
|
{
|
|
XmlAttribute temp = Xd.CreateAttribute(Name);
|
|
temp.Value = Value;
|
|
return temp;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Performance tuned method for use in the tree
|
|
/// </summary>
|
|
/// <param name="NodeId">The parentdocuments id</param>
|
|
/// <returns></returns>
|
|
public static Document[] GetChildrenForTree(int NodeId)
|
|
{
|
|
ArrayList tmp = new ArrayList();
|
|
using (IRecordsReader dr =
|
|
SqlHelper.ExecuteReader(
|
|
// Ruben Verborgh: Rewrote this without temporary table, but we really should make a view of this
|
|
@"
|
|
select
|
|
count(children.id) as children, umbracoNode.id, umbracoNode.uniqueId, umbracoNode.level, umbracoNode.parentId, cmsDocument.documentUser, umbracoNode.path, umbracoNode.sortOrder, coalesce(publishCheck.published,0) as published, umbracoNode.createDate, cmsDocument.text, cmsDocument.updateDate, cmsContentVersion.versionDate, cmsContentType.icon
|
|
from umbracoNode
|
|
left join umbracoNode children on children.parentId = umbracoNode.id
|
|
inner join cmsContent on cmsContent.nodeId = umbracoNode.id
|
|
inner join cmsContentType on cmsContentType.nodeId = cmsContent.contentType
|
|
inner join (select contentId, max(versionDate) AS versionDate from cmsContentVersion
|
|
inner join umbracoNode on umbracoNode.id = cmsContentVersion.contentId and umbracoNode.parentId = @parentId
|
|
group by contentId) AS temp
|
|
on temp.contentId = cmsContent.nodeId
|
|
inner join cmsContentVersion on cmsContentVersion.contentId = temp.contentId and cmsContentVersion.versionDate = temp.versionDate
|
|
inner join cmsDocument on cmsDocument.versionId = cmsContentversion.versionId
|
|
left join cmsDocument publishCheck on publishCheck.nodeId = cmsContent.nodeID and publishCheck.published = 1
|
|
where umbracoNode.parentID = @parentId
|
|
group by umbracoNode.id, umbracoNode.uniqueId, umbracoNode.level, umbracoNode.parentId, cmsDocument.documentUser, umbracoNode.path, umbracoNode.sortOrder, coalesce(publishCheck.published,0), umbracoNode.createDate, cmsDocument.text, cmsDocument.updateDate, cmsContentVersion.versionDate, cmsContentType.icon
|
|
order by umbracoNode.sortOrder
|
|
",
|
|
SqlHelper.CreateParameter("@parentId", NodeId)))
|
|
{
|
|
while (dr.Read())
|
|
{
|
|
Document d = new Document(dr.GetInt("id"), true);
|
|
bool _hc = false;
|
|
if (dr.GetInt("children") > 0)
|
|
_hc = true;
|
|
d.SetupDocumentForTree(dr.GetGuid("uniqueId"), dr.GetShort("level"),
|
|
dr.GetInt("parentId"),
|
|
dr.GetInt("documentUser"),
|
|
(dr.GetInt("published")==1),
|
|
dr.GetString("path"), dr.GetString("text"),
|
|
dr.GetDateTime("createDate"),
|
|
dr.GetDateTime("updateDate"),
|
|
dr.GetDateTime("versionDate"), dr.GetString("icon"), _hc);
|
|
tmp.Add(d);
|
|
}
|
|
}
|
|
|
|
Document[] retval = new Document[tmp.Count];
|
|
|
|
for (int i = 0; i < tmp.Count; i ++)
|
|
retval[i] = (Document) tmp[i];
|
|
|
|
return retval;
|
|
}
|
|
|
|
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)
|
|
{
|
|
SetupNodeForTree(uniqueId, _objectType, level, parentId, user, path, text, createDate, hasChildren);
|
|
|
|
_published = publish;
|
|
_updated = updateDate;
|
|
ContentTypeIcon = icon;
|
|
VersionDate = versionDate;
|
|
}
|
|
|
|
public static void RePublishAll()
|
|
{
|
|
XmlDocument xd = new XmlDocument();
|
|
SqlHelper.ExecuteNonQuery("truncate table cmsContentXml");
|
|
IRecordsReader dr = SqlHelper.ExecuteReader("select nodeId from cmsDocument where published = 1");
|
|
|
|
while (dr.Read())
|
|
{
|
|
try
|
|
{
|
|
new Document(dr.GetInt("nodeId")).XmlGenerate(xd);
|
|
}
|
|
catch (Exception ee)
|
|
{
|
|
Log.Add(LogTypes.Error, User.GetUser(0), dr.GetInt("nodeId"),
|
|
string.Format("Error generating xml: {0}", ee));
|
|
}
|
|
}
|
|
dr.Close();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieve a list of documents with an expirationdate greater than today
|
|
/// </summary>
|
|
/// <returns>A list of documents with expirationdates than today</returns>
|
|
public static Document[] GetDocumentsForExpiration()
|
|
{
|
|
ArrayList docs = new ArrayList();
|
|
IRecordsReader dr =
|
|
SqlHelper.ExecuteReader("select distinct nodeId from cmsDocument where newest = 1 and not expireDate is null and expireDate <= @today",
|
|
SqlHelper.CreateParameter("@today", DateTime.Now));
|
|
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]);
|
|
return retval;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieve a list of documents with with releasedate greater than today
|
|
/// </summary>
|
|
/// <returns>Retrieve a list of documents with with releasedate greater than today</returns>
|
|
public static Document[] GetDocumentsForRelease()
|
|
{
|
|
ArrayList docs = new ArrayList();
|
|
IRecordsReader dr = SqlHelper.ExecuteReader("select distinct nodeId, level, sortOrder from cmsDocument inner join umbracoNode on umbracoNode.id = cmsDocument.nodeId where newest = 1 and not releaseDate is null and releaseDate <= @today order by [level], sortOrder",
|
|
SqlHelper.CreateParameter("@today", DateTime.Now));
|
|
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]);
|
|
|
|
return retval;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Imports (create) a document from a xmlrepresentation of a document, used by the packager
|
|
/// </summary>
|
|
/// <param name="ParentId">The id to import to</param>
|
|
/// <param name="Creator">Creator of the new document</param>
|
|
/// <param name="Source">Xmlsource</param>
|
|
public static int Import(int ParentId, User Creator, XmlElement Source)
|
|
{
|
|
Document d = MakeNew(
|
|
Source.GetAttribute("nodeName"),
|
|
DocumentType.GetByAlias(Source.GetAttribute("nodeTypeAlias")),
|
|
Creator,
|
|
ParentId);
|
|
|
|
d.CreateDateTime = DateTime.Parse(Source.GetAttribute("createDate"));
|
|
|
|
// Properties
|
|
foreach (XmlElement n in Source.SelectNodes("data"))
|
|
{
|
|
Property prop = d.getProperty(n.GetAttribute("alias"));
|
|
string propValue = xmlHelper.GetNodeValue(n);
|
|
|
|
// only update real values
|
|
if (!String.IsNullOrEmpty(propValue))
|
|
{
|
|
//test if the property has prevalues, of so, try to convert the imported values so they match the new ones
|
|
SortedList prevals = cms.businesslogic.datatype.PreValues.GetPreValues(prop.PropertyType.DataTypeDefinition.Id);
|
|
|
|
//Okey we found some prevalue, let's replace the vals with some ids
|
|
if (prevals.Count > 0)
|
|
{
|
|
System.Collections.Generic.List<string> list = new System.Collections.Generic.List<string>(propValue.Split(','));
|
|
|
|
foreach (DictionaryEntry item in prevals)
|
|
{
|
|
string pval = ((umbraco.cms.businesslogic.datatype.PreValue)item.Value).Value;
|
|
string pid = ((umbraco.cms.businesslogic.datatype.PreValue)item.Value).Id.ToString();
|
|
|
|
if (list.Contains(pval))
|
|
list[list.IndexOf(pval)] = pid;
|
|
|
|
}
|
|
|
|
//join the list of new values and return it as the new property value
|
|
System.Text.StringBuilder builder = new System.Text.StringBuilder();
|
|
bool isFirst = true;
|
|
|
|
foreach (string str in list)
|
|
{
|
|
if (!isFirst)
|
|
builder.Append(",");
|
|
|
|
builder.Append(str);
|
|
isFirst = false;
|
|
}
|
|
prop.Value = builder.ToString();
|
|
|
|
}
|
|
else
|
|
prop.Value = propValue;
|
|
}
|
|
}
|
|
|
|
// Subpages
|
|
foreach (XmlElement n in Source.SelectNodes("node"))
|
|
Import(d.Id, Creator, n);
|
|
|
|
return d.Id;
|
|
}
|
|
|
|
//EVENTS
|
|
/// <summary>
|
|
/// The save event handler
|
|
/// </summary>
|
|
public delegate void SaveEventHandler(Document sender, SaveEventArgs e);
|
|
/// <summary>
|
|
/// The New event handler
|
|
/// </summary>
|
|
public delegate void NewEventHandler(Document sender, NewEventArgs e);
|
|
/// <summary>
|
|
/// The delete event handler
|
|
/// </summary>
|
|
public delegate void DeleteEventHandler(Document sender, DeleteEventArgs e);
|
|
/// <summary>
|
|
/// The publish event handler
|
|
/// </summary>
|
|
public delegate void PublishEventHandler(Document sender, PublishEventArgs e);
|
|
/// <summary>
|
|
/// The Send To Publish event handler
|
|
/// </summary>
|
|
public delegate void SendToPublishEventHandler(Document sender, SendToPublishEventArgs e);
|
|
/// <summary>
|
|
/// The unpublish event handler
|
|
/// </summary>
|
|
public delegate void UnPublishEventHandler(Document sender, UnPublishEventArgs e);
|
|
/// <summary>
|
|
/// The copy event handler
|
|
/// </summary>
|
|
public delegate void CopyEventHandler(Document sender, CopyEventArgs e);
|
|
/// <summary>
|
|
/// The rollback event handler
|
|
/// </summary>
|
|
public delegate void RollBackEventHandler(Document sender, RollBackEventArgs e);
|
|
|
|
/// <summary>
|
|
/// The Move to trash event handler
|
|
/// </summary>
|
|
public delegate void MoveToTrashEventHandler(Document sender, MoveToTrashEventArgs e);
|
|
|
|
|
|
/// <summary>
|
|
/// The index event handlers
|
|
/// </summary>
|
|
public delegate void IndexEventHandler(Document sender, AddToIndexEventArgs e);
|
|
|
|
/// <summary>
|
|
/// Occurs when [before save].
|
|
/// </summary>
|
|
public static event SaveEventHandler BeforeSave;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:BeforeSave"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireBeforeSave(SaveEventArgs e) {
|
|
if (BeforeSave != null) {
|
|
BeforeSave(this, e); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs when [after save].
|
|
/// </summary>
|
|
public static event SaveEventHandler AfterSave;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:AfterSave"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireAfterSave(SaveEventArgs e) {
|
|
if (AfterSave != null) {
|
|
AfterSave(this, e);
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Occurs when [new].
|
|
/// </summary>
|
|
public static event NewEventHandler New;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:New"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void OnNew(NewEventArgs e) {
|
|
if (New != null)
|
|
New(this, e);
|
|
}
|
|
|
|
//TODO: Slace - Document this
|
|
public static event EventHandler<DocumentNewingEventArgs> Newing;
|
|
protected virtual void OnNewing(DocumentNewingEventArgs e)
|
|
{
|
|
if (Newing != null)
|
|
{
|
|
Newing(this, e);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs when [before delete].
|
|
/// </summary>
|
|
public static event DeleteEventHandler BeforeDelete;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:BeforeDelete"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireBeforeDelete(DeleteEventArgs e) {
|
|
if (BeforeDelete != null)
|
|
BeforeDelete(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs when [after delete].
|
|
/// </summary>
|
|
public static event DeleteEventHandler AfterDelete;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:AfterDelete"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireAfterDelete(DeleteEventArgs e) {
|
|
if (AfterDelete != null)
|
|
AfterDelete(this, e);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Occurs when [before delete].
|
|
/// </summary>
|
|
public static event MoveToTrashEventHandler BeforeMoveToTrash;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:BeforeDelete"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireBeforeMoveToTrash(MoveToTrashEventArgs e) {
|
|
if (BeforeMoveToTrash != null)
|
|
BeforeMoveToTrash(this, e);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Occurs when [after move to trash].
|
|
/// </summary>
|
|
public static event MoveToTrashEventHandler AfterMoveToTrash;
|
|
/// <summary>
|
|
/// Fires the after move to trash.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="umbraco.cms.businesslogic.MoveToTrashEventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireAfterMoveToTrash(MoveToTrashEventArgs e) {
|
|
if (AfterMoveToTrash != null)
|
|
AfterMoveToTrash(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs when [before publish].
|
|
/// </summary>
|
|
public static event PublishEventHandler BeforePublish;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:BeforePublish"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireBeforePublish(PublishEventArgs e)
|
|
{
|
|
if (BeforePublish != null)
|
|
BeforePublish(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs when [after publish].
|
|
/// </summary>
|
|
public static event PublishEventHandler AfterPublish;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:AfterPublish"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireAfterPublish(PublishEventArgs e)
|
|
{
|
|
if (AfterPublish != null)
|
|
AfterPublish(this, e);
|
|
}
|
|
/// <summary>
|
|
/// Occurs when [before publish].
|
|
/// </summary>
|
|
public static event SendToPublishEventHandler BeforeSendToPublish;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:BeforePublish"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireBeforeSendToPublish(SendToPublishEventArgs e)
|
|
{
|
|
if (BeforeSendToPublish != null)
|
|
BeforeSendToPublish(this, e);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Occurs when [after publish].
|
|
/// </summary>
|
|
public static event SendToPublishEventHandler AfterSendToPublish;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:AfterPublish"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireAfterSendToPublish(SendToPublishEventArgs e)
|
|
{
|
|
if (AfterSendToPublish != null)
|
|
AfterSendToPublish(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs when [before un publish].
|
|
/// </summary>
|
|
public static event UnPublishEventHandler BeforeUnPublish;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:BeforeUnPublish"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireBeforeUnPublish(UnPublishEventArgs e) {
|
|
if (BeforeUnPublish != null)
|
|
BeforeUnPublish(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs when [after un publish].
|
|
/// </summary>
|
|
public static event UnPublishEventHandler AfterUnPublish;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:AfterUnPublish"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireAfterUnPublish(UnPublishEventArgs e) {
|
|
if (AfterUnPublish != null)
|
|
AfterUnPublish(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs when [before copy].
|
|
/// </summary>
|
|
public static event CopyEventHandler BeforeCopy;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:BeforeCopy"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireBeforeCopy(CopyEventArgs e) {
|
|
if (BeforeCopy != null)
|
|
BeforeCopy(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs when [after copy].
|
|
/// </summary>
|
|
public static event CopyEventHandler AfterCopy;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:AfterCopy"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireAfterCopy(CopyEventArgs e) {
|
|
if (AfterCopy != null)
|
|
AfterCopy(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs when [before roll back].
|
|
/// </summary>
|
|
public static event RollBackEventHandler BeforeRollBack;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:BeforeRollBack"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireBeforeRollBack(RollBackEventArgs e) {
|
|
if (BeforeRollBack != null)
|
|
BeforeRollBack(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs when [after roll back].
|
|
/// </summary>
|
|
public static event RollBackEventHandler AfterRollBack;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:AfterRollBack"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireAfterRollBack(RollBackEventArgs e) {
|
|
if (AfterRollBack != null)
|
|
AfterRollBack(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs when [before add to index].
|
|
/// </summary>
|
|
public static event IndexEventHandler BeforeAddToIndex;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:BeforeAddToIndex"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireBeforeAddToIndex(AddToIndexEventArgs e) {
|
|
if (BeforeAddToIndex != null)
|
|
BeforeAddToIndex(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs when [after add to index].
|
|
/// </summary>
|
|
public static event IndexEventHandler AfterAddToIndex;
|
|
/// <summary>
|
|
/// Raises the <see cref="E:AfterAddToIndex"/> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
|
|
protected virtual void FireAfterAddToIndex(AddToIndexEventArgs e) {
|
|
if (AfterAddToIndex != null)
|
|
AfterAddToIndex(this, e);
|
|
}
|
|
|
|
private Dictionary<Property, object> _knownProperties;
|
|
private Func<KeyValuePair<Property, object>, string, bool> propertyTypeByAlias = (pt, alias) => pt.Key.PropertyType.Alias == alias;
|
|
public object this[string alias]
|
|
{
|
|
get
|
|
{
|
|
if (this._optimizedMode)
|
|
{
|
|
if (this._knownProperties == null) this._knownProperties = new Dictionary<Property, object>();
|
|
|
|
return this._knownProperties.Single(p => propertyTypeByAlias(p, alias)).Value;
|
|
}
|
|
else
|
|
{
|
|
return this.getProperty(alias).Value;
|
|
}
|
|
}
|
|
set
|
|
{
|
|
if (this._optimizedMode)
|
|
{
|
|
if (this._knownProperties == null) this._knownProperties = new Dictionary<Property, object>();
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// A lightweight datastructure used to represent a version of a document
|
|
/// </summary>
|
|
public class DocumentVersionList
|
|
{
|
|
private Guid _version;
|
|
private DateTime _date;
|
|
private string _text;
|
|
private User _user;
|
|
|
|
/// <summary>
|
|
/// The unique id of the version
|
|
/// </summary>
|
|
public Guid Version
|
|
{
|
|
get { return _version; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The date of the creation of the version
|
|
/// </summary>
|
|
public DateTime Date
|
|
{
|
|
get { return _date; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The name of the document in the version
|
|
/// </summary>
|
|
public string Text
|
|
{
|
|
get { return _text; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The user which created the version
|
|
/// </summary>
|
|
public User User
|
|
{
|
|
get { return _user; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the DocumentVersionList class.
|
|
/// </summary>
|
|
/// <param name="Version">Unique version id</param>
|
|
/// <param name="Date">Version createdate</param>
|
|
/// <param name="Text">Version name</param>
|
|
/// <param name="User">Creator</param>
|
|
public DocumentVersionList(Guid Version, DateTime Date, string Text, User User)
|
|
{
|
|
_version = Version;
|
|
_date = Date;
|
|
_text = Text;
|
|
_user = User;
|
|
}
|
|
}
|
|
}
|