diff --git a/src/Umbraco.Core/Events/RecycleBinEventArgs.cs b/src/Umbraco.Core/Events/RecycleBinEventArgs.cs new file mode 100644 index 0000000000..028438c6ae --- /dev/null +++ b/src/Umbraco.Core/Events/RecycleBinEventArgs.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; + +namespace Umbraco.Core.Events +{ + public class RecycleBinEventArgs : CancellableEventArgs + { + public RecycleBinEventArgs(Guid nodeObjectType, IEnumerable files) + : base(false) + { + NodeObjectType = nodeObjectType; + Files = files; + } + + /// + /// Gets the Id of the node object type of the items + /// being deleted from the Recycle Bin. + /// + public Guid NodeObjectType { get; private set; } + + /// + /// Gets the list of Files that should be deleted as part + /// of emptying the Recycle Bin. + /// + public IEnumerable Files { get; private set; } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/RecycleBinRepository.cs b/src/Umbraco.Core/Persistence/Repositories/RecycleBinRepository.cs index d879503485..b468a06dad 100644 --- a/src/Umbraco.Core/Persistence/Repositories/RecycleBinRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/RecycleBinRepository.cs @@ -1,11 +1,19 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; +using Umbraco.Core.Configuration; +using Umbraco.Core.Events; +using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories { + /// + /// Represents a repository specific to the Recycle Bins + /// available for Content and Media. + /// internal class RecycleBinRepository { private readonly IDatabaseUnitOfWork _unitOfWork; @@ -59,6 +67,7 @@ namespace Umbraco.Core.Persistence.Repositories } //Trigger (internal) event with list of files to delete - RecycleBinEmptied + RecycleBinEmptied.RaiseEvent(new RecycleBinEventArgs(nodeObjectType, files), this); return true; } @@ -69,6 +78,34 @@ namespace Umbraco.Core.Persistence.Repositories } } + public bool DeleteFiles(IEnumerable files) + { + try + { + var fs = FileSystemProviderManager.Current.GetFileSystemProvider(); + Parallel.ForEach(files, file => + { + if (UmbracoSettings.UploadAllowDirectories) + { + var relativeFilePath = fs.GetRelativePath(file); + var parentDirectory = System.IO.Path.GetDirectoryName(relativeFilePath); + fs.DeleteDirectory(parentDirectory, true); + } + else + { + fs.DeleteFile(file, true); + } + }); + + return true; + } + catch (Exception ex) + { + LogHelper.Error("An error occurred while deleting files attached to deleted nodes: " + ex.Message, ex); + return false; + } + } + private string FormatDeleteStatement(string tableName, string keyName) { return @@ -76,5 +113,10 @@ namespace Umbraco.Core.Persistence.Repositories "DELETE FROM {0} FROM {0} as TB1 INNER JOIN umbracoNode as TB2 ON TB1.{1} = TB2.id WHERE TB2.trashed = '1' AND TB2.nodeObjectType = @NodeObjectType", tableName, keyName); } + + /// + /// Occurs after RecycleBin was been Emptied + /// + internal static event TypedEventHandler RecycleBinEmptied; } } \ No newline at end of file diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index c4af37c34a..ddaebb5637 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -1016,7 +1016,7 @@ namespace Umbraco.Core.Services var uow = _uowProvider.GetUnitOfWork(); using (var repository = _repositoryFactory.CreateContentRepository(uow)) { - var query = Query.Builder.Where(x => x.Trashed == true); + /*var query = Query.Builder.Where(x => x.Trashed == true); var contents = repository.GetByQuery(query).OrderByDescending(x => x.Level); foreach (var content in contents) @@ -1027,7 +1027,8 @@ namespace Umbraco.Core.Services repository.Delete(content); Deleted.RaiseEvent(new DeleteEventArgs(content, false), this); - } + }*/ + repository.EmptyRecycleBin(); uow.Commit(); } diff --git a/src/Umbraco.Core/Services/MediaService.cs b/src/Umbraco.Core/Services/MediaService.cs index 34f4000d4b..dac42a4fc6 100644 --- a/src/Umbraco.Core/Services/MediaService.cs +++ b/src/Umbraco.Core/Services/MediaService.cs @@ -542,7 +542,7 @@ namespace Umbraco.Core.Services var uow = _uowProvider.GetUnitOfWork(); using (var repository = _repositoryFactory.CreateMediaRepository(uow)) { - var query = Query.Builder.Where(x => x.Trashed == true); + /*var query = Query.Builder.Where(x => x.Trashed == true); var contents = repository.GetByQuery(query).OrderByDescending(x => x.Level); foreach (var content in contents) @@ -553,7 +553,8 @@ namespace Umbraco.Core.Services repository.Delete(content); Deleted.RaiseEvent(new DeleteEventArgs(content, false), this); - } + }*/ + repository.EmptyRecycleBin(); uow.Commit(); } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 5fa9177947..9c37a3dd48 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -156,6 +156,7 @@ + diff --git a/src/Umbraco.Web/Strategies/DeleteFilesAfterEmptiedRecycleBin.cs b/src/Umbraco.Web/Strategies/DeleteFilesAfterEmptiedRecycleBin.cs new file mode 100644 index 0000000000..629c9863b6 --- /dev/null +++ b/src/Umbraco.Web/Strategies/DeleteFilesAfterEmptiedRecycleBin.cs @@ -0,0 +1,30 @@ +using Umbraco.Core; +using Umbraco.Core.Events; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence.Repositories; + +namespace Umbraco.Web.Strategies +{ + /// + /// Represents the DeleteFilesAfterEmptiedRecycleBin class, which subscribes to the + /// RecycleBinEmptied event of the class + /// and is responsible for deleting files attached to the items that were + /// permanently deleted from the Recycle Bin - when the Recycle Bin was emptied. + /// + public sealed class DeleteFilesAfterEmptiedRecycleBin : ApplicationEventHandler + { + protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, + ApplicationContext applicationContext) + { + RecycleBinRepository.RecycleBinEmptied += RecycleBinRepository_RecycleBinEmptied; + } + + void RecycleBinRepository_RecycleBinEmptied(RecycleBinRepository sender, RecycleBinEventArgs e) + { + var success = sender.DeleteFiles(e.Files); + + if(success) + LogHelper.Info("All files attached to delete nodes were deleted as part of emptying the Recycle Bin"); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 4fc9b92b8d..c804a064ee 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -369,6 +369,7 @@ +