diff --git a/src/Umbraco.Core/Models/ContentExtensions.cs b/src/Umbraco.Core/Models/ContentExtensions.cs
index 1ca6ff4b7c..cc65a8dc5f 100644
--- a/src/Umbraco.Core/Models/ContentExtensions.cs
+++ b/src/Umbraco.Core/Models/ContentExtensions.cs
@@ -106,6 +106,22 @@ namespace Umbraco.Core.Models
}
#endregion
+ internal static bool IsInRecycleBin(this IContent content)
+ {
+ return IsInRecycleBin(content, Constants.System.RecycleBinContent);
+ }
+
+ internal static bool IsInRecycleBin(this IMedia media)
+ {
+ return IsInRecycleBin(media, Constants.System.RecycleBinMedia);
+ }
+
+ internal static bool IsInRecycleBin(this IContentBase content, int recycleBinId)
+ {
+ return content.Path.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
+ .Contains(recycleBinId.ToInvariantString());
+ }
+
///
/// Checks if the IContentBase has children
///
diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs
index d2df3c9050..d0f4357293 100644
--- a/src/Umbraco.Tests/Models/ContentTests.cs
+++ b/src/Umbraco.Tests/Models/ContentTests.cs
@@ -13,6 +13,32 @@ namespace Umbraco.Tests.Models
[TestFixture]
public class ContentTests
{
+ [TestCase("-1,-20,12,34,56", false)]
+ [TestCase("-1,-21,12,34,56", true)]
+ [TestCase("-1,12,34,56", false)]
+ public void Is_Media_In_Recycle_Bin(string path, bool isInBin)
+ {
+ var mediaType = MockedContentTypes.CreateImageMediaType();
+ var media = MockedMedia.CreateMediaFile(mediaType, -1);
+ media.Path = path;
+ media.Id = 34;
+
+ Assert.AreEqual(isInBin, media.IsInRecycleBin());
+ }
+
+ [TestCase("-1,-20,12,34,56", true)]
+ [TestCase("-1,-21,12,34,56", false)]
+ [TestCase("-1,12,34,56", false)]
+ public void Is_Content_In_Recycle_Bin(string path, bool isInBin)
+ {
+ var contentType = MockedContentTypes.CreateSimpleContentType();
+ var content = MockedContent.CreateSimpleContent(contentType);
+ content.Path = path;
+ content.Id = 34;
+
+ Assert.AreEqual(isInBin, content.IsInRecycleBin());
+ }
+
[Test]
public void Get_Non_Grouped_Properties()
{
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js
index 43de6f1f46..5e2286536b 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js
@@ -98,7 +98,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, $rootSc
/** Gets a child node by id */
getChildNode: function(treeNode, id) {
var found = _.find(treeNode.children, function (child) {
- return child.id === id;
+ return String(child.id) === String(id);
});
return found === undefined ? null : found;
},
diff --git a/src/Umbraco.Web.UI.Client/test/unit/common/services/tree-service.spec.js b/src/Umbraco.Web.UI.Client/test/unit/common/services/tree-service.spec.js
index b6602e3911..a38efec646 100644
--- a/src/Umbraco.Web.UI.Client/test/unit/common/services/tree-service.spec.js
+++ b/src/Umbraco.Web.UI.Client/test/unit/common/services/tree-service.spec.js
@@ -53,10 +53,21 @@ describe('tree service tests', function () {
beforeEach(inject(function ($injector) {
treeService = $injector.get('treeService');
- }));
+ }));
describe('query existing node structure of the tree', function () {
+ it('can get a descendant node with string id', function () {
+
+ var tree = getContentTree();
+ var found = treeService.getDescendantNode(tree, "13");
+
+ expect(found).toBeDefined();
+ expect(found).not.toBeNull();
+ expect(found.id).toBe(13);
+ expect(found.name).toBe("random-name-3");
+ });
+
it('can get a descendant node', function() {
var tree = getContentTree();
diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs
index e781213998..1c1ec80508 100644
--- a/src/Umbraco.Web/Editors/ContentController.cs
+++ b/src/Umbraco.Web/Editors/ContentController.cs
@@ -19,6 +19,7 @@ using Umbraco.Web.WebApi;
using Umbraco.Web.WebApi.Binders;
using Umbraco.Web.WebApi.Filters;
using umbraco;
+using Umbraco.Core.Models;
namespace Umbraco.Web.Editors
{
@@ -177,7 +178,7 @@ namespace Umbraco.Web.Editors
}
///
- /// Deletes an item
+ /// Moves an item to the recycle bin, if it is already there then it will permanently delete it
///
///
///
@@ -186,9 +187,19 @@ namespace Umbraco.Web.Editors
var foundContent = Services.ContentService.GetById(id);
if (foundContent == null)
{
- HandleContentNotFound(id);
+ return HandleContentNotFound(id, false);
}
- Services.ContentService.Delete(foundContent, UmbracoUser.Id);
+
+ //if the current item is in the recycle bin
+ if (foundContent.IsInRecycleBin() == false)
+ {
+ Services.ContentService.MoveToRecycleBin(foundContent, UmbracoUser.Id);
+ }
+ else
+ {
+ Services.ContentService.Delete(foundContent, UmbracoUser.Id);
+ }
+
return Request.CreateResponse(HttpStatusCode.OK);
}
diff --git a/src/Umbraco.Web/Editors/ContentControllerBase.cs b/src/Umbraco.Web/Editors/ContentControllerBase.cs
index 12da55b2ee..bb375ce3b7 100644
--- a/src/Umbraco.Web/Editors/ContentControllerBase.cs
+++ b/src/Umbraco.Web/Editors/ContentControllerBase.cs
@@ -33,13 +33,17 @@ namespace Umbraco.Web.Editors
{
}
- protected void HandleContentNotFound(int id)
+ protected HttpResponseMessage HandleContentNotFound(int id, bool throwException = true)
{
ModelState.AddModelError("id", string.Format("content with id: {0} was not found", id));
var errorResponse = Request.CreateErrorResponse(
HttpStatusCode.NotFound,
ModelState);
- throw new HttpResponseException(errorResponse);
+ if (throwException)
+ {
+ throw new HttpResponseException(errorResponse);
+ }
+ return errorResponse;
}
protected void UpdateName(ContentItemSave contentItem)