/// <summary> /// Saves and Publishes a single <see cref="IContent"/> object /// </summary> /// <param name="content">The <see cref="IContent"/> to save and publish</param> /// <param name="userId">Optional Id of the User issueing the publishing</param> /// <param name="raiseEvents">Optional boolean indicating whether or not to raise save events.</param> /// <returns>True if publishing succeeded, otherwise False</returns> private Attempt<PublishStatus> SaveAndPublishDo(IContent content, int userId = 0, bool raiseEvents = true) { if (raiseEvents) { if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IContent>(content), this)) { return new Attempt<PublishStatus>(false, new PublishStatus(content, PublishStatusType.FailedCancelledByEvent)); } } using (new WriteLock(Locker)) { //Has this content item previously been published? If so, we don't need to refresh the children var previouslyPublished = content.HasIdentity && HasPublishedVersion(content.Id); //content might not have an id var publishStatus = new PublishStatus(content, PublishStatusType.Success); //initially set to success //Check if parent is published (although not if its a root node) - if parent isn't published this Content cannot be published publishStatus.StatusType = CheckAndLogIsPublishable(content); //Content contains invalid property values and can therefore not be published - fire event? publishStatus.StatusType = CheckAndLogIsValid(content); //set the invalid properties (if there are any) publishStatus.InvalidProperties = ((ContentBase) content).LastInvalidProperties; //if we're still successful, then publish using the strategy if (publishStatus.StatusType == PublishStatusType.Success) { var internalStrategy = (PublishingStrategy)_publishingStrategy; //Publish and then update the database with new status var publishResult = internalStrategy.PublishInternal(content, userId); //set the status type to the publish result publishStatus.StatusType = publishResult.Result.StatusType; } //we are successfully published if our publishStatus is still Successful bool published = publishStatus.StatusType == PublishStatusType.Success; var uow = _uowProvider.GetUnitOfWork(); using (var repository = _repositoryFactory.CreateContentRepository(uow)) { //Since this is the Save and Publish method, the content should be saved even though the publish fails or isn't allowed content.WriterId = userId; repository.AddOrUpdate(content); uow.Commit(); var xml = content.ToXml(); //Preview Xml CreateAndSavePreviewXml(xml, content.Id, content.Version, uow.Database); if (published) { //Content Xml CreateAndSaveContentXml(xml, content.Id, uow.Database); } } if (raiseEvents) Saved.RaiseEvent(new SaveEventArgs<IContent>(content, false), this); //Save xml to db and call following method to fire event through PublishingStrategy to update cache if (published) { _publishingStrategy.PublishingFinalized(content); } //We need to check if children and their publish state to ensure that we 'republish' content that was previously published if (published && previouslyPublished == false && HasChildren(content.Id)) { var descendants = GetPublishedDescendants(content); _publishingStrategy.PublishingFinalized(descendants, false); } Audit.Add(AuditTypes.Publish, "Save and Publish performed by user", userId, content.Id); return new Attempt<PublishStatus>(publishStatus.StatusType == PublishStatusType.Success, publishStatus); } }
private string GetMessageForStatus(PublishStatus status) { switch (status.StatusType) { case PublishStatusType.Success: case PublishStatusType.SuccessAlreadyPublished: return ui.Text("publish", "nodePublish", status.ContentItem.Name, UmbracoUser); case PublishStatusType.FailedPathNotPublished: return ui.Text("publish", "contentPublishedFailedByParent", string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id), UmbracoUser); case PublishStatusType.FailedHasExpired: case PublishStatusType.FailedAwaitingRelease: case PublishStatusType.FailedIsTrashed: return ""; //we will not notify about this type of failure... or should we ? case PublishStatusType.FailedCancelledByEvent: return ui.Text("publish", "contentPublishedFailedByEvent", string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id), UmbracoUser); case PublishStatusType.FailedContentInvalid: return ui.Text("publish", "contentPublishedFailedInvalid", new []{ string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id), string.Join(",", status.InvalidProperties.Select(x => x.Alias)) }, UmbracoUser); default: return status.StatusType.ToString(); } }
private string GetMessageForStatus(PublishStatus status) { switch (status.StatusType) { case PublishStatusType.Success: case PublishStatusType.SuccessAlreadyPublished: return ui.Text("speechBubbles", "editContentPublishedText", UmbracoUser); case PublishStatusType.FailedPathNotPublished: return ui.Text("publish", "contentPublishedFailedByParent", string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id), UmbracoUser).Trim(); case PublishStatusType.FailedCancelledByEvent: return ui.Text("speechBubbles", "contentPublishedFailedByEvent"); case PublishStatusType.FailedHasExpired: case PublishStatusType.FailedAwaitingRelease: case PublishStatusType.FailedIsTrashed: case PublishStatusType.FailedContentInvalid: return ui.Text("publish", "contentPublishedFailedInvalid", new[] { string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id), string.Join(",", status.InvalidProperties.Select(x => x.Alias)) }, UmbracoUser); default: throw new IndexOutOfRangeException(); } }
private void ShowMessageForPublishStatus(PublishStatus status, ContentItemDisplay display) { switch (status.StatusType) { case PublishStatusType.Success: case PublishStatusType.SuccessAlreadyPublished: display.AddSuccessNotification( ui.Text("speechBubbles", "editContentPublishedHeader", UmbracoUser), ui.Text("speechBubbles", "editContentPublishedText", UmbracoUser)); break; case PublishStatusType.FailedPathNotPublished: display.AddWarningNotification( ui.Text("publish"), ui.Text("publish", "contentPublishedFailedByParent", string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id), UmbracoUser).Trim()); break; case PublishStatusType.FailedCancelledByEvent: display.AddWarningNotification( ui.Text("publish"), ui.Text("speechBubbles", "contentPublishedFailedByEvent")); break; case PublishStatusType.FailedAwaitingRelease: display.AddWarningNotification( ui.Text("publish"), ui.Text("publish", "contentPublishedFailedAwaitingRelease", new[] { string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id) }, UmbracoUser).Trim()); break; case PublishStatusType.FailedHasExpired: //TODO: We should add proper error messaging for this! case PublishStatusType.FailedIsTrashed: //TODO: We should add proper error messaging for this! case PublishStatusType.FailedContentInvalid: display.AddWarningNotification( ui.Text("publish"), ui.Text("publish", "contentPublishedFailedInvalid", new[] { string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id), string.Join(",", status.InvalidProperties.Select(x => x.Alias)) }, UmbracoUser).Trim()); break; default: throw new IndexOutOfRangeException(); } }