More unit tests.
Fixes: 16981 - no longer data loss when deleting document types with nested document type children Fixes: 27096, 27098, 27106, 27107, 27108, 27110, 27111 [TFS Changeset #66192]
This commit is contained in:
@@ -13,6 +13,7 @@ using umbraco.editorControls.textfield;
|
||||
using umbraco.cms.businesslogic.propertytype;
|
||||
using umbraco.cms.businesslogic.property;
|
||||
using umbraco.cms.businesslogic.language;
|
||||
using umbraco.BusinessLogic.console;
|
||||
|
||||
namespace umbraco.Test
|
||||
{
|
||||
@@ -35,6 +36,50 @@ namespace umbraco.Test
|
||||
|
||||
#region Unit Tests
|
||||
|
||||
/// <summary>
|
||||
/// Creates a bunch of nodes in a heirarchy, then deletes the top most node (moves to the recycle bin
|
||||
/// and completely deletes from system.) This should completely delete all of these nodes from the database.
|
||||
/// </summary>
|
||||
[TestMethod()]
|
||||
public void Document_DeleteHeirarchyPermanentlyTest()
|
||||
{
|
||||
var docList = new List<Document>();
|
||||
var total = 20;
|
||||
var dt = new DocumentType(GetExistingDocTypeId());
|
||||
//allow the doc type to be created underneath itself
|
||||
dt.AllowedChildContentTypeIDs = new int[] { dt.Id };
|
||||
dt.Save();
|
||||
|
||||
//create 20 content nodes underneath each other, this will test deleting with heirarchy as well
|
||||
var lastParentId = -1;
|
||||
for (var i = 0; i < total; i++)
|
||||
{
|
||||
var newDoc = Document.MakeNew(i.ToString() + Guid.NewGuid().ToString("N"), dt, m_User, lastParentId);
|
||||
docList.Add(newDoc);
|
||||
Assert.IsTrue(docList[docList.Count - 1].Id > 0);
|
||||
lastParentId = newDoc.Id;
|
||||
}
|
||||
|
||||
//now delete all of them permanently, since they are nested, we only need to delete one
|
||||
docList.First().delete(true);
|
||||
|
||||
//make sure they are all gone
|
||||
foreach (var d in docList)
|
||||
{
|
||||
Assert.IsFalse(Document.IsNode(d.Id));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///A test for PublishWithResult
|
||||
///</summary>
|
||||
[TestMethod()]
|
||||
public void Document_PublishWithResultTest()
|
||||
{
|
||||
var val = m_NewRootDoc.PublishWithResult(m_User);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a doc type, assigns a domain to it and removes it
|
||||
/// </summary>
|
||||
@@ -83,26 +128,28 @@ namespace umbraco.Test
|
||||
{
|
||||
//System.Diagnostics.Debugger.Break();
|
||||
Document target = new Document(GetExistingNodeId());
|
||||
int parentId = target.Level == 1 ? -1 : target.Parent.Id;
|
||||
int parentId = target.ParentId;
|
||||
bool RelateToOrignal = false;
|
||||
|
||||
//get children ids for the current parent
|
||||
var childrenIds = target.Level == 1 ? Document.GetRootDocuments().ToList().Select(x => x.Id) : target.Parent.Children.ToList().Select(x => x.Id);
|
||||
var childrenIds = GetChildNodesOfParent(target).Select(x => x.Id);
|
||||
|
||||
//copy the node
|
||||
target.Copy(parentId, m_User, RelateToOrignal);
|
||||
|
||||
//test that the child id count + 1 is equal to the total child count
|
||||
Assert.AreEqual(childrenIds.Count() + 1, target.Level == 1 ? Document.GetRootDocuments().Count() : target.Parent.ChildCount);
|
||||
Assert.AreEqual(childrenIds.Count() + 1, GetChildNodesOfParent(target).Count(), "Child node counts do not match");
|
||||
|
||||
//get the list of new child ids from the parent
|
||||
var newChildIds = target.Level == 1 ? Document.GetRootDocuments().ToList().Select(x => x.Id) : target.Parent.Children.ToList().Select(x => x.Id);
|
||||
var newChildIds = GetChildNodesOfParent(target).Select(x => x.Id);
|
||||
//get the children difference which should be the new node
|
||||
var diff = newChildIds.Except(childrenIds);
|
||||
|
||||
|
||||
Assert.AreEqual(1, diff.Count());
|
||||
|
||||
//get the node that is the difference to compare
|
||||
Document newDoc = new Document(diff.First());
|
||||
Assert.AreEqual<int>(parentId, newDoc.ParentId);
|
||||
|
||||
RecycleAndDelete(newDoc);
|
||||
}
|
||||
@@ -115,15 +162,15 @@ namespace umbraco.Test
|
||||
{
|
||||
//System.Diagnostics.Debugger.Break();
|
||||
Document target = new Document(GetExistingNodeId());
|
||||
int parentId = target.Level == 1 ? -1 : target.Parent.Id;
|
||||
int parentId = target.ParentId;
|
||||
bool RelateToOrignal = true;
|
||||
|
||||
//get children ids
|
||||
var childrenIds = target.Parent.Children.ToList().Select(x => x.Id);
|
||||
//get children ids
|
||||
var childrenIds = GetChildNodesOfParent(target).Select(x => x.Id);
|
||||
|
||||
target.Copy(parentId, m_User, RelateToOrignal);
|
||||
|
||||
Assert.AreEqual(childrenIds.Count() + 1, target.Level == 1 ? Document.GetRootDocuments().Count() : target.Parent.ChildCount);
|
||||
Assert.AreEqual(childrenIds.Count() + 1, GetChildNodesOfParent(target).Count());
|
||||
|
||||
Document parent = new Document(parentId);
|
||||
//get the children difference which should be the new node
|
||||
@@ -355,7 +402,7 @@ namespace umbraco.Test
|
||||
var doc = new Document(GetExistingNodeId());
|
||||
//create new content based on the existing content in the same heirarchy
|
||||
var dt = new DocumentType(doc.ContentType.Id);
|
||||
var parentId = doc.Level == 1 ? -1 : doc.Parent.Id;
|
||||
var parentId = doc.ParentId;
|
||||
var newDoc = Document.MakeNew("NewDoc" + Guid.NewGuid().ToString("N"), dt, m_User, parentId);
|
||||
Assert.IsTrue(newDoc.Id > 0);
|
||||
|
||||
@@ -379,34 +426,36 @@ namespace umbraco.Test
|
||||
[TestMethod]
|
||||
public void Document_EmptyRecycleBinTest()
|
||||
{
|
||||
var totalTrashedItems = RecycleBin.Count(RecycleBin.RecycleBinType.Content);
|
||||
|
||||
var docList = new List<Document>();
|
||||
var total = 20;
|
||||
var dt = new DocumentType(GetExistingDocTypeId());
|
||||
//create 20 content nodes
|
||||
var dt = m_ExistingDocType;
|
||||
//allow the doc type to be created underneath itself
|
||||
dt.AllowedChildContentTypeIDs = new int[] { dt.Id };
|
||||
dt.Save();
|
||||
|
||||
//create 20 content nodes underneath each other, this will test deleting with heirarchy as well
|
||||
var lastParentId = -1;
|
||||
for (var i = 0; i < total; i++)
|
||||
{
|
||||
docList.Add(Document.MakeNew(i.ToString() + Guid.NewGuid().ToString("N"), dt, m_User, -1));
|
||||
var newDoc = Document.MakeNew("R-" + i.ToString() + Guid.NewGuid().ToString("N"), dt, m_User, lastParentId);
|
||||
docList.Add(newDoc);
|
||||
Assert.IsTrue(docList[docList.Count - 1].Id > 0);
|
||||
Assert.AreEqual(lastParentId, newDoc.ParentId);
|
||||
lastParentId = newDoc.Id;
|
||||
}
|
||||
|
||||
//now delete all of them
|
||||
foreach (var d in docList)
|
||||
{
|
||||
d.delete();
|
||||
Assert.IsTrue(d.IsTrashed);
|
||||
}
|
||||
//now delete all of them, since they are nested, we only need to delete one
|
||||
docList.First().delete();
|
||||
|
||||
//a callback action for each item removed from the recycle bin
|
||||
var totalDeleted = 0;
|
||||
var deleteCallback = new Action<int>(x =>
|
||||
{
|
||||
Assert.AreEqual((total + totalTrashedItems) - (++totalDeleted), x);
|
||||
});
|
||||
|
||||
var bin = new RecycleBin(RecycleBin.RecycleBinType.Content);
|
||||
bin.CallTheGarbageMan(deleteCallback);
|
||||
var totalTrashedItems = bin.GetDescendants().Cast<object>().Count();
|
||||
bin.CallTheGarbageMan(x =>
|
||||
{
|
||||
Assert.AreEqual(totalTrashedItems - (++totalDeleted), x);
|
||||
});
|
||||
|
||||
Assert.AreEqual(0, RecycleBin.Count(RecycleBin.RecycleBinType.Content));
|
||||
}
|
||||
@@ -540,21 +589,7 @@ namespace umbraco.Test
|
||||
// Assert.Inconclusive("A method that does not return a value cannot be verified.");
|
||||
//}
|
||||
|
||||
///// <summary>
|
||||
/////A test for PublishWithResult
|
||||
/////</summary>
|
||||
//[TestMethod()]
|
||||
//public void PublishWithResultTest()
|
||||
//{
|
||||
// Guid id = new Guid(); // TODO: Initialize to an appropriate value
|
||||
// Document target = new Document(id); // TODO: Initialize to an appropriate value
|
||||
// User u = null; // TODO: Initialize to an appropriate value
|
||||
// bool expected = false; // TODO: Initialize to an appropriate value
|
||||
// bool actual;
|
||||
// actual = target.PublishWithResult(u);
|
||||
// Assert.AreEqual(expected, actual);
|
||||
// Assert.Inconclusive("Verify the correctness of this test method.");
|
||||
//}
|
||||
|
||||
|
||||
///// <summary>
|
||||
/////A test for PublishWithChildrenWithResult
|
||||
@@ -745,15 +780,20 @@ namespace umbraco.Test
|
||||
}
|
||||
|
||||
var id = d.Id;
|
||||
//now recycle it
|
||||
d.delete();
|
||||
|
||||
Assert.IsTrue(d.IsTrashed);
|
||||
//check if it is already trashed
|
||||
var alreadyTrashed = d.IsTrashed;
|
||||
|
||||
Document recycled = new Document(id);
|
||||
//now delete it
|
||||
recycled.delete();
|
||||
if (!alreadyTrashed)
|
||||
{
|
||||
//now recycle it
|
||||
d.delete();
|
||||
|
||||
Assert.IsTrue(d.IsTrashed);
|
||||
}
|
||||
|
||||
//now permanently delete
|
||||
d.delete(true);
|
||||
Assert.IsFalse(Document.IsNode(id));
|
||||
|
||||
//check with sql that it is gone
|
||||
@@ -814,6 +854,32 @@ namespace umbraco.Test
|
||||
return ids[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A helper method to get the parent node.
|
||||
/// The reason we need this is because the API currently throws an exception if we access the Parent property
|
||||
/// of a node and the node is on level 1. This also causes issues if the node is in level 1 in the recycle bin.
|
||||
/// </summary>
|
||||
/// <param name="d"></param>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<IconI> GetChildNodesOfParent(Document d)
|
||||
{
|
||||
if (d.ParentId == (int)RecycleBin.RecycleBinType.Content)
|
||||
{
|
||||
return new RecycleBin(RecycleBin.RecycleBinType.Content).Children.ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (d.Level == 1)
|
||||
{
|
||||
return Document.GetRootDocuments();
|
||||
}
|
||||
else
|
||||
{
|
||||
return d.Parent.Children;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DocumentType GetExistingDocType()
|
||||
{
|
||||
DocumentType dct = new DocumentType(GetExistingDocTypeId());
|
||||
|
||||
@@ -22,18 +22,80 @@ namespace umbraco.Test
|
||||
[TestClass()]
|
||||
public class DocumentTypeTest
|
||||
{
|
||||
[TestMethod()]
|
||||
public void DocumentType_DeleteDocTypeWithContennt()
|
||||
{
|
||||
var dt = CreateNewDocType();
|
||||
var doc = Document.MakeNew("TEST" + Guid.NewGuid().ToString("N"), dt, m_User, -1);
|
||||
Assert.IsInstanceOfType(doc, typeof(Document));
|
||||
Assert.IsTrue(doc.Id > 0);
|
||||
|
||||
DeleteDocType(dt);
|
||||
|
||||
Assert.IsFalse(Document.IsNode(doc.Id));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will create 3 document types, and create nodes in the following structure:
|
||||
/// - root
|
||||
/// -- node1 (of doc type #1)
|
||||
/// --- node 2 (of doc type #2)
|
||||
/// ---- node 3 (of doc type #1)
|
||||
/// ----- node 4 (of doc type #3)
|
||||
///
|
||||
/// Then we'll delete doc type #1. The result should be that node1 and node3 are completely deleted from the database and node2 and node4 are
|
||||
/// moved to the recycle bin.
|
||||
/// </summary>
|
||||
[TestMethod()]
|
||||
public void DocumentType_DeleteDocTypeWithContentAndChildrenOfDifferentDocTypes()
|
||||
{
|
||||
//System.Diagnostics.Debugger.Break();
|
||||
|
||||
//create the doc types
|
||||
var dt1 = CreateNewDocType();
|
||||
var dt2 = CreateNewDocType();
|
||||
var dt3 = CreateNewDocType();
|
||||
|
||||
//create the heirarchy
|
||||
dt1.AllowedChildContentTypeIDs = new int[] { dt2.Id, dt3.Id };
|
||||
dt1.Save();
|
||||
dt2.AllowedChildContentTypeIDs = new int[] { dt1.Id };
|
||||
dt2.Save();
|
||||
|
||||
//create the content tree
|
||||
var node1 = Document.MakeNew("TEST" + Guid.NewGuid().ToString("N"), dt1, m_User, -1);
|
||||
var node2 = Document.MakeNew("TEST" + Guid.NewGuid().ToString("N"), dt2, m_User, node1.Id);
|
||||
var node3 = Document.MakeNew("TEST" + Guid.NewGuid().ToString("N"), dt1, m_User, node2.Id);
|
||||
var node4 = Document.MakeNew("TEST" + Guid.NewGuid().ToString("N"), dt3, m_User, node3.Id);
|
||||
|
||||
//do the deletion of doc type #1
|
||||
DeleteDocType(dt1);
|
||||
|
||||
//do our checks
|
||||
Assert.IsFalse(Document.IsNode(node1.Id), "node1 is not deleted"); //this was of doc type 1, should be gone
|
||||
Assert.IsFalse(Document.IsNode(node3.Id), "node3 is not deleted"); //this was of doc type 1, should be gone
|
||||
|
||||
Assert.IsTrue(Document.IsNode(node2.Id), "node2 is deleted");
|
||||
Assert.IsTrue(Document.IsNode(node4.Id), "node4 is deleted");
|
||||
|
||||
node2 = new Document(node2.Id);//need to re-query the node
|
||||
Assert.IsTrue(node2.IsTrashed, "node2 is not in the trash");
|
||||
node4 = new Document(node4.Id); //need to re-query the node
|
||||
Assert.IsTrue(node4.IsTrashed, "node 4 is not in the trash");
|
||||
|
||||
//remove the old data
|
||||
DeleteDocType(dt2);
|
||||
DeleteDocType(dt3);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///A test for creating a new document type
|
||||
///</summary>
|
||||
[TestMethod()]
|
||||
public void DocumentType_MakeNewTest()
|
||||
{
|
||||
var dt = DocumentType.MakeNew(m_User, "TEST" + Guid.NewGuid().ToString("N"));
|
||||
Assert.IsTrue(dt.Id > 0);
|
||||
Assert.AreEqual(DateTime.Now.Date, dt.CreateDateTime.Date);
|
||||
|
||||
DeleteDocType(dt);
|
||||
{
|
||||
Assert.IsInstanceOfType(m_NewDocType, typeof(DocumentType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -43,18 +105,14 @@ namespace umbraco.Test
|
||||
public void DocumentType_AddPropertiesToTabThenDeleteItTest()
|
||||
{
|
||||
//System.Diagnostics.Debugger.Break();
|
||||
|
||||
var dt = DocumentType.MakeNew(m_User, "TEST" + Guid.NewGuid().ToString("N"));
|
||||
Assert.IsTrue(dt.Id > 0);
|
||||
Assert.AreEqual(DateTime.Now.Date, dt.CreateDateTime.Date);
|
||||
|
||||
|
||||
//allow itself to be created under itself
|
||||
dt.AllowedChildContentTypeIDs = new int[] { dt.Id };
|
||||
m_NewDocType.AllowedChildContentTypeIDs = new int[] { m_NewDocType.Id };
|
||||
//create a tab
|
||||
dt.AddVirtualTab("TEST");
|
||||
m_NewDocType.AddVirtualTab("TEST");
|
||||
|
||||
//test the tab
|
||||
var tabs = dt.getVirtualTabs.ToList();
|
||||
var tabs = m_NewDocType.getVirtualTabs.ToList();
|
||||
Assert.AreEqual(1, tabs.Count);
|
||||
|
||||
//create a property
|
||||
@@ -63,22 +121,20 @@ namespace umbraco.Test
|
||||
foreach (var dataType in allDataTypes)
|
||||
{
|
||||
//add a property type of the first type found in the list
|
||||
dt.AddPropertyType(dataType, "testProperty" + (++i).ToString(), "Test Property" + i.ToString());
|
||||
m_NewDocType.AddPropertyType(dataType, "testProperty" + (++i).ToString(), "Test Property" + i.ToString());
|
||||
//test the prop
|
||||
var prop = dt.getPropertyType("testProperty" + i.ToString());
|
||||
var prop = m_NewDocType.getPropertyType("testProperty" + i.ToString());
|
||||
Assert.IsTrue(prop.Id > 0);
|
||||
Assert.AreEqual("Test Property" + i.ToString(), prop.Name);
|
||||
//put the properties to the tab
|
||||
dt.SetTabOnPropertyType(prop, tabs[0].Id);
|
||||
m_NewDocType.SetTabOnPropertyType(prop, tabs[0].Id);
|
||||
//re-get the property since data is cached in the object
|
||||
prop = dt.getPropertyType("testProperty" + i.ToString());
|
||||
prop = m_NewDocType.getPropertyType("testProperty" + i.ToString());
|
||||
Assert.AreEqual<int>(tabs[0].Id, prop.TabId);
|
||||
}
|
||||
|
||||
//now we need to delete the tab
|
||||
dt.DeleteVirtualTab(tabs[0].Id);
|
||||
|
||||
dt.delete();
|
||||
m_NewDocType.DeleteVirtualTab(tabs[0].Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -688,6 +744,23 @@ namespace umbraco.Test
|
||||
|
||||
private User m_User = new User(0);
|
||||
|
||||
/// <summary>
|
||||
/// before each test starts, this object is created so it can be used for testing.
|
||||
/// </summary>
|
||||
private DocumentType m_NewDocType;
|
||||
|
||||
/// <summary>
|
||||
/// Create a brand new document type
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private DocumentType CreateNewDocType()
|
||||
{
|
||||
var dt = DocumentType.MakeNew(m_User, "TEST" + Guid.NewGuid().ToString("N"));
|
||||
Assert.IsTrue(dt.Id > 0);
|
||||
Assert.AreEqual(DateTime.Now.Date, dt.CreateDateTime.Date);
|
||||
return dt;
|
||||
}
|
||||
|
||||
private void DeleteDocType(DocumentType dt)
|
||||
{
|
||||
var id = dt.Id;
|
||||
@@ -739,18 +812,25 @@ namespace umbraco.Test
|
||||
//{
|
||||
//}
|
||||
//
|
||||
//Use TestInitialize to run code before running each test
|
||||
//[TestInitialize()]
|
||||
//public void MyTestInitialize()
|
||||
//{
|
||||
//}
|
||||
//
|
||||
//Use TestCleanup to run code after each test has run
|
||||
//[TestCleanup()]
|
||||
//public void MyTestCleanup()
|
||||
//{
|
||||
//}
|
||||
//
|
||||
|
||||
/// <summary>
|
||||
/// Create a new document type for use in tests
|
||||
/// </summary>
|
||||
[TestInitialize()]
|
||||
public void MyTestInitialize()
|
||||
{
|
||||
m_NewDocType = CreateNewDocType();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the created document type
|
||||
/// </summary>
|
||||
[TestCleanup()]
|
||||
public void MyTestCleanup()
|
||||
{
|
||||
DeleteDocType(m_NewDocType);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ using System.Text.RegularExpressions;
|
||||
using System.ComponentModel;
|
||||
using umbraco.IO;
|
||||
using umbraco.cms.businesslogic.media;
|
||||
using System.Collections;
|
||||
|
||||
namespace umbraco.cms.businesslogic
|
||||
{
|
||||
@@ -51,6 +52,7 @@ namespace umbraco.cms.businesslogic
|
||||
#endregion
|
||||
|
||||
#region Private static
|
||||
|
||||
private static readonly string m_DefaultIconCssFile = IOHelper.MapPath(SystemDirectories.Umbraco_client + "/Tree/treeIcons.css");
|
||||
private static List<string> m_DefaultIconClasses = new List<string>();
|
||||
private static void initializeIconClasses()
|
||||
@@ -74,6 +76,12 @@ namespace umbraco.cms.businesslogic
|
||||
m_DefaultIconClasses.Add(cssClass);
|
||||
}
|
||||
}
|
||||
private const string m_SQLSingle = "SELECT id, createDate, trashed, parentId, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text FROM umbracoNode WHERE id = @id";
|
||||
private const string m_SQLDescendants = @"
|
||||
SELECT id, createDate, trashed, parentId, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text
|
||||
FROM umbracoNode
|
||||
WHERE path LIKE '%,{0},%'";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public static
|
||||
@@ -408,56 +416,35 @@ order by level,sortOrder";
|
||||
return base.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves the CMSNode from the current position in the hierarchy to the target
|
||||
/// </summary>
|
||||
/// <param name="NewParentId">Target CMSNode id</param>
|
||||
public void Move(int newParentId)
|
||||
private void Move(CMSNode parent)
|
||||
{
|
||||
//first we need to establish if the node already exists under the parent node
|
||||
var isSameParent = (Path.Contains("," + newParentId + ","));
|
||||
|
||||
MoveEventArgs e = new MoveEventArgs();
|
||||
FireBeforeMove(e);
|
||||
|
||||
if (!e.Cancel)
|
||||
{
|
||||
CMSNode n = new CMSNode(newParentId);
|
||||
//first we need to establish if the node already exists under the parent node
|
||||
var isSameParent = (Path.Contains("," + parent.Id + ","));
|
||||
|
||||
//if it's the same parent, we can save some SQL calls since we know these wont change.
|
||||
//level and path might change even if it's the same parent because the parent could be moving somewhere.
|
||||
if (!isSameParent)
|
||||
{
|
||||
int maxSortOrder = SqlHelper.ExecuteScalar<int>(
|
||||
"select coalesce(max(sortOrder),0) from umbracoNode where parentid = @parentId",
|
||||
SqlHelper.CreateParameter("@parentId", newParentId));
|
||||
int maxSortOrder = SqlHelper.ExecuteScalar<int>("select coalesce(max(sortOrder),0) from umbracoNode where parentid = @parentId",
|
||||
SqlHelper.CreateParameter("@parentId", parent.Id));
|
||||
|
||||
this.Parent = n;
|
||||
this.Parent = parent;
|
||||
this.sortOrder = maxSortOrder + 1;
|
||||
}
|
||||
|
||||
this.Level = n.Level + 1;
|
||||
this.Path = n.Path + "," + this.Id.ToString();
|
||||
}
|
||||
|
||||
this.Level = parent.Level + 1;
|
||||
this.Path = parent.Path + "," + this.Id.ToString();
|
||||
|
||||
//this code block should not be here but since the class structure is very poor and doesn't use
|
||||
//overrides (instead using shadows/new) for the Children property, when iterating over the children
|
||||
//and calling Move(), the super classes overridden OnMove or Move methods never get fired, so
|
||||
//we now need to hard code this here :(
|
||||
|
||||
//make sure the node type is a document/media, if it is a recycle bin then this will not be equal
|
||||
if (n.nodeObjectType == Document._objectType)
|
||||
{
|
||||
//regenerate the xml for the parent node
|
||||
var d = new Document(n.Id);
|
||||
d.XmlGenerate(new XmlDocument());
|
||||
}
|
||||
else if (n.nodeObjectType == Media._objectType)
|
||||
{
|
||||
//regenerate the xml for the parent node
|
||||
var m = new Media(n.Id);
|
||||
m.XmlGenerate(new XmlDocument());
|
||||
}
|
||||
|
||||
if (Path.Contains("," + ((int)RecycleBin.RecycleBinType.Content).ToString() + ",")
|
||||
|| Path.Contains("," + ((int)RecycleBin.RecycleBinType.Media).ToString() + ","))
|
||||
{
|
||||
@@ -469,16 +456,40 @@ order by level,sortOrder";
|
||||
if (IsTrashed) IsTrashed = false; //don't update if it's not necessary
|
||||
}
|
||||
|
||||
//make sure the node type is a document/media, if it is a recycle bin then this will not be equal
|
||||
if (!IsTrashed && parent.nodeObjectType == Document._objectType)
|
||||
{
|
||||
//regenerate the xml for the parent node
|
||||
var d = new Document(parent.Id);
|
||||
d.XmlGenerate(new XmlDocument());
|
||||
}
|
||||
else if (!IsTrashed && parent.nodeObjectType == Media._objectType)
|
||||
{
|
||||
//regenerate the xml for the parent node
|
||||
var m = new Media(parent.Id);
|
||||
m.XmlGenerate(new XmlDocument());
|
||||
}
|
||||
|
||||
var children = this.Children;
|
||||
foreach (CMSNode c in children)
|
||||
{
|
||||
c.Move(this.Id);
|
||||
c.Move(this);
|
||||
}
|
||||
|
||||
FireAfterMove(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves the CMSNode from the current position in the hierarchy to the target
|
||||
/// </summary>
|
||||
/// <param name="NewParentId">Target CMSNode id</param>
|
||||
public void Move(int newParentId)
|
||||
{
|
||||
CMSNode parent = new CMSNode(newParentId);
|
||||
Move(parent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes this instance.
|
||||
/// </summary>
|
||||
@@ -500,7 +511,6 @@ order by level,sortOrder";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Does the current CMSNode have any child nodes.
|
||||
/// </summary>
|
||||
@@ -524,7 +534,31 @@ order by level,sortOrder";
|
||||
_hasChildrenInitialized = true;
|
||||
_hasChildren = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all descendant nodes from this node.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This doesn't return a strongly typed IEnumerable object so that we can override in in super clases
|
||||
/// and since this class isn't a generic (thought it should be) this is not strongly typed.
|
||||
/// </remarks>
|
||||
public virtual IEnumerable GetDescendants()
|
||||
{
|
||||
var descendants = new List<CMSNode>();
|
||||
using (IRecordsReader dr = SqlHelper.ExecuteReader(string.Format(m_SQLDescendants, Id)))
|
||||
{
|
||||
while (dr.Read())
|
||||
{
|
||||
var node = new CMSNode(dr.GetInt("id"), true);
|
||||
node.PopulateCMSNodeFromReader(dr);
|
||||
descendants.Add(node);
|
||||
}
|
||||
}
|
||||
return descendants;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public properties
|
||||
@@ -602,6 +636,13 @@ order by level,sortOrder";
|
||||
get { return _id; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the parent id of the node
|
||||
/// </summary>
|
||||
public int ParentId
|
||||
{
|
||||
get { return _parentid; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given the hierarchical tree structure a CMSNode has only one parent but can have many children
|
||||
@@ -690,7 +731,8 @@ order by level,sortOrder";
|
||||
{
|
||||
System.Collections.ArrayList tmp = new System.Collections.ArrayList();
|
||||
using (IRecordsReader dr = SqlHelper.ExecuteReader("SELECT id, createDate, trashed, parentId, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text FROM umbracoNode WHERE ParentID = @ParentID AND nodeObjectType = @type order by sortOrder",
|
||||
SqlHelper.CreateParameter("@type", this.nodeObjectType), SqlHelper.CreateParameter("ParentID", this.Id)))
|
||||
SqlHelper.CreateParameter("@type", this.nodeObjectType),
|
||||
SqlHelper.CreateParameter("ParentID", this.Id)))
|
||||
{
|
||||
while (dr.Read())
|
||||
{
|
||||
@@ -816,9 +858,8 @@ order by level,sortOrder";
|
||||
/// </summary>
|
||||
protected virtual void setupNode()
|
||||
{
|
||||
using (IRecordsReader dr = SqlHelper.ExecuteReader(
|
||||
"SELECT createDate, trashed, parentId, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text FROM umbracoNode WHERE id = " + this.Id
|
||||
))
|
||||
using (IRecordsReader dr = SqlHelper.ExecuteReader(m_SQLSingle,
|
||||
SqlHelper.CreateParameter("@id",this.Id)))
|
||||
{
|
||||
if (dr.Read())
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Linq;
|
||||
using umbraco.DataLayer;
|
||||
using umbraco.cms.businesslogic.web;
|
||||
using umbraco.cms.businesslogic.media;
|
||||
using System.Threading;
|
||||
|
||||
namespace umbraco.cms.businesslogic
|
||||
{
|
||||
@@ -134,12 +135,18 @@ namespace umbraco.cms.businesslogic
|
||||
{
|
||||
lock (m_Locker)
|
||||
{
|
||||
//first, move all nodes underneath the recycle bin directly under the recycle bin node (flatten heirarchy)
|
||||
//then delete them all.
|
||||
|
||||
SqlHelper.ExecuteNonQuery("UPDATE umbracoNode SET parentID=@parentID, level=1 WHERE path LIKE '%," + ((int)m_BinType).ToString() + ",%'",
|
||||
SqlHelper.CreateParameter("@parentID", (int)m_BinType));
|
||||
|
||||
foreach (var c in Children.ToList())
|
||||
{
|
||||
switch (m_BinType)
|
||||
{
|
||||
case RecycleBinType.Content:
|
||||
new Document(c.Id).delete();
|
||||
new Document(c.Id).delete(true);
|
||||
itemDeletedCallback(RecycleBin.Count(m_BinType));
|
||||
break;
|
||||
case RecycleBinType.Media:
|
||||
|
||||
@@ -146,41 +146,38 @@ namespace umbraco.cms.businesslogic.web
|
||||
umbracoNode.createDate, umbracoNode.trashed, umbracoNode.parentId, umbracoNode.nodeObjectType, umbracoNode.nodeUser, umbracoNode.level, umbracoNode.path, umbracoNode.sortOrder, umbracoNode.uniqueId, umbracoNode.text
|
||||
from
|
||||
umbracoNode
|
||||
inner join
|
||||
cmsContentVersion on cmsContentVersion.contentID = umbracoNode.id
|
||||
inner join
|
||||
cmsDocument on cmsDocument.versionId = cmsContentVersion.versionId
|
||||
inner join
|
||||
cmsContent on cmsDocument.nodeId = cmsContent.NodeId
|
||||
inner join
|
||||
cmsContentType on cmsContentType.nodeId = cmsContent.ContentType
|
||||
inner join
|
||||
umbracoNode contentTypeNode on contentTypeNode.id = cmsContentType.nodeId
|
||||
left join cmsDocumentType on
|
||||
cmsDocumentType.contentTypeNodeId = cmsContent.contentType and cmsDocumentType.IsDefault = 1
|
||||
where
|
||||
{0}
|
||||
order by
|
||||
{1}
|
||||
";
|
||||
private const string m_SQLOptimizedChildren = @"
|
||||
select count(children.id) as children, umbracoNode.id, umbracoNode.uniqueId, umbracoNode.level, umbracoNode.parentId, cmsDocument.documentUser,
|
||||
coalesce(cmsDocument.templateId, cmsDocumentType.templateNodeId) as templateId, umbracoNode.path, umbracoNode.sortOrder, coalesce(publishCheck.published,0) as published, umbracoNode.createDate, cmsDocument.text, cmsDocument.updateDate, cmsContentVersion.versionDate, cmsContentType.icon, cmsContentType.alias, cmsContentType.thumbnail, cmsContentType.description, cmsContentType.masterContentType, cmsContentType.nodeId as contentTypeId
|
||||
from umbracoNode
|
||||
left join umbracoNode children on children.parentId = umbracoNode.id
|
||||
inner join cmsContent on cmsContent.nodeId = umbracoNode.id
|
||||
inner join cmsContentType on cmsContentType.nodeId = cmsContent.contentType
|
||||
inner join (select contentId, max(versionDate) AS versionDate from cmsContentVersion
|
||||
inner join umbracoNode on umbracoNode.id = cmsContentVersion.contentId and umbracoNode.parentId = @parentId
|
||||
group by contentId) AS temp
|
||||
on temp.contentId = cmsContent.nodeId
|
||||
inner join cmsContentVersion on cmsContentVersion.contentId = temp.contentId and cmsContentVersion.versionDate = temp.versionDate
|
||||
inner join cmsDocument on cmsDocument.versionId = cmsContentversion.versionId
|
||||
left join cmsDocument publishCheck on publishCheck.nodeId = cmsContent.nodeID and publishCheck.published = 1
|
||||
left join cmsDocumentType on
|
||||
cmsDocumentType.contentTypeNodeId = cmsContent.contentType and cmsDocumentType.IsDefault = 1
|
||||
inner join cmsContentVersion on cmsContentVersion.contentID = umbracoNode.id
|
||||
inner join cmsDocument on cmsDocument.versionId = cmsContentVersion.versionId
|
||||
inner join cmsContent on cmsDocument.nodeId = cmsContent.NodeId
|
||||
inner join cmsContentType on cmsContentType.nodeId = cmsContent.ContentType
|
||||
inner join umbracoNode contentTypeNode on contentTypeNode.id = cmsContentType.nodeId
|
||||
left join cmsDocumentType on cmsDocumentType.contentTypeNodeId = cmsContent.contentType and cmsDocumentType.IsDefault = 1
|
||||
where {0}
|
||||
group by umbracoNode.id, umbracoNode.uniqueId, umbracoNode.level, umbracoNode.parentId, cmsDocument.documentUser, cmsDocument.templateId, cmsDocumentType.templateNodeId, umbracoNode.path, umbracoNode.sortOrder, coalesce(publishCheck.published,0), umbracoNode.createDate, cmsDocument.text, cmsDocument.updateDate, cmsContentVersion.versionDate, cmsContentType.icon, cmsContentType.alias, cmsContentType.thumbnail, cmsContentType.description, cmsContentType.masterContentType, cmsContentType.nodeId
|
||||
order by {1}
|
||||
";
|
||||
private const string m_SQLOptimizedMany = @"
|
||||
select count(children.id) as children, umbracoNode.id, umbracoNode.uniqueId, umbracoNode.level, umbracoNode.parentId,
|
||||
cmsDocument.documentUser, coalesce(cmsDocument.templateId, cmsDocumentType.templateNodeId) as templateId,
|
||||
umbracoNode.path, umbracoNode.sortOrder, coalesce(publishCheck.published,0) as published, umbracoNode.createDate,
|
||||
cmsDocument.text, cmsDocument.updateDate, cmsContentVersion.versionDate, cmsContentType.icon, cmsContentType.alias,
|
||||
cmsContentType.thumbnail, cmsContentType.description, cmsContentType.masterContentType, cmsContentType.nodeId as contentTypeId
|
||||
from umbracoNode
|
||||
left join umbracoNode children on children.parentId = umbracoNode.id
|
||||
inner join cmsContent on cmsContent.nodeId = umbracoNode.id
|
||||
inner join cmsContentType on cmsContentType.nodeId = cmsContent.contentType
|
||||
inner join cmsContentVersion on cmsContentVersion.contentId = umbracoNode.id
|
||||
inner join (select contentId, max(versionDate) as versionDate from cmsContentVersion group by contentId) temp
|
||||
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
|
||||
left join cmsDocumentType on cmsDocumentType.contentTypeNodeId = cmsContent.contentType and cmsDocumentType.IsDefault = 1
|
||||
where {0}
|
||||
group by
|
||||
umbracoNode.id, umbracoNode.uniqueId, umbracoNode.level, umbracoNode.parentId, cmsDocument.documentUser,
|
||||
cmsDocument.templateId, cmsDocumentType.templateNodeId, umbracoNode.path, umbracoNode.sortOrder,
|
||||
coalesce(publishCheck.published,0), umbracoNode.createDate, cmsDocument.text,
|
||||
cmsContentType.icon, cmsContentType.alias, cmsContentType.thumbnail, cmsContentType.description,
|
||||
cmsContentType.masterContentType, cmsContentType.nodeId, cmsDocument.updateDate, cmsContentVersion.versionDate
|
||||
order by {1}
|
||||
";
|
||||
|
||||
@@ -396,11 +393,13 @@ namespace umbraco.cms.businesslogic.web
|
||||
//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("insert into cmsDocument (newest, nodeId, published, documentUser, versionId, Text, TemplateId) values (1,@id, 0, @userId, @versionId, @text, @template)",
|
||||
SqlHelper.CreateParameter("@id", Id),
|
||||
SqlHelper.CreateParameter("@template", _template > 0 ? (object)_template : (object)DBNull.Value), //pass null in if the template doesn't have a valid id
|
||||
SqlHelper.CreateParameter("@userId", u.Id),
|
||||
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));
|
||||
@@ -648,6 +647,38 @@ namespace umbraco.cms.businesslogic.web
|
||||
_published = InitPublished;
|
||||
}
|
||||
|
||||
protected void PopulateDocumentFromReader(IRecordsReader dr)
|
||||
{
|
||||
bool _hc = false;
|
||||
|
||||
if (dr.GetInt("children") > 0)
|
||||
_hc = true;
|
||||
|
||||
int? masterContentType = null;
|
||||
|
||||
if (!dr.IsNull("masterContentType"))
|
||||
masterContentType = dr.GetInt("masterContentType");
|
||||
|
||||
SetupDocumentForTree(dr.GetGuid("uniqueId")
|
||||
, dr.GetShort("level")
|
||||
, dr.GetInt("parentId")
|
||||
, dr.GetInt("documentUser")
|
||||
, (dr.GetInt("published") == 1)
|
||||
, dr.GetString("path")
|
||||
, dr.GetString("text")
|
||||
, dr.GetDateTime("createDate")
|
||||
, dr.GetDateTime("updateDate")
|
||||
, dr.GetDateTime("versionDate")
|
||||
, dr.GetString("icon")
|
||||
, _hc
|
||||
, dr.GetString("alias")
|
||||
, dr.GetString("thumbnail")
|
||||
, dr.GetString("description")
|
||||
, masterContentType
|
||||
, dr.GetInt("contentTypeId")
|
||||
, dr.GetInt("templateId"));
|
||||
}
|
||||
|
||||
public override string Text
|
||||
{
|
||||
get
|
||||
@@ -836,8 +867,12 @@ namespace umbraco.cms.businesslogic.web
|
||||
// Make the new document
|
||||
Document NewDoc = MakeNew(Text, new DocumentType(ContentType.Id), u, CopyTo);
|
||||
|
||||
// update template
|
||||
NewDoc.Template = Template;
|
||||
// update template if a template is set
|
||||
if (this.Template > 0)
|
||||
NewDoc.Template = Template;
|
||||
|
||||
//update the trashed property as it could be copied inside the recycle bin
|
||||
NewDoc.IsTrashed = this.IsTrashed;
|
||||
|
||||
// Copy the properties of the current document
|
||||
var props = getProperties;
|
||||
@@ -955,12 +990,6 @@ namespace umbraco.cms.businesslogic.web
|
||||
{
|
||||
get
|
||||
{
|
||||
//SD: Removed old, non-optimized method!
|
||||
//IconI[] tmp = base.Children;
|
||||
//Document[] retval = new Document[tmp.Length];
|
||||
//for (int i = 0; i < tmp.Length; i++) retval[i] = new Document(tmp[i].Id);
|
||||
//return retval;
|
||||
|
||||
//cache the documents children so that this db call doesn't have to occur again
|
||||
if (this._children == null)
|
||||
this._children = Document.GetChildrenForTree(this.Id);
|
||||
@@ -982,32 +1011,40 @@ namespace umbraco.cms.businesslogic.web
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the current document (and all children recursive)
|
||||
/// Puts the current document in the trash
|
||||
/// </summary>
|
||||
public override void delete()
|
||||
{
|
||||
// Check for recyle bin
|
||||
if (!Path.Contains("," + ((int)RecycleBin.RecycleBinType.Content).ToString() + ","))
|
||||
MoveToTrash();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// With either move the document to the trash or permanently remove it from the database.
|
||||
/// </summary>
|
||||
/// <param name="deletePermanently">flag to set whether or not to completely remove it from the database or just send to trash</param>
|
||||
public void delete(bool deletePermanently)
|
||||
{
|
||||
if (!deletePermanently)
|
||||
{
|
||||
MoveToTrash();
|
||||
}
|
||||
else
|
||||
{
|
||||
DeletePermanently(false);
|
||||
DeletePermanently();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used internally to permanently delete the data from the database
|
||||
/// </summary>
|
||||
/// <param name="onlyCurrentDocType">
|
||||
/// if onlyCurrentDocType is set, this means that we shouldn't delete any children that are not
|
||||
/// the current document type and instead just move them to the recycle bin. This is effective if
|
||||
/// <param name="onlyThisDocType">
|
||||
/// if onlyThisDocType is set, this means that we shouldn't delete any children that are not
|
||||
/// the document type specified and instead just move them to the recycle bin. This is effective if
|
||||
/// we're deleting an entire document type but don't want to delete other data that isn't this document type
|
||||
/// but the ndoe exists as a child of the document type that is being deleted.
|
||||
/// </param>
|
||||
/// <returns>returns true if deletion isn't cancelled</returns>
|
||||
private bool DeletePermanently(bool onlyCurrentDocType)
|
||||
private bool DeletePermanently()
|
||||
{
|
||||
DeleteEventArgs e = new DeleteEventArgs();
|
||||
|
||||
@@ -1015,20 +1052,9 @@ namespace umbraco.cms.businesslogic.web
|
||||
|
||||
if (!e.Cancel)
|
||||
{
|
||||
|
||||
var c = Children;
|
||||
foreach (Document d in c)
|
||||
foreach (Document d in Children.ToList())
|
||||
{
|
||||
if (onlyCurrentDocType && (d.ContentType.Id != this.ContentType.Id))
|
||||
{
|
||||
//if we're only supposed to be deleting an exact document type, then just move the document
|
||||
//to the trash
|
||||
d.MoveToTrash();
|
||||
}
|
||||
else
|
||||
{
|
||||
d.DeletePermanently(onlyCurrentDocType);
|
||||
}
|
||||
d.DeletePermanently();
|
||||
}
|
||||
|
||||
umbraco.BusinessLogic.Actions.Action.RunActionHandlers(this, ActionDelete.Instance);
|
||||
@@ -1085,16 +1111,45 @@ namespace umbraco.cms.businesslogic.web
|
||||
/// <param name="dt">The type of which documents should be deleted</param>
|
||||
public static void DeleteFromType(DocumentType dt)
|
||||
{
|
||||
var objs = getContentOfContentType(dt);
|
||||
foreach (Content c in objs)
|
||||
//get all document for the document type and order by level (top level first)
|
||||
var docs = Document.GetDocumentsOfDocumentType(dt.Id)
|
||||
.OrderByDescending(x => x.Level);
|
||||
|
||||
foreach (Document doc in docs)
|
||||
{
|
||||
// due to recursive structure document might already been deleted..
|
||||
if (IsNode(c.UniqueId))
|
||||
//before we delete this document, we need to make sure we don't end up deleting other documents that
|
||||
//are not of this document type that are children. So we'll move all of it's children to the trash first.
|
||||
foreach (Document c in doc.GetDescendants())
|
||||
{
|
||||
Document d = new Document(c.UniqueId);
|
||||
d.DeletePermanently(true);
|
||||
if (c.ContentType.Id != dt.Id)
|
||||
{
|
||||
c.MoveToTrash();
|
||||
}
|
||||
}
|
||||
|
||||
doc.DeletePermanently();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all decendants of the current document
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override IEnumerable GetDescendants()
|
||||
{
|
||||
var tmp = new List<Document>();
|
||||
using (IRecordsReader dr = SqlHelper.ExecuteReader(
|
||||
string.Format(m_SQLOptimizedMany, "umbracoNode.path LIKE '%," + this.Id + ",%'", "umbracoNode.level")))
|
||||
{
|
||||
while (dr.Read())
|
||||
{
|
||||
Document d = new Document(dr.GetInt("id"), true);
|
||||
d.PopulateDocumentFromReader(dr);
|
||||
tmp.Add(d);
|
||||
}
|
||||
}
|
||||
|
||||
return tmp.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1317,6 +1372,25 @@ namespace umbraco.cms.businesslogic.web
|
||||
return temp;
|
||||
}
|
||||
|
||||
public static IEnumerable<Document> GetDocumentsOfDocumentType(int docTypeId)
|
||||
{
|
||||
var tmp = new List<Document>();
|
||||
using (IRecordsReader dr =
|
||||
SqlHelper.ExecuteReader(
|
||||
string.Format(m_SQLOptimizedMany, "cmsContent.contentType = @contentTypeId", "umbracoNode.sortOrder"),
|
||||
SqlHelper.CreateParameter("@contentTypeId", docTypeId)))
|
||||
{
|
||||
while (dr.Read())
|
||||
{
|
||||
Document d = new Document(dr.GetInt("id"), true);
|
||||
d.PopulateDocumentFromReader(dr);
|
||||
tmp.Add(d);
|
||||
}
|
||||
}
|
||||
|
||||
return tmp.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performance tuned method for use in the tree
|
||||
/// </summary>
|
||||
@@ -1324,49 +1398,21 @@ namespace umbraco.cms.businesslogic.web
|
||||
/// <returns></returns>
|
||||
public static Document[] GetChildrenForTree(int NodeId)
|
||||
{
|
||||
ArrayList tmp = new ArrayList();
|
||||
var tmp = new List<Document>();
|
||||
using (IRecordsReader dr =
|
||||
SqlHelper.ExecuteReader(
|
||||
string.Format(m_SQLOptimizedChildren, "umbracoNode.parentID = @parentId", "umbracoNode.sortOrder"),
|
||||
string.Format(m_SQLOptimizedMany, "umbracoNode.parentID = @parentId", "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;
|
||||
int? masterContentType = null;
|
||||
if (!dr.IsNull("masterContentType"))
|
||||
masterContentType = dr.GetInt("masterContentType");
|
||||
d.SetupDocumentForTree(dr.GetGuid("uniqueId")
|
||||
, dr.GetShort("level")
|
||||
, dr.GetInt("parentId")
|
||||
, dr.GetInt("documentUser")
|
||||
, (dr.GetInt("published") == 1)
|
||||
, dr.GetString("path")
|
||||
, dr.GetString("text")
|
||||
, dr.GetDateTime("createDate")
|
||||
, dr.GetDateTime("updateDate")
|
||||
, dr.GetDateTime("versionDate")
|
||||
, dr.GetString("icon")
|
||||
, _hc
|
||||
, dr.GetString("alias")
|
||||
, dr.GetString("thumbnail")
|
||||
, dr.GetString("description")
|
||||
, masterContentType
|
||||
, dr.GetInt("contentTypeId")
|
||||
, dr.GetInt("templateId"));
|
||||
d.PopulateDocumentFromReader(dr);
|
||||
tmp.Add(d);
|
||||
}
|
||||
}
|
||||
|
||||
Document[] retval = new Document[tmp.Count];
|
||||
|
||||
for (int i = 0; i < tmp.Count; i++)
|
||||
retval[i] = (Document)tmp[i];
|
||||
|
||||
return retval;
|
||||
return tmp.ToArray();
|
||||
}
|
||||
|
||||
private void SetupDocumentForTree(Guid uniqueId, int level, int parentId, int user, bool publish, string path,
|
||||
|
||||
@@ -17,6 +17,8 @@ using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Web.UI;
|
||||
using umbraco.IO;
|
||||
using umbraco.cms.businesslogic.web;
|
||||
using umbraco.cms.businesslogic.media;
|
||||
|
||||
|
||||
namespace umbraco.presentation.webservices
|
||||
@@ -32,7 +34,7 @@ namespace umbraco.presentation.webservices
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Overloaded method to accept a string value for the node id. Used for tree's such as python
|
||||
/// method to accept a string value for the node id. Used for tree's such as python
|
||||
/// and xslt since the file names are the node IDs
|
||||
/// </summary>
|
||||
/// <param name="nodeId"></param>
|
||||
@@ -52,6 +54,37 @@ namespace umbraco.presentation.webservices
|
||||
else
|
||||
presentation.create.dialogHandler_temp.Delete(nodeType, 0, nodeId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Permanently deletes a document/media object.
|
||||
/// Used to remove an item from the recycle bin.
|
||||
/// </summary>
|
||||
/// <param name="nodeId"></param>
|
||||
[WebMethod]
|
||||
[ScriptMethod]
|
||||
public void DeleteContentPermanently(string nodeId, string nodeType)
|
||||
{
|
||||
Authorize();
|
||||
|
||||
int intNodeID;
|
||||
if (int.TryParse(nodeId, out intNodeID))
|
||||
{
|
||||
switch (nodeType)
|
||||
{
|
||||
case "media":
|
||||
new Media(intNodeID).delete();
|
||||
break;
|
||||
case "content":
|
||||
new Document(intNodeID).delete(true);
|
||||
break;
|
||||
}
|
||||
new Document(intNodeID).delete(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("The nodeId argument could not be parsed to an integer");
|
||||
}
|
||||
}
|
||||
|
||||
[WebMethod]
|
||||
[ScriptMethod]
|
||||
|
||||
@@ -317,21 +317,41 @@ Umbraco.Application.Actions = function() {
|
||||
actionDelete: function() {
|
||||
/// <summary></summary>
|
||||
|
||||
var actionNode = UmbClientMgr.mainTree().getActionNode();
|
||||
if (UmbClientMgr.mainTree().getActionNode().nodeType == "content" && UmbClientMgr.mainTree().getActionNode().nodeId == '-1')
|
||||
return;
|
||||
|
||||
this._debug("actionDelete");
|
||||
|
||||
|
||||
if (confirm(uiKeys['defaultdialogs_confirmdelete'] + ' "' + UmbClientMgr.mainTree().getActionNode().nodeName + '"?\n\n')) {
|
||||
//raise nodeDeleting event
|
||||
jQuery(window.top).trigger("nodeDeleting", []);
|
||||
var _this = this;
|
||||
umbraco.presentation.webservices.legacyAjaxCalls.Delete(UmbClientMgr.mainTree().getActionNode().nodeId, "", UmbClientMgr.mainTree().getActionNode().nodeType, function() {
|
||||
_this._debug("actionDelete: Raising event");
|
||||
//raise nodeDeleted event
|
||||
jQuery(window.top).trigger("nodeDeleted", []);
|
||||
});
|
||||
|
||||
//check if it's in the recycle bin
|
||||
if (actionNode.jsNode.closest("li[id='-20']").length == 1 || actionNode.jsNode.closest("li[id='-21']").length == 1) {
|
||||
umbraco.presentation.webservices.legacyAjaxCalls.DeleteContentPermanently(
|
||||
UmbClientMgr.mainTree().getActionNode().nodeId,
|
||||
UmbClientMgr.mainTree().getActionNode().nodeType,
|
||||
function() {
|
||||
_this._debug("actionDelete: Raising event");
|
||||
//raise nodeDeleted event
|
||||
jQuery(window.top).trigger("nodeDeleted", []);
|
||||
});
|
||||
}
|
||||
else {
|
||||
umbraco.presentation.webservices.legacyAjaxCalls.Delete(
|
||||
UmbClientMgr.mainTree().getActionNode().nodeId, "",
|
||||
UmbClientMgr.mainTree().getActionNode().nodeType,
|
||||
function() {
|
||||
_this._debug("actionDelete: Raising event");
|
||||
//raise nodeDeleted event
|
||||
jQuery(window.top).trigger("nodeDeleted", []);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
actionDisable: function() {
|
||||
|
||||
Reference in New Issue
Block a user