/// <summary> /// Moves an <see cref="IContent"/> object to a new location by changing its parent id. /// </summary> /// <remarks> /// If the <see cref="IContent"/> object is already published it will be /// published after being moved to its new location. Otherwise it'll just /// be saved with a new parent id. /// </remarks> /// <param name="content">The <see cref="IContent"/> to move</param> /// <param name="parentId">Id of the Content's new Parent</param> /// <param name="userId">Optional Id of the User moving the Content</param> public void Move(IContent content, int parentId, int userId = 0) { using (new WriteLock(Locker)) { //This ensures that the correct method is called if this method is used to Move to recycle bin. if (parentId == -20) { MoveToRecycleBin(content, userId); return; } if (Moving.IsRaisedEventCancelled(new MoveEventArgs<IContent>(content, parentId), this)) return; content.WriterId = userId; if (parentId == -1) { content.Path = string.Concat("-1,", content.Id); content.Level = 1; } else { var parent = GetById(parentId); content.Path = string.Concat(parent.Path, ",", content.Id); content.Level = parent.Level + 1; } //If Content is being moved away from Recycle Bin, its state should be un-trashed if (content.Trashed && parentId != -20) { content.ChangeTrashedState(false, parentId); } else { content.ParentId = parentId; } //If Content is published, it should be (re)published from its new location if (content.Published) { //If Content is Publishable its saved and published //otherwise we save the content without changing the publish state, and generate new xml because the Path, Level and Parent has changed. if (IsPublishable(content)) { SaveAndPublish(content, userId); } else { Save(content, false, userId, true); using (var uow = _uowProvider.GetUnitOfWork()) { var xml = content.ToXml(); var poco = new ContentXmlDto { NodeId = content.Id, Xml = xml.ToString(SaveOptions.None) }; var exists = uow.Database.FirstOrDefault<ContentXmlDto>("WHERE nodeId = @Id", new { Id = content.Id }) != null; int result = exists ? uow.Database.Update(poco) : Convert.ToInt32(uow.Database.Insert(poco)); } } } else { Save(content, userId); } //Ensure that Path and Level is updated on children var children = GetChildren(content.Id); if (children.Any()) { foreach (var child in children) { Move(child, content.Id, userId); } } Moved.RaiseEvent(new MoveEventArgs<IContent>(content, false, parentId), this); Audit.Add(AuditTypes.Move, "Move Content performed by user", userId, content.Id); } }
/// <summary> /// Deletes an <see cref="IContent"/> object by moving it to the Recycle Bin /// </summary> /// <remarks>Move an item to the Recycle Bin will result in the item being unpublished</remarks> /// <param name="content">The <see cref="IContent"/> to delete</param> /// <param name="userId">Optional Id of the User deleting the Content</param> public void MoveToRecycleBin(IContent content, int userId = 0) { using (new WriteLock(Locker)) { if (Trashing.IsRaisedEventCancelled(new MoveEventArgs<IContent>(content, -20), this)) return; //Make sure that published content is unpublished before being moved to the Recycle Bin if (HasPublishedVersion(content.Id)) { UnPublish(content, userId); } //Unpublish descendents of the content item that is being moved to trash var descendants = GetDescendants(content).OrderBy(x => x.Level).ToList(); foreach (var descendant in descendants) { UnPublish(descendant, userId); } var uow = _uowProvider.GetUnitOfWork(); using (var repository = _repositoryFactory.CreateContentRepository(uow)) { content.WriterId = userId; content.ChangeTrashedState(true); repository.AddOrUpdate(content); //Loop through descendants to update their trash state, but ensuring structure by keeping the ParentId foreach (var descendant in descendants) { descendant.WriterId = userId; descendant.ChangeTrashedState(true, descendant.ParentId); repository.AddOrUpdate(descendant); } uow.Commit(); } Trashed.RaiseEvent(new MoveEventArgs<IContent>(content, false, -20), this); Audit.Add(AuditTypes.Move, "Move Content to Recycle Bin performed by user", userId, content.Id); } }