diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs index 741634157d..60951f6086 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs @@ -618,6 +618,17 @@ namespace Umbraco.Core.Persistence.Repositories repo.ReplaceEntityPermissions(permissionSet); } + public void ClearPublished(IContent content) + { + // race cond! + var documentDtos = Database.Fetch("WHERE nodeId=@id AND published=@published", new { id = content.Id, published = true }); + foreach (var documentDto in documentDtos) + { + documentDto.Published = false; + Database.Update(documentDto); + } + } + public IContent GetByLanguage(int id, string language) { var sql = GetBaseQuery(false); diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs index ac0fcebbe7..5cb470b7cd 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs @@ -27,6 +27,12 @@ namespace Umbraco.Core.Persistence.Repositories /// void ReplaceContentPermissions(EntityPermissionSet permissionSet); + /// + /// Clears the published flag for a content. + /// + /// + void ClearPublished(IContent content); + /// /// Gets a specific language version of an /// diff --git a/src/Umbraco.Core/Publishing/PublishingStrategy.cs b/src/Umbraco.Core/Publishing/PublishingStrategy.cs index 899567bf8d..1c33f87c5e 100644 --- a/src/Umbraco.Core/Publishing/PublishingStrategy.cs +++ b/src/Umbraco.Core/Publishing/PublishingStrategy.cs @@ -303,32 +303,7 @@ namespace Umbraco.Core.Publishing /// True if the unpublish operation was successfull and not cancelled, otherwise false public override bool UnPublish(IContent content, int userId) { - if (UnPublishing.IsRaisedEventCancelled(new PublishEventArgs(content), this)) - { - LogHelper.Info( - string.Format("Content '{0}' with Id '{1}' will not be un-published, the event was cancelled.", content.Name, content.Id)); - return false; - } - - - //If Content has a release date set to before now, it should be removed so it doesn't interrupt an unpublish - //Otherwise it would remain released == published - if (content.ReleaseDate.HasValue && content.ReleaseDate.Value <= DateTime.Now) - { - content.ReleaseDate = null; - - LogHelper.Info( - string.Format( - "Content '{0}' with Id '{1}' had its release date removed, because it was unpublished.", - content.Name, content.Id)); - } - - content.ChangePublishedState(PublishedState.Unpublished); - - LogHelper.Info( - string.Format("Content '{0}' with Id '{1}' has been unpublished.", - content.Name, content.Id)); - return true; + return UnPublishInternal(content, userId).Success; } /// @@ -337,43 +312,47 @@ namespace Umbraco.Core.Publishing /// An enumerable list of /// Id of the User issueing the unpublish operation /// A list of publish statuses - internal IEnumerable> UnPublishInternal(IEnumerable content, int userId) + private IEnumerable> UnPublishInternal(IEnumerable content, int userId) { - var result = new List>(); + return content.Select(x => UnPublishInternal(x, userId)); + } - //Only update content thats already been published - foreach (var item in content.Where(x => x.Published == true)) + private Attempt UnPublishInternal(IContent content, int userId) + { + // content should (is assumed to ) be the newest version, which may not be published + // don't know how to test this, so it's not verified + // NOTE + // if published != newest, then the published flags need to be reseted by whoever is calling that method + // at the moment it's done by the content service + + //Fire UnPublishing event + if (UnPublishing.IsRaisedEventCancelled(new PublishEventArgs(content), this)) { - //Fire UnPublishing event - if (UnPublishing.IsRaisedEventCancelled(new PublishEventArgs(item), this)) - { - LogHelper.Info( - string.Format("Content '{0}' with Id '{1}' will not be published, the event was cancelled.", item.Name, item.Id)); - result.Add(Attempt.Fail(new PublishStatus(item, PublishStatusType.FailedCancelledByEvent))); - continue; - } - - //If Content has a release date set to before now, it should be removed so it doesn't interrupt an unpublish - //Otherwise it would remain released == published - if (item.ReleaseDate.HasValue && item.ReleaseDate.Value <= DateTime.Now) - { - item.ReleaseDate = null; - - LogHelper.Info( - string.Format("Content '{0}' with Id '{1}' had its release date removed, because it was unpublished.", - item.Name, item.Id)); - } - - item.ChangePublishedState(PublishedState.Unpublished); - LogHelper.Info( - string.Format("Content '{0}' with Id '{1}' has been unpublished.", - item.Name, item.Id)); - - result.Add(Attempt.Succeed(new PublishStatus(item))); + string.Format("Content '{0}' with Id '{1}' will not be unpublished, the event was cancelled.", content.Name, content.Id)); + return Attempt.Fail(new PublishStatus(content, PublishStatusType.FailedCancelledByEvent)); } - return result; + //If Content has a release date set to before now, it should be removed so it doesn't interrupt an unpublish + //Otherwise it would remain released == published + if (content.ReleaseDate.HasValue && content.ReleaseDate.Value <= DateTime.Now) + { + content.ReleaseDate = null; + + LogHelper.Info( + string.Format("Content '{0}' with Id '{1}' had its release date removed, because it was unpublished.", + content.Name, content.Id)); + } + + // if newest is published, unpublish + if (content.Published) + content.ChangePublishedState(PublishedState.Unpublished); + + LogHelper.Info( + string.Format("Content '{0}' with Id '{1}' has been unpublished.", + content.Name, content.Id)); + + return Attempt.Succeed(new PublishStatus(content)); } /// diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index f86739aeb8..c4181a80a4 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -1698,6 +1698,13 @@ namespace Umbraco.Core.Services /// True if unpublishing succeeded, otherwise False private bool UnPublishDo(IContent content, bool omitCacheRefresh = false, int userId = 0) { + var newest = GetById(content.Id); // ensure we have the newest version + if (content.Version != newest.Version) // but use the original object if it's already the newest version + content = newest; + var published = content.Published ? content : GetPublishedVersion(content.Id); // get the published version + if (published == null) + return false; // already unpublished + var unpublished = _publishingStrategy.UnPublish(content, userId); if (unpublished) { @@ -1706,6 +1713,9 @@ namespace Umbraco.Core.Services { content.WriterId = userId; repository.AddOrUpdate(content); + // is published is not newest, reset the published flag on published version + if (published.Version != content.Version) + repository.ClearPublished(published); repository.DeleteContentXml(content); uow.Commit();