diff --git a/SHANDEMVAIO.testrunconfig b/SHANDEMVAIO.testrunconfig
new file mode 100644
index 0000000000..48adf6cd4e
--- /dev/null
+++ b/SHANDEMVAIO.testrunconfig
@@ -0,0 +1,10 @@
+
+
+ This is a default test run configuration for a local test run.
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/umbraco.Test/AuthoringTests.txt b/umbraco.Test/AuthoringTests.txt
new file mode 100644
index 0000000000..64bab9481d
--- /dev/null
+++ b/umbraco.Test/AuthoringTests.txt
@@ -0,0 +1,136 @@
+==========================================================================
+ Visual Studio Team System: Overview of Authoring and Running Tests
+==========================================================================
+
+This overview describes the features for authoring and running tests in
+Visual Studio Team System and Visual Studio Team Edition for Software Testers.
+
+Opening Tests
+-------------
+To open a test, open a test project or a test metadata file (a file with
+extension .vsmdi) that contains the definition of the test. You can find
+test projects and metadata files in Solution Explorer.
+
+Viewing Tests
+-------------
+To see which tests are available to you, open the Test View window. Or,
+if you have installed Team Edition for Software Testers, you can also open
+the Test List Editor window to view tests.
+
+To open the Test View window, click the Test menu, point to Windows, and
+then click Test View. To open the Test List Editor window (if you have
+installed Team Edition for Software Testers), click Test, point to Windows,
+and then click Test List Editor.
+
+Running Tests
+-------------
+You can run tests from the Test View window and the Test List Editor window.
+See Viewing Tests to learn how to open these windows. To run one or more
+tests displayed in the Test View window, first select the tests in that
+window; to select multiple tests, hold either the Shift or CTRL key while
+clicking tests. Then click the Run Tests button in the Test View window
+toolbar.
+
+If you have installed Visual Studio Team Edition for Software Testers, you can
+also use the Test List Editor window to run tests. To run tests in Test List Editor,
+select the check box next to each test that you want to run. Then click the
+Run Tests button in the Test List Editor window toolbar.
+
+Viewing Test Results
+--------------------
+When you run a test or a series of tests, the results of the test run will be
+shown in the Test Results window. Each individual test in the run is shown on
+a separate line so that you can see its status. The window contains an
+embedded status bar in the top half of the window that provides you with
+summary details of the complete test run.
+
+To see more detailed results for a particular test result, double-click it in
+the Test Results window. This opens a window that provides more information
+about the particular test result, such as any specific error messages returned
+by the test.
+
+Changing the way that tests are run
+-----------------------------------
+Each time you run one or more tests, a collection of settings is used to
+determine how those tests are run. These settings are contained in a “test
+run configuration” file.
+
+Here is a partial list of the changes you can make with a test run
+configuration file:
+
+ - Change the naming scheme for each test run.
+ - Change the test controller that the tests are run on so that you can run
+ tests remotely.
+ - Gather code coverage data for the code being tested so that you can see
+ which lines of code are covered by your tests.
+ - Enable and disable test deployment.
+ - Specify additional files to deploy before tests are run.
+ - Select a different host, ASP.NET, for running ASP.NET unit tests.
+ - Select a different host, the smart device test host, for running smart device unit tests.
+ - Set various properties for the test agents that run your tests.
+ - Run custom scripts at the start and end of each test run so that you can
+ set up the test environment exactly as required each time tests are run.
+ - Set time limits for tests and test runs.
+ - Set the browser mix and the number of times to repeat Web tests in the
+ test run.
+
+By default, a test run configuration file is created whenever you create a
+new test project. You make changes to this file by double-clicking it in
+Solution Explorer and then changing its settings. (Test run configuration
+files have the extension .testrunconfig.)
+
+A solution can contain multiple test run configuration files. Only one of
+those files, known as the “Active” test run configuration file, is used to
+determine the settings that are currently used for test runs. You select
+the active test run configuration by clicking Select Active Test Run
+Configuration on the Test menu.
+
+-------------------------------------------------------------------------------
+
+Test Types
+----------
+Using Visual Studio Team Edition for Software Testers, you can create a number
+of different test types:
+
+Unit test: Use a unit test to create a programmatic test in C++, Visual C# or
+Visual Basic that exercises source code. A unit test calls the methods of a
+class, passing suitable parameters, and verifies that the returned value is
+what you expect.
+There are three specialized variants of unit tests:
+ - Data-driven unit tests are created when you configure a unit test to be
+ called repeatedly for each row of a data source. The data from each row
+ is used by the unit test as input data.
+ - ASP.NET unit tests are unit tests that exercise code in an ASP.NET Web
+ application.
+ - Smart device unit tests are unit tests that are deployed to a smart device
+ or emulator and then executed by the smart device test host.
+
+Web Test: Web tests consist of an ordered series of HTTP requests that you
+record in a browser session using Microsoft Internet Explorer. You can have
+the test report specific details about the pages or sites it requests, such
+as whether a particular page contains a specified string.
+
+Load Test: You use a load test to encapsulate non-manual tests, such as
+unit, Web, and generic tests, and then run them simultaneously by using
+virtual users. Running these tests under load generates test results,
+including performance and other counters, in tables and in graphs.
+
+Generic test: A generic test is an existing program wrapped to function as a
+test in Visual Studio. The following are examples of tests or programs that
+you can turn into generic tests:
+ - An existing test that uses process exit codes to communicate whether the
+ test passed or failed. 0 indicates passing and any other value indicates
+ a failure.
+ - A general program to obtain specific functionality during a test scenario.
+ - A test or program that uses a special XML file (called a “summary results
+ file”), to communicate detailed results.
+
+Manual test: The manual test type is used when the test tasks are to be
+completed by a test engineer as opposed to an automated script.
+
+Ordered test: Use an ordered test to execute a set of tests in an order you
+specify.
+
+-------------------------------------------------------------------------------
+
+
diff --git a/umbraco.Test/DocumentTest.cs b/umbraco.Test/DocumentTest.cs
new file mode 100644
index 0000000000..b2eef67c39
--- /dev/null
+++ b/umbraco.Test/DocumentTest.cs
@@ -0,0 +1,837 @@
+using umbraco.cms.businesslogic.web;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using umbraco.BusinessLogic;
+using umbraco.cms.businesslogic;
+using System.Collections.Generic;
+using System.Xml;
+using Microsoft.VisualStudio.TestTools.UnitTesting.Web;
+using System.Linq;
+using System.Threading;
+using umbraco.cms.businesslogic.datatype;
+using umbraco.editorControls.textfield;
+using umbraco.cms.businesslogic.propertytype;
+using umbraco.cms.businesslogic.property;
+
+namespace umbraco.Test
+{
+
+
+ ///
+ /// Test for the Document API.
+ ///
+ ///
+ /// All of these tests are run in the ASP.Net context and these tests will require that there is data
+ /// in the Umbraco instance being tested including both document types and content.
+ ///
+ /// This WILL make alot of SQL calls.
+ ///
+ /// All of these tests will also delete any data that they create
+ ///
+ [TestClass()]
+ public class DocumentTest
+ {
+
+ #region Unit Tests
+ ///
+ ///A test for making a new document and deleting it which actuall first moves it to the recycle bin
+ ///and then deletes it.
+ ///
+ [TestMethod()]
+ public void MakeNewTest()
+ {
+ //System.Diagnostics.Debugger.Break();
+ string Name = "TEST-" + Guid.NewGuid().ToString("N");
+ DocumentType dct = new DocumentType(GetExistingDocTypeId());
+ int ParentId = -1;
+ Document actual = Document.MakeNew(Name, dct, m_User, ParentId);
+ var id = actual.Id;
+ Assert.IsTrue(actual.Id > 0);
+ RecycleAndDelete(actual);
+ }
+
+ ///
+ /// A test for Copying a node, then deleting the copied node.
+ /// This does error checking on the case of when a node is being copied that is in the root and doesn't have a parent node, it will
+ /// lookup the root docs to do the test.
+ ///
+ [TestMethod()]
+ public void CopyTest()
+ {
+ //System.Diagnostics.Debugger.Break();
+ Document target = new Document(GetExistingNodeId());
+ int parentId = target.Level == 1 ? -1 : target.Parent.Id;
+ 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);
+
+ //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);
+
+ //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);
+ //get the children difference which should be the new node
+ var diff = newChildIds.Except(childrenIds);
+
+ Assert.AreEqual(1, diff.Count());
+
+ Document newDoc = new Document(diff.First());
+
+ RecycleAndDelete(newDoc);
+ }
+
+ ///
+ /// Tests copying by relating nodes, then deleting
+ ///
+ [TestMethod()]
+ public void CopyAndRelateTest()
+ {
+ //System.Diagnostics.Debugger.Break();
+ Document target = new Document(GetExistingNodeId());
+ int parentId = target.Parent.Id;
+ bool RelateToOrignal = true;
+
+ //get children ids
+ var childrenIds = target.Parent.Children.ToList().Select(x => x.Id);
+
+ target.Copy(parentId, m_User, RelateToOrignal);
+
+ Assert.AreEqual(childrenIds.Count() + 1, target.Parent.ChildCount);
+
+ Document parent = new Document(parentId);
+ //get the children difference which should be the new node
+ var diff = parent.Children.ToList().Select(x => x.Id).Except(childrenIds);
+
+ Assert.AreEqual(1, diff.Count());
+
+ Document newDoc = new Document(diff.First());
+
+ RecycleAndDelete(newDoc);
+ }
+
+ ///
+ ///Create a new document, create preview xml for it, then delete it
+ ///
+ [TestMethod()]
+ public void ToPreviewXmlTest()
+ {
+ //System.Diagnostics.Debugger.Break();
+ string Name = "TEST-" + Guid.NewGuid().ToString("N");
+ DocumentType dct = new DocumentType(GetExistingDocTypeId());
+ int ParentId = -1;
+ Document actual = Document.MakeNew(Name, dct, m_User, ParentId);
+ var id = actual.Id;
+ Assert.IsTrue(actual.Id > 0);
+
+ XmlDocument xd = new XmlDocument();
+ var xmlNode = actual.ToPreviewXml(xd);
+
+ Assert.IsNotNull(xmlNode);
+ Assert.IsTrue(xmlNode.HasChildNodes);
+
+ RecycleAndDelete(actual);
+ }
+
+ ///
+ /// Run test to create a node, publish it and delete it. This will test the versioning too.
+ ///
+ [TestMethod()]
+ public void MakeNewAndPublishTest()
+ {
+ //System.Diagnostics.Debugger.Break();
+ string Name = "TEST-" + Guid.NewGuid().ToString("N");
+ DocumentType dct = new DocumentType(GetExistingDocTypeId());
+ int ParentId = -1;
+ Document actual = Document.MakeNew(Name, dct, m_User, ParentId);
+ var id = actual.Id;
+ Assert.IsTrue(actual.Id > 0);
+
+ var versionCount = actual.GetVersions().Count();
+
+ actual.Publish(m_User);
+
+ Assert.IsTrue(actual.Published);
+ Assert.AreEqual(versionCount + 1, actual.GetVersions().Count());
+
+ RecycleAndDelete(actual);
+ }
+
+ ///
+ ///A test that creates a new document, publishes it, unpublishes it and finally deletes it
+ ///
+ [TestMethod()]
+ public void PublishThenUnPublishTest()
+ {
+ //System.Diagnostics.Debugger.Break();
+ string Name = "TEST-" + Guid.NewGuid().ToString("N");
+ DocumentType dct = new DocumentType(GetExistingDocTypeId());
+ int ParentId = -1;
+ Document actual = Document.MakeNew(Name, dct, m_User, ParentId);
+ var id = actual.Id;
+ Assert.IsTrue(actual.Id > 0);
+
+ var versionCount = actual.GetVersions().Count();
+
+ actual.Publish(m_User);
+
+ Assert.IsTrue(actual.Published);
+ Assert.AreEqual(versionCount + 1, actual.GetVersions().Count());
+
+ actual.UnPublish();
+
+ Assert.IsFalse(actual.Published);
+
+ RecycleAndDelete(actual);
+ }
+
+ ///
+ ///A test that makes a new document, updates some properties, saves and publishes the document, then rolls the document back and finally deletes it.
+ ///
+ [TestMethod()]
+ public void SaveAndPublishThenRollBackTest()
+ {
+ //System.Diagnostics.Debugger.Break();
+
+ //create new document in the root
+ string Name = "TEST-" + Guid.NewGuid().ToString("N");
+ DocumentType dct = new DocumentType(GetExistingDocTypeId());
+ Document actual = Document.MakeNew(Name, dct, m_User, -1);
+ var id = actual.Id;
+ Assert.IsTrue(actual.Id > 0);
+
+ //get a text property
+ var prop = GetTextFieldProperty(dct, actual);
+ var originalPropVal = prop.Value;
+ var versionCount = actual.GetVersions().Count();
+
+ //save
+ actual.Save();
+ Assert.IsTrue(actual.HasPendingChanges());
+
+ //publish and create new version
+ actual.Publish(m_User);
+ Assert.IsTrue(actual.Published);
+ var versions = actual.GetVersions().ToList();
+ Assert.AreEqual(versionCount + 1, versions.Count());
+
+ prop.Value = "updated!"; //udpate the prop
+ Assert.AreNotEqual(originalPropVal, prop.Value);
+
+ //rollback to first version
+ actual.RollBack(versions.OrderBy(x => x.Date).Last().Version, m_User);
+
+ var rolledBack = new Document(id);
+
+ Assert.AreEqual(originalPropVal, rolledBack.GenericProperties.ToList().Where(x => x.PropertyType.Alias == "headerText").First().Value);
+
+ RecycleAndDelete(actual);
+ }
+
+ ///
+ ///Tests creating a new document type, then creating a new node with that document type, adding some data to it, then deleting the
+ ///document type which should delete all documents associated with that.
+ ///This will create a document type that has it's own id allowed as children. When we create the content nodes, we'll create
+ ///them as children of each other to ensure the deletion occurs correctly.
+ ///
+ [TestMethod()]
+ public void DeleteAllDocsByDocumentTypeTest()
+ {
+ //System.Diagnostics.Debugger.Break();
+
+ //create a new doc type
+ string name = "TEST-" + Guid.NewGuid().ToString("N");
+ var dt = DocumentType.MakeNew(m_User, name);
+
+ //test the doc type
+ Assert.AreEqual(DateTime.Now.Date, dt.CreateDateTime.Date);
+ Assert.IsTrue(dt.Id > 0);
+
+ //allow itself to be created under itself
+ dt.AllowedChildContentTypeIDs = new int[] { dt.Id };
+ //create a tab
+ dt.AddVirtualTab("TEST");
+
+ //test the tab
+ var tabs = dt.getVirtualTabs.ToList();
+ Assert.AreEqual(1, tabs.Count);
+
+ //create a property
+ var allDataTypes = DataTypeDefinition.GetAll().ToList(); //get all definitions
+ dt.AddPropertyType(allDataTypes[0], "testProperty", "Test Property"); //add a property type of the first type found in the list
+
+ //test the prop
+ var prop = dt.getPropertyType("testProperty");
+ Assert.AreEqual("Test Property", prop.Name);
+
+ //create 1st node
+ var node1 = Document.MakeNew("TEST-" + Guid.NewGuid().ToString("N"), dt, m_User, -1);
+ Assert.IsTrue(node1.Id > 0);
+
+ //create 2nd node underneath node 1
+ var node2 = Document.MakeNew("TEST-" + Guid.NewGuid().ToString("N"), dt, m_User, node1.Id);
+ Assert.IsTrue(node2.Id > 0);
+ Assert.AreEqual(node1.Id, node2.Parent.Id);
+
+ //create 3rd node underneath node 2
+ var node3 = Document.MakeNew("TEST-" + Guid.NewGuid().ToString("N"), dt, m_User, node2.Id);
+ Assert.IsTrue(node3.Id > 0);
+ Assert.AreEqual(node2.Id, node3.Parent.Id);
+
+ Document.DeleteFromType(dt);
+
+ Assert.IsFalse(Document.IsNode(node1.Id));
+ Assert.IsFalse(Document.IsNode(node2.Id));
+ Assert.IsFalse(Document.IsNode(node3.Id));
+
+ //now remove the document type created
+ dt.delete();
+
+ Assert.IsFalse(DocumentType.IsNode(dt.Id));
+ }
+
+ ///
+ /// This will find a document type that supports a heirarchy, create 2 root nodes, then create a child node under the first one,
+ /// then move it to the second one and finally delete everything that was created.
+ ///
+ [TestMethod]
+ public void MoveTest()
+ {
+ //first need to document type that allows other types of document types to exist underneath it
+ DocumentType parent = null;
+ DocumentType child = null;
+ var ids = DocumentType.getAllUniqueNodeIdsFromObjectType(DocumentType._objectType);
+ foreach (var id in ids)
+ {
+ var dt = new DocumentType(id);
+ var allowed = dt.AllowedChildContentTypeIDs.ToList();
+ if (allowed.Count() > 0)
+ {
+ parent = dt;
+ child = new DocumentType(allowed[0]);
+ break;
+ }
+ }
+ if (parent == null || child == null)
+ {
+ throw new NotImplementedException("The umbraco install doesn't have document types that support a heirarchy");
+ }
+
+ //now that we have a parent and a child, we need to create some documents
+ var node1 = Document.MakeNew("FromCopy" + Guid.NewGuid().ToString("N"), parent, m_User, -1);
+ Assert.IsTrue(node1.Id > 0);
+
+ var node2 = Document.MakeNew("ToCopy" + Guid.NewGuid().ToString("N"), parent, m_User, -1);
+ Assert.IsTrue(node2.Id > 0);
+
+ //we now have 2 nodes in the root of the same type, we'll create a child node under node1 and move it to node2
+ var childNode = Document.MakeNew("ChildCopy" + Guid.NewGuid().ToString("N"), child, m_User, node2.Id);
+ Assert.IsTrue(childNode.Id > 0);
+
+ childNode.Move(node2.Id);
+ Assert.AreEqual(node2.Id, childNode.Parent.Id);
+
+ RecycleAndDelete(childNode);
+ RecycleAndDelete(node2);
+ RecycleAndDelete(node1);
+ }
+
+ ///
+ /// This will find an existing node, copy it to the same parent, delete the copied node and restore it, then finally completley remove it.
+ ///
+ [TestMethod]
+ public void UndeleteTest()
+ {
+ //find existing content
+ 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 newDoc = Document.MakeNew("NewDoc" + Guid.NewGuid().ToString("N"), dt, m_User, parentId);
+ Assert.IsTrue(newDoc.Id > 0);
+
+ //this will recycle the node
+ newDoc.delete();
+ Assert.IsTrue(newDoc.IsTrashed);
+ Assert.IsTrue(newDoc.Path.Contains("," + (int)RecycleBin.RecycleBinType.Content + ","));
+
+ //undelete the node (move it)
+ newDoc.Move(parentId);
+ Assert.IsFalse(newDoc.IsTrashed);
+ Assert.IsFalse(newDoc.Path.Contains("," + (int)RecycleBin.RecycleBinType.Content + ","));
+
+ //remove it completely
+ RecycleAndDelete(newDoc);
+ }
+
+ ///
+ /// This method will create 20 content nodes, send them to the recycle bin and then empty the recycle bin
+ ///
+ [TestMethod]
+ public void EmptyRecycleBinTest()
+ {
+ var docList = new List();
+ var total = 20;
+ var dt = new DocumentType(GetExistingDocTypeId());
+ //create 20 content nodes
+ for (var i = 0; i < total; i++)
+ {
+ docList.Add(Document.MakeNew(i.ToString() + Guid.NewGuid().ToString("N"), dt, m_User, -1));
+ Assert.IsTrue(docList[docList.Count - 1].Id > 0);
+ }
+
+ //now delete all of them
+ foreach (var d in docList)
+ {
+ d.delete();
+ Assert.IsTrue(d.IsTrashed);
+ }
+
+ //a callback action for each item removed from the recycle bin
+ var totalDeleted = 0;
+ var deleteCallback = new Action(x =>
+ {
+ Assert.AreEqual(total - (++totalDeleted), x);
+ });
+
+ var bin = new RecycleBin(RecycleBin.RecycleBinType.Content);
+ bin.CallTheGarbageMan(deleteCallback);
+
+ Assert.AreEqual(0, RecycleBin.Count(RecycleBin.RecycleBinType.Content));
+ }
+
+ #endregion
+
+ #region TEST TO BE WRITTEN
+
+ /////
+ /////A test for XmlPopulate
+ /////
+ //[TestMethod()]
+ //public void XmlPopulateTest()
+ //{
+ // Guid id = new Guid(); // TODO: Initialize to an appropriate value
+ // Document target = new Document(id); // TODO: Initialize to an appropriate value
+ // XmlDocument xd = null; // TODO: Initialize to an appropriate value
+ // XmlNode x = null; // TODO: Initialize to an appropriate value
+ // XmlNode xExpected = null; // TODO: Initialize to an appropriate value
+ // bool Deep = false; // TODO: Initialize to an appropriate value
+ // target.XmlPopulate(xd, ref x, Deep);
+ // Assert.AreEqual(xExpected, x);
+ // Assert.Inconclusive("A method that does not return a value cannot be verified.");
+ //}
+
+ /////
+ /////A test for XmlNodeRefresh
+ /////
+ //[TestMethod()]
+ //public void XmlNodeRefreshTest()
+ //{
+ // Guid id = new Guid(); // TODO: Initialize to an appropriate value
+ // Document target = new Document(id); // TODO: Initialize to an appropriate value
+ // XmlDocument xd = null; // TODO: Initialize to an appropriate value
+ // XmlNode x = null; // TODO: Initialize to an appropriate value
+ // XmlNode xExpected = null; // TODO: Initialize to an appropriate value
+ // target.XmlNodeRefresh(xd, ref x);
+ // Assert.AreEqual(xExpected, x);
+ // Assert.Inconclusive("A method that does not return a value cannot be verified.");
+ //}
+
+ /////
+ /////A test for XmlGenerate
+ /////
+ //[TestMethod()]
+ //public void XmlGenerateTest()
+ //{
+ // Guid id = new Guid(); // TODO: Initialize to an appropriate value
+ // Document target = new Document(id); // TODO: Initialize to an appropriate value
+ // XmlDocument xd = null; // TODO: Initialize to an appropriate value
+ // target.XmlGenerate(xd);
+ // Assert.Inconclusive("A method that does not return a value cannot be verified.");
+ //}
+
+ /////
+ /////A test for ToXml
+ /////
+ //[TestMethod()]
+ //public void ToXmlTest()
+ //{
+ // Guid id = new Guid(); // TODO: Initialize to an appropriate value
+ // Document target = new Document(id); // TODO: Initialize to an appropriate value
+ // XmlDocument xd = null; // TODO: Initialize to an appropriate value
+ // bool Deep = false; // TODO: Initialize to an appropriate value
+ // XmlNode expected = null; // TODO: Initialize to an appropriate value
+ // XmlNode actual;
+ // actual = target.ToXml(xd, Deep);
+ // Assert.AreEqual(expected, actual);
+ // Assert.Inconclusive("Verify the correctness of this test method.");
+ //}
+
+
+ /////
+ /////A test for SendToPublication
+ /////
+ //[TestMethod()]
+ //public void SendToPublicationTest()
+ //{
+ // 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.SendToPublication(u);
+ // Assert.AreEqual(expected, actual);
+ // Assert.Inconclusive("Verify the correctness of this test method.");
+ //}
+
+ /////
+ /////A test for RePublishAll
+ /////
+ //[TestMethod()]
+ //public void RePublishAllTest()
+ //{
+ // Document.RePublishAll();
+ // Assert.Inconclusive("A method that does not return a value cannot be verified.");
+ //}
+
+ /////
+ /////A test for RegeneratePreviews
+ /////
+ //[TestMethod()]
+ //public void RegeneratePreviewsTest()
+ //{
+ // Document.RegeneratePreviews();
+ // Assert.Inconclusive("A method that does not return a value cannot be verified.");
+ //}
+
+ /////
+ /////A test for refreshXmlSortOrder
+ /////
+ //[TestMethod()]
+ //public void refreshXmlSortOrderTest()
+ //{
+ // Guid id = new Guid(); // TODO: Initialize to an appropriate value
+ // Document target = new Document(id); // TODO: Initialize to an appropriate value
+ // target.refreshXmlSortOrder();
+ // Assert.Inconclusive("A method that does not return a value cannot be verified.");
+ //}
+
+ /////
+ /////A test for PublishWithSubs
+ /////
+ //[TestMethod()]
+ //public void PublishWithSubsTest()
+ //{
+ // 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
+ // target.PublishWithSubs(u);
+ // Assert.Inconclusive("A method that does not return a value cannot be verified.");
+ //}
+
+ /////
+ /////A test for PublishWithResult
+ /////
+ //[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.");
+ //}
+
+ /////
+ /////A test for PublishWithChildrenWithResult
+ /////
+ //[TestMethod()]
+ //public void PublishWithChildrenWithResultTest()
+ //{
+ // 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.PublishWithChildrenWithResult(u);
+ // Assert.AreEqual(expected, actual);
+ // Assert.Inconclusive("Verify the correctness of this test method.");
+ //}
+
+ /////
+ /////A test for Publish
+ /////
+ //[TestMethod()]
+ //public void PublishTest()
+ //{
+ // 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
+ // target.Publish(u);
+ // Assert.Inconclusive("A method that does not return a value cannot be verified.");
+ //}
+
+ /////
+ /////A test for Import
+ /////
+ //[TestMethod()]
+ //public void ImportTest()
+ //{
+ // int ParentId = 0; // TODO: Initialize to an appropriate value
+ // User Creator = null; // TODO: Initialize to an appropriate value
+ // XmlElement Source = null; // TODO: Initialize to an appropriate value
+ // int expected = 0; // TODO: Initialize to an appropriate value
+ // int actual;
+ // actual = Document.Import(ParentId, Creator, Source);
+ // Assert.AreEqual(expected, actual);
+ // Assert.Inconclusive("Verify the correctness of this test method.");
+ //}
+
+ /////
+ /////A test for GetTextPath
+ /////
+ //[TestMethod()]
+ //public void GetTextPathTest()
+ //{
+ // Guid id = new Guid(); // TODO: Initialize to an appropriate value
+ // Document target = new Document(id); // TODO: Initialize to an appropriate value
+ // string expected = string.Empty; // TODO: Initialize to an appropriate value
+ // string actual;
+ // actual = target.GetTextPath();
+ // Assert.AreEqual(expected, actual);
+ // Assert.Inconclusive("Verify the correctness of this test method.");
+ //}
+
+ /////
+ /////A test for GetRootDocuments
+ /////
+ //[TestMethod()]
+ //public void GetRootDocumentsTest()
+ //{
+ // Document[] expected = null; // TODO: Initialize to an appropriate value
+ // Document[] actual;
+ // actual = Document.GetRootDocuments();
+ // Assert.AreEqual(expected, actual);
+ // Assert.Inconclusive("Verify the correctness of this test method.");
+ //}
+
+ /////
+ /////A test for GetNodesForPreview
+ /////
+ //[TestMethod()]
+ //public void GetNodesForPreviewTest()
+ //{
+ // Guid id = new Guid(); // TODO: Initialize to an appropriate value
+ // Document target = new Document(id); // TODO: Initialize to an appropriate value
+ // bool childrenOnly = false; // TODO: Initialize to an appropriate value
+ // List expected = null; // TODO: Initialize to an appropriate value
+ // List actual;
+ // actual = target.GetNodesForPreview(childrenOnly);
+ // Assert.AreEqual(expected, actual);
+ // Assert.Inconclusive("Verify the correctness of this test method.");
+ //}
+
+ /////
+ /////A test for GetDocumentsForRelease
+ /////
+ //[TestMethod()]
+ //public void GetDocumentsForReleaseTest()
+ //{
+ // Document[] expected = null; // TODO: Initialize to an appropriate value
+ // Document[] actual;
+ // actual = Document.GetDocumentsForRelease();
+ // Assert.AreEqual(expected, actual);
+ // Assert.Inconclusive("Verify the correctness of this test method.");
+ //}
+
+ /////
+ /////A test for GetDocumentsForExpiration
+ /////
+ //[TestMethod()]
+ //public void GetDocumentsForExpirationTest()
+ //{
+ // Document[] expected = null; // TODO: Initialize to an appropriate value
+ // Document[] actual;
+ // actual = Document.GetDocumentsForExpiration();
+ // Assert.AreEqual(expected, actual);
+ // Assert.Inconclusive("Verify the correctness of this test method.");
+ //}
+
+ /////
+ /////A test for GetChildrenForTree
+ /////
+ //[TestMethod()]
+ //public void GetChildrenForTreeTest()
+ //{
+ // int NodeId = 0; // TODO: Initialize to an appropriate value
+ // Document[] expected = null; // TODO: Initialize to an appropriate value
+ // Document[] actual;
+ // actual = Document.GetChildrenForTree(NodeId);
+ // Assert.AreEqual(expected, actual);
+ // Assert.Inconclusive("Verify the correctness of this test method.");
+ //}
+
+ /////
+ /////A test for CountSubs
+ /////
+ //[TestMethod()]
+ //public void CountSubsTest()
+ //{
+ // int parentId = 0; // TODO: Initialize to an appropriate value
+ // bool publishedOnly = false; // TODO: Initialize to an appropriate value
+ // int expected = 0; // TODO: Initialize to an appropriate value
+ // int actual;
+ // actual = Document.CountSubs(parentId, publishedOnly);
+ // Assert.AreEqual(expected, actual);
+ // Assert.Inconclusive("Verify the correctness of this test method.");
+ //}
+
+ /////
+ /////A test for Copy
+ /////
+ //[TestMethod()]
+ //public void CopyTest1()
+ //{
+ // Guid id = new Guid(); // TODO: Initialize to an appropriate value
+ // Document target = new Document(id); // TODO: Initialize to an appropriate value
+ // int CopyTo = 0; // TODO: Initialize to an appropriate value
+ // User u = null; // TODO: Initialize to an appropriate value
+ // target.Copy(CopyTo, u);
+ // Assert.Inconclusive("A method that does not return a value cannot be verified.");
+ //}
+
+ #endregion
+
+ #region Private properties and methods
+ private User m_User = new User(0);
+
+ private void RecycleAndDelete(Document d)
+ {
+ var id = d.Id;
+ //now recycle it
+ d.delete();
+
+ Assert.IsTrue(d.IsTrashed);
+
+ Document recycled = new Document(id);
+ //now delete it
+ recycled.delete();
+
+ Assert.IsFalse(Document.IsNode(id));
+
+ //check with sql that it is gone
+ var count = Application.SqlHelper.ExecuteScalar("SELECT COUNT(*) FROM umbracoNode WHERE id=@id",
+ Application.SqlHelper.CreateParameter("@id", id));
+
+ Assert.AreEqual(0, count);
+ }
+
+ ///
+ /// Returns a random docuemnt type that supports a text property
+ ///
+ ///
+ private int GetExistingDocTypeId()
+ {
+ var types = DocumentType.GetAllAsList();
+ DocumentType found = null;
+ TextFieldDataType txtField = new TextFieldDataType();
+ foreach (var d in types)
+ {
+ var prop = d.PropertyTypes
+ .Where(x => x.DataTypeDefinition.DataType.Id == txtField.Id).FirstOrDefault();
+ if (prop != null)
+ {
+ found = d;
+ break;
+ }
+ }
+ if (found == null)
+ {
+ throw new MissingMemberException("No document type was found that contains a text field property");
+ }
+ return found.Id;
+ }
+
+ ///
+ /// Returns a text field property of the document type specified. This will throw an exception if one is not found.
+ ///
+ ///
+ ///
+ private Property GetTextFieldProperty(DocumentType dt, Document d)
+ {
+ TextFieldDataType txtField = new TextFieldDataType();
+ var prop = dt.PropertyTypes
+ .Where(x => x.DataTypeDefinition.DataType.Id == txtField.Id).First();
+ return d.GenericProperties.Where(x => x.PropertyType.Id == prop.Id).First();
+ }
+
+ ///
+ /// Returns a content node
+ ///
+ ///
+ private int GetExistingNodeId()
+ {
+ var ids = Document.getAllUniqueNodeIdsFromObjectType(Document._objectType).ToList();
+ var r = new Random();
+ var index = r.Next(0, ids.Count() - 1);
+ return ids[index];
+ }
+ #endregion
+
+ #region Test Context
+ private TestContext testContextInstance;
+
+ ///
+ ///Gets or sets the test context which provides
+ ///information about and functionality for the current test run.
+ ///
+ public TestContext TestContext
+ {
+ get
+ {
+ return testContextInstance;
+ }
+ set
+ {
+ testContextInstance = value;
+ }
+ }
+ #endregion
+
+ #region Initialize and cleanup
+ //
+ //You can use the following additional attributes as you write your tests:
+ //
+ //Use ClassInitialize to run code before running the first test in the class
+ //[ClassInitialize()]
+ //public static void MyClassInitialize(TestContext testContext)
+ //{
+ //}
+ //
+ //Use ClassCleanup to run code after all tests in a class have run
+ //[ClassCleanup()]
+ //public static void MyClassCleanup()
+ //{
+ //}
+ //
+ //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()
+ //{
+ //}
+ //
+ #endregion
+ }
+}
diff --git a/umbraco.Test/Properties/AssemblyInfo.cs b/umbraco.Test/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..69339e7adc
--- /dev/null
+++ b/umbraco.Test/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("umbraco.Test")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("umbraco.Test")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM componenets. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("662e3518-c5af-49ea-a195-dee4b94a522d")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/umbraco.Test/Test References/umbraco.accessor b/umbraco.Test/Test References/umbraco.accessor
new file mode 100644
index 0000000000..6939496894
--- /dev/null
+++ b/umbraco.Test/Test References/umbraco.accessor
@@ -0,0 +1,2 @@
+umbraco.dll
+Desktop
diff --git a/umbraco.Test/umbraco.Test.csproj b/umbraco.Test/umbraco.Test.csproj
new file mode 100644
index 0000000000..ecbfcdf873
--- /dev/null
+++ b/umbraco.Test/umbraco.Test.csproj
@@ -0,0 +1,172 @@
+
+
+ Debug
+ AnyCPU
+ 9.0.30729
+ 2.0
+ {6277C9FB-3A9A-4537-AA86-82DA9B2527FD}
+ Library
+ Properties
+ umbraco.Test
+ umbraco.Test
+ v3.5
+ 512
+ {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ SAK
+ SAK
+ SAK
+ SAK
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ False
+ ..\foreign dlls\ClientDependency.Core.dll
+
+
+ False
+ ..\foreign dlls\CookComputing.XmlRpcV2.dll
+
+
+ False
+ ..\foreign dlls\Examine.dll
+
+
+ False
+ ..\foreign dlls\ICSharpCode.SharpZipLib.dll
+
+
+ False
+ ..\foreign dlls\IronPython.dll
+
+
+ False
+ ..\foreign dlls\IronRuby.dll
+
+
+ False
+ ..\foreign dlls\Microsoft.Scripting.dll
+
+
+ False
+ ..\foreign dlls\Microsoft.Scripting.Core.dll
+
+
+ False
+ ..\foreign dlls\Microsoft.Scripting.ExtensionAttribute.dll
+
+
+
+
+
+ 3.5
+
+
+
+ 3.5
+
+
+
+
+
+
+
+ 3.5
+
+
+ 3.5
+
+
+ 3.5
+
+
+
+
+ 3.5
+
+
+ False
+ ..\foreign dlls\TidyNet.dll
+
+
+ False
+ ..\foreign dlls\UmbracoExamine.dll
+
+
+ False
+ ..\foreign dlls\UrlRewritingNet.UrlRewriter.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {255F5DF1-4E43-4758-AC05-7A0B68EB021B}
+ umbraco.editorControls
+
+
+ {52AB8F1F-FB76-4E8C-885F-0747B6CE71EC}
+ umbraco.macroRenderings
+
+
+ {6EDD2061-82F2-461B-BB6E-879245A832DE}
+ umbraco.controls
+
+
+ {E469A9CE-1BEC-423F-AC44-713CD72457EA}
+ umbraco.businesslogic
+
+
+ {CCD75EC3-63DB-4184-B49D-51C1DD337230}
+ umbraco.cms
+
+
+ {C7CB79F0-1C97-4B33-BFA7-00731B579AE2}
+ umbraco.datalayer
+
+
+ {511F6D8D-7717-440A-9A57-A507E9A8B27F}
+ umbraco.interfaces
+
+
+ {651E1350-91B6-44B7-BD60-7207006D7003}
+ umbraco.presentation
+
+
+ {D7636876-0756-43CB-A192-138C6F0D5E42}
+ umbraco.providers
+
+
+
+
+
\ No newline at end of file
diff --git a/umbraco.Test/umbraco.Test.csproj.vspscc b/umbraco.Test/umbraco.Test.csproj.vspscc
new file mode 100644
index 0000000000..feffdecaa4
--- /dev/null
+++ b/umbraco.Test/umbraco.Test.csproj.vspscc
@@ -0,0 +1,10 @@
+""
+{
+"FILE_VERSION" = "9237"
+"ENLISTMENT_CHOICE" = "NEVER"
+"PROJECT_FILE_RELATIVE_PATH" = ""
+"NUMBER_OF_EXCLUDED_FILES" = "0"
+"ORIGINAL_PROJECT_FILE_PATH" = ""
+"NUMBER_OF_NESTED_PROJECTS" = "0"
+"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
+}
diff --git a/umbraco.sln b/umbraco.sln
index 89e67803e8..874fbc6ec7 100644
--- a/umbraco.sln
+++ b/umbraco.sln
@@ -4,8 +4,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
ProjectSection(SolutionItems) = preProject
build.xml = build.xml
default.build = default.build
+ SHANDEMVAIO.testrunconfig = SHANDEMVAIO.testrunconfig
umbraco weekly.build = umbraco weekly.build
umbraco.build = umbraco.build
+ umbraco.vsmdi = umbraco.vsmdi
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StandardConfig", "StandardConfig", "{B8ECDB8B-BF44-462C-B6DA-22421B3EC4D7}"
@@ -98,9 +100,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DLLs", "DLLs", "{F06D18F6-C
foreign dlls\VistaDB.NET20.dll = foreign dlls\VistaDB.NET20.dll
EndProjectSection
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "umbraco.Test", "umbraco.Test\umbraco.Test.csproj", "{6277C9FB-3A9A-4537-AA86-82DA9B2527FD}"
+EndProject
Global
GlobalSection(TeamFoundationVersionControl) = preSolution
- SccNumberOfProjects = 13
+ SccNumberOfProjects = 14
SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C}
SccTeamFoundationServer = https://tfs01.codeplex.com/
SccLocalPath0 = .
@@ -140,6 +144,12 @@ Global
SccProjectUniqueName12 = umbraco\\umbraco.Legacy\\umbraco.Legacy.csproj
SccProjectName12 = umbraco/umbraco.Legacy
SccLocalPath12 = umbraco\\umbraco.Legacy
+ SccProjectUniqueName13 = umbraco.Test\\umbraco.Test.csproj
+ SccProjectName13 = umbraco.Test
+ SccLocalPath13 = umbraco.Test
+ EndGlobalSection
+ GlobalSection(TestCaseManagementSettings) = postSolution
+ CategoryFile = umbraco.vsmdi
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug - Fixed Version|Any CPU = Debug - Fixed Version|Any CPU
@@ -216,6 +226,12 @@ Global
{27A2590E-1313-4A33-89FD-92811540B69C}.Debug - Fixed Version|Any CPU.ActiveCfg = Debug|Any CPU
{27A2590E-1313-4A33-89FD-92811540B69C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{27A2590E-1313-4A33-89FD-92811540B69C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6277C9FB-3A9A-4537-AA86-82DA9B2527FD}.Debug - Fixed Version|Any CPU.ActiveCfg = Debug|Any CPU
+ {6277C9FB-3A9A-4537-AA86-82DA9B2527FD}.Debug - Fixed Version|Any CPU.Build.0 = Debug|Any CPU
+ {6277C9FB-3A9A-4537-AA86-82DA9B2527FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6277C9FB-3A9A-4537-AA86-82DA9B2527FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6277C9FB-3A9A-4537-AA86-82DA9B2527FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6277C9FB-3A9A-4537-AA86-82DA9B2527FD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/umbraco.vsmdi b/umbraco.vsmdi
new file mode 100644
index 0000000000..d85bbd66f8
--- /dev/null
+++ b/umbraco.vsmdi
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/umbraco/cms/businesslogic/CMSNode.cs b/umbraco/cms/businesslogic/CMSNode.cs
index 0d099fd145..ad43abcca8 100644
--- a/umbraco/cms/businesslogic/CMSNode.cs
+++ b/umbraco/cms/businesslogic/CMSNode.cs
@@ -11,6 +11,7 @@ using System.IO;
using System.Text.RegularExpressions;
using System.ComponentModel;
using umbraco.IO;
+using umbraco.cms.businesslogic.media;
namespace umbraco.cms.businesslogic
{
@@ -44,7 +45,8 @@ namespace umbraco.cms.businesslogic
private int _userId;
private DateTime _createDate;
private bool _hasChildrenInitialized;
- private string m_image = "default.png";
+ private string m_image = "default.png";
+ private bool? _isTrashed = null;
#endregion
@@ -132,7 +134,7 @@ namespace umbraco.cms.businesslogic
/// True if there is a CMSNode with the given id
public static bool IsNode(int Id)
{
- return (SqlHelper.ExecuteScalar("select count(id) from umbracoNode where id = '" + Id + "'") > 0);
+ return (SqlHelper.ExecuteScalar("select count(id) from umbracoNode where id = @id", SqlHelper.CreateParameter("@id", Id)) > 0);
}
///
@@ -231,7 +233,7 @@ namespace umbraco.cms.businesslogic
// But does anyone know what the 'level++' is supposed to be doing there?
// Nothing obviously, since it's a postfix.
- SqlHelper.ExecuteNonQuery("INSERT INTO umbracoNode(trashed, parentID, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text) VALUES(@trashed, @parentID, @nodeObjectType, @nodeUser, @level, @path, @sortOrder, @uniqueID, @text)",
+ SqlHelper.ExecuteNonQuery("INSERT INTO umbracoNode(trashed, parentID, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text, createDate) VALUES(@trashed, @parentID, @nodeObjectType, @nodeUser, @level, @path, @sortOrder, @uniqueID, @text, @createDate)",
SqlHelper.CreateParameter("@trashed", 0),
SqlHelper.CreateParameter("@parentID", parentId),
SqlHelper.CreateParameter("@nodeObjectType", objectType),
@@ -240,7 +242,8 @@ namespace umbraco.cms.businesslogic
SqlHelper.CreateParameter("@path", path),
SqlHelper.CreateParameter("@sortOrder", sortOrder),
SqlHelper.CreateParameter("@uniqueID", uniqueID),
- SqlHelper.CreateParameter("@text", text));
+ SqlHelper.CreateParameter("@text", text),
+ SqlHelper.CreateParameter("@createDate", DateTime.Now));
CMSNode retVal = new CMSNode(uniqueID);
retVal.Path = path + "," + retVal.Id.ToString();
@@ -334,6 +337,49 @@ namespace umbraco.cms.businesslogic
#region Public Methods
+
+ ///
+ /// An xml representation of the CMSNOde
+ ///
+ /// Xmldocument context
+ /// If true the xml will append the CMSNodes child xml
+ /// The CMSNode Xmlrepresentation
+ public virtual XmlNode ToXml(XmlDocument xd, bool Deep)
+ {
+ XmlNode x = xd.CreateNode(XmlNodeType.Element, "node", "");
+ XmlPopulate(xd, x, Deep);
+ return x;
+ }
+
+ public virtual XmlNode ToPreviewXml(XmlDocument xd)
+ {
+ // If xml already exists
+ if (!PreviewExists(UniqueId))
+ {
+ savePreviewXml(ToXml(xd, false), UniqueId);
+ }
+ return GetPreviewXml(xd, UniqueId);
+ }
+
+ public virtual List GetNodesForPreview(bool childrenOnly)
+ {
+ List nodes = new List();
+ string sql = @"
+select umbracoNode.id, umbracoNode.parentId, umbracoNode.level, umbracoNode.sortOrder, cmsPreviewXml.xml from umbracoNode
+inner join cmsPreviewXml on cmsPreviewXml.nodeId = umbracoNode.id
+where trashed = 0 and path like '{0}'
+order by level,sortOrder";
+
+ string pathExp = childrenOnly ? Path + ",%" : Path;
+
+ IRecordsReader dr = SqlHelper.ExecuteReader(String.Format(sql, pathExp));
+ while (dr.Read())
+ nodes.Add(new CMSPreviewNode(dr.GetInt("id"), dr.GetGuid("uniqueID"), dr.GetInt("parentId"), dr.GetShort("level"), dr.GetInt("sortOrder"), dr.GetString("xml")));
+ dr.Close();
+
+ return nodes;
+ }
+
///
/// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility
///
@@ -360,46 +406,74 @@ namespace umbraco.cms.businesslogic
}
return base.ToString();
- }
+ }
///
/// Moves the CMSNode from the current position in the hierarchy to the target
///
/// Target CMSNode id
- public void Move(int NewParentId)
+ public void Move(int newParentId)
{
+ //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)
{
- int maxSortOrder = SqlHelper.ExecuteScalar(
+ CMSNode n = new CMSNode(newParentId);
+
+ //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(
"select coalesce(max(sortOrder),0) from umbracoNode where parentid = @parentId",
- SqlHelper.CreateParameter("@parentId", NewParentId));
+ SqlHelper.CreateParameter("@parentId", newParentId));
-
- CMSNode n = new CMSNode(NewParentId);
- this.Parent = n;
+ this.Parent = n;
+ this.sortOrder = maxSortOrder + 1;
+ }
+
this.Level = n.Level + 1;
this.Path = n.Path + "," + this.Id.ToString();
- this.sortOrder = maxSortOrder + 1;
+ //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 :(
-
- if (n.nodeObjectType == web.Document._objectType)
+ //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)
{
- Document d =
- new umbraco.cms.businesslogic.web.Document(n.Id);
+ //regenerate the xml for the parent node
+ var d = new Document(n.Id);
d.XmlGenerate(new XmlDocument());
-
}
- else if (n.nodeObjectType == media.Media._objectType)
- new umbraco.cms.businesslogic.media.Media(n.Id).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() + ","))
+ {
+ //if we've moved this to the recyle bin, we need to update the trashed property
+ if (!IsTrashed) IsTrashed = true; //don't update if it's not necessary
+ }
+ else
+ {
+ if (IsTrashed) IsTrashed = false; //don't update if it's not necessary
+ }
- //store children array here because iterating over an Array property object is very inneficient.
var children = this.Children;
foreach (CMSNode c in children)
+ {
c.Move(this.Id);
+ }
FireAfterMove(e);
}
@@ -454,47 +528,28 @@ namespace umbraco.cms.businesslogic
#region Public properties
-
///
- /// An xml representation of the CMSNOde
+ /// Determines if the node is in the recycle bin.
+ /// This is only relavent for node types that support a recyle bin (such as Document/Media)
///
- /// Xmldocument context
- /// If true the xml will append the CMSNodes child xml
- /// The CMSNode Xmlrepresentation
- public virtual XmlNode ToXml(XmlDocument xd, bool Deep)
+ public bool IsTrashed
{
- XmlNode x = xd.CreateNode(XmlNodeType.Element, "node", "");
- XmlPopulate(xd, x, Deep);
- return x;
- }
-
- public virtual XmlNode ToPreviewXml(XmlDocument xd)
- {
- // If xml already exists
- if (!PreviewExists(UniqueId))
+ get
{
- savePreviewXml(ToXml(xd, false), UniqueId);
+ if (!_isTrashed.HasValue)
+ {
+ _isTrashed = Convert.ToBoolean(SqlHelper.ExecuteScalar