U4-9610 - fix nullref in BulkPublishController
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
@@ -12,7 +13,8 @@ namespace Umbraco.Core.Publishing
|
||||
{
|
||||
public PublishStatus(IContent content, PublishStatusType statusType, EventMessages eventMessages)
|
||||
: base(content, statusType, eventMessages)
|
||||
{
|
||||
{
|
||||
InvalidProperties = Enumerable.Empty<Property>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -20,8 +22,7 @@ namespace Umbraco.Core.Publishing
|
||||
/// </summary>
|
||||
public PublishStatus(IContent content, EventMessages eventMessages)
|
||||
: this(content, PublishStatusType.Success, eventMessages)
|
||||
{
|
||||
}
|
||||
{ }
|
||||
|
||||
public IContent ContentItem
|
||||
{
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Umbraco.Core.Publishing
|
||||
/// Publishes a single piece of Content
|
||||
/// </summary>
|
||||
/// <param name="content"><see cref="IContent"/> to publish</param>
|
||||
/// <param name="userId">Id of the User issueing the publish operation</param>
|
||||
/// <param name="userId">Id of the User issueing the publish operation</param>
|
||||
internal Attempt<PublishStatus> PublishInternal(IContent content, int userId)
|
||||
{
|
||||
var evtMsgs = _eventMessagesFactory.Get();
|
||||
@@ -99,26 +99,26 @@ namespace Umbraco.Core.Publishing
|
||||
/// By default this is set to true which means that it will publish any content item in the list that is completely unpublished and
|
||||
/// not visible on the front-end. If set to false, this will only publish content that is live on the front-end but has new versions
|
||||
/// that have yet to be published.
|
||||
/// </param>
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
///
|
||||
///
|
||||
/// This method becomes complex once we start to be able to cancel events or stop publishing a content item in any way because if a
|
||||
/// content item is not published then it's children shouldn't be published either. This rule will apply for the following conditions:
|
||||
/// * If a document fails to be published, do not proceed to publish it's children if:
|
||||
/// ** The document does not have a publish version
|
||||
/// ** The document does have a published version but the includeUnpublishedDocuments = false
|
||||
///
|
||||
///
|
||||
/// In order to do this, we will order the content by level and begin by publishing each item at that level, then proceed to the next
|
||||
/// level and so on. If we detect that the above rule applies when the document publishing is cancelled we'll add it to the list of
|
||||
/// level and so on. If we detect that the above rule applies when the document publishing is cancelled we'll add it to the list of
|
||||
/// parentsIdsCancelled so that it's children don't get published.
|
||||
///
|
||||
///
|
||||
/// Its important to note that all 'root' documents included in the list *will* be published regardless of the rules mentioned
|
||||
/// above (unless it is invalid)!! By 'root' documents we are referring to documents in the list with the minimum value for their 'level'.
|
||||
/// In most cases the 'root' documents will only be one document since under normal circumstance we only publish one document and
|
||||
/// above (unless it is invalid)!! By 'root' documents we are referring to documents in the list with the minimum value for their 'level'.
|
||||
/// In most cases the 'root' documents will only be one document since under normal circumstance we only publish one document and
|
||||
/// its children. The reason we have to do this is because if a user is publishing a document and it's children, it is implied that
|
||||
/// the user definitely wants to publish it even if it has never been published before.
|
||||
///
|
||||
///
|
||||
/// </remarks>
|
||||
internal IEnumerable<Attempt<PublishStatus>> PublishWithChildrenInternal(
|
||||
IEnumerable<IContent> content, int userId, bool includeUnpublishedDocuments = true)
|
||||
@@ -132,7 +132,7 @@ namespace Umbraco.Core.Publishing
|
||||
|
||||
//group by levels and iterate over the sorted ascending level.
|
||||
//TODO: This will cause all queries to execute, they will not be lazy but I'm not really sure being lazy actually made
|
||||
// much difference because we iterate over them all anyways?? Morten?
|
||||
// much difference because we iterate over them all anyways?? Morten?
|
||||
// Because we're grouping I think this will execute all the queries anyways so need to fetch it all first.
|
||||
var fetchedContent = content.ToArray();
|
||||
|
||||
@@ -149,7 +149,7 @@ namespace Umbraco.Core.Publishing
|
||||
var levelGroups = fetchedContent.GroupBy(x => x.Level);
|
||||
foreach (var level in levelGroups.OrderBy(x => x.Key))
|
||||
{
|
||||
//set the first level flag, used to ensure that all documents at the first level will
|
||||
//set the first level flag, used to ensure that all documents at the first level will
|
||||
//be published regardless of the rules mentioned in the remarks.
|
||||
if (!firstLevel.HasValue)
|
||||
{
|
||||
@@ -200,7 +200,10 @@ namespace Umbraco.Core.Publishing
|
||||
_logger.Info<PublishingStrategy>(
|
||||
string.Format("Content '{0}' with Id '{1}' will not be published because some of it's content is not passing validation rules.",
|
||||
item.Name, item.Id));
|
||||
statuses.Add(Attempt.Fail(new PublishStatus(item, PublishStatusType.FailedContentInvalid, evtMsgs)));
|
||||
statuses.Add(Attempt.Fail(new PublishStatus(item, PublishStatusType.FailedContentInvalid, evtMsgs)
|
||||
{
|
||||
InvalidProperties = ((ContentBase)item).LastInvalidProperties
|
||||
}));
|
||||
|
||||
//Does this document apply to our rule to cancel it's children being published?
|
||||
CheckCancellingOfChildPublishing(item, parentsIdsCancelled, includeUnpublishedDocuments);
|
||||
@@ -272,11 +275,11 @@ namespace Umbraco.Core.Publishing
|
||||
/// <param name="includeUnpublishedDocuments"></param>
|
||||
/// <remarks>
|
||||
/// See remarks on method: PublishWithChildrenInternal
|
||||
/// </remarks>
|
||||
/// </remarks>
|
||||
private void CheckCancellingOfChildPublishing(IContent content, List<int> parentsIdsCancelled, bool includeUnpublishedDocuments)
|
||||
{
|
||||
//Does this document apply to our rule to cancel it's children being published?
|
||||
//TODO: We're going back to the service layer here... not sure how to avoid this? And this will add extra overhead to
|
||||
//TODO: We're going back to the service layer here... not sure how to avoid this? And this will add extra overhead to
|
||||
// any document that fails to publish...
|
||||
var hasPublishedVersion = ApplicationContext.Current.Services.ContentService.HasPublishedVersion(content.Id);
|
||||
|
||||
@@ -306,8 +309,8 @@ namespace Umbraco.Core.Publishing
|
||||
//NOTE: This previously always returned true so I've left it that way. It returned true because (from Morten)...
|
||||
// ... if one item couldn't be published it wouldn't be correct to return false.
|
||||
// in retrospect it should have returned a list of with Ids and Publish Status
|
||||
// come to think of it ... the cache would still be updated for a failed item or at least tried updated.
|
||||
// It would call the Published event for the entire list, but if the Published property isn't set to True it
|
||||
// come to think of it ... the cache would still be updated for a failed item or at least tried updated.
|
||||
// It would call the Published event for the entire list, but if the Published property isn't set to True it
|
||||
// wouldn't actually update the cache for that item. But not really ideal nevertheless...
|
||||
return true;
|
||||
}
|
||||
@@ -345,7 +348,7 @@ namespace Umbraco.Core.Publishing
|
||||
var evtMsgs = _eventMessagesFactory.Get();
|
||||
|
||||
//Fire UnPublishing event
|
||||
if (UnPublishing.IsRaisedEventCancelled(
|
||||
if (UnPublishing.IsRaisedEventCancelled(
|
||||
new PublishEventArgs<IContent>(content, evtMsgs), this))
|
||||
{
|
||||
_logger.Info<PublishingStrategy>(
|
||||
@@ -388,8 +391,8 @@ namespace Umbraco.Core.Publishing
|
||||
//NOTE: This previously always returned true so I've left it that way. It returned true because (from Morten)...
|
||||
// ... if one item couldn't be published it wouldn't be correct to return false.
|
||||
// in retrospect it should have returned a list of with Ids and Publish Status
|
||||
// come to think of it ... the cache would still be updated for a failed item or at least tried updated.
|
||||
// It would call the Published event for the entire list, but if the Published property isn't set to True it
|
||||
// come to think of it ... the cache would still be updated for a failed item or at least tried updated.
|
||||
// It would call the Published event for the entire list, but if the Published property isn't set to True it
|
||||
// wouldn't actually update the cache for that item. But not really ideal nevertheless...
|
||||
return true;
|
||||
}
|
||||
@@ -405,7 +408,7 @@ namespace Umbraco.Core.Publishing
|
||||
public override void PublishingFinalized(IContent content)
|
||||
{
|
||||
var evtMsgs = _eventMessagesFactory.Get();
|
||||
Published.RaiseEvent(
|
||||
Published.RaiseEvent(
|
||||
new PublishEventArgs<IContent>(content, false, false, evtMsgs), this);
|
||||
}
|
||||
|
||||
|
||||
@@ -874,18 +874,15 @@ namespace umbraco.cms.businesslogic.web
|
||||
[Obsolete("Don't use! Only used internally to support the legacy events", false)]
|
||||
internal IEnumerable<Attempt<PublishStatus>> PublishWithSubs(int userId, bool includeUnpublished)
|
||||
{
|
||||
PublishEventArgs e = new PublishEventArgs();
|
||||
var e = new PublishEventArgs();
|
||||
FireBeforePublish(e);
|
||||
|
||||
IEnumerable<Attempt<PublishStatus>> publishedResults = Enumerable.Empty<Attempt<PublishStatus>>();
|
||||
if (e.Cancel) return Enumerable.Empty<Attempt<PublishStatus>>();
|
||||
|
||||
if (!e.Cancel)
|
||||
{
|
||||
publishedResults = ApplicationContext.Current.Services.ContentService
|
||||
.PublishWithChildrenWithStatus(ContentEntity, userId, includeUnpublished);
|
||||
var publishedResults = ApplicationContext.Current.Services.ContentService
|
||||
.PublishWithChildrenWithStatus(ContentEntity, userId, includeUnpublished);
|
||||
|
||||
FireAfterPublish(e);
|
||||
}
|
||||
FireAfterPublish(e);
|
||||
|
||||
return publishedResults;
|
||||
}
|
||||
@@ -893,7 +890,6 @@ namespace umbraco.cms.businesslogic.web
|
||||
[Obsolete("Don't use! Only used internally to support the legacy events", false)]
|
||||
internal Attempt<PublishStatus> SaveAndPublish(int userId)
|
||||
{
|
||||
var result = Attempt.Fail(new PublishStatus(ContentEntity, PublishStatusType.FailedCancelledByEvent, new EventMessages()));
|
||||
foreach (var property in GenericProperties)
|
||||
{
|
||||
ContentEntity.SetValue(property.PropertyType.Alias, property.Value);
|
||||
@@ -901,32 +897,28 @@ namespace umbraco.cms.businesslogic.web
|
||||
|
||||
var saveArgs = new SaveEventArgs();
|
||||
FireBeforeSave(saveArgs);
|
||||
if (saveArgs.Cancel) return Attempt.Fail(new PublishStatus(ContentEntity, PublishStatusType.FailedCancelledByEvent, new EventMessages()));
|
||||
|
||||
if (!saveArgs.Cancel)
|
||||
{
|
||||
var publishArgs = new PublishEventArgs();
|
||||
FireBeforePublish(publishArgs);
|
||||
var publishArgs = new PublishEventArgs();
|
||||
FireBeforePublish(publishArgs);
|
||||
if (publishArgs.Cancel) return Attempt.Fail(new PublishStatus(ContentEntity, PublishStatusType.FailedCancelledByEvent, new EventMessages()));
|
||||
|
||||
if (!publishArgs.Cancel)
|
||||
{
|
||||
//NOTE: The 'false' parameter will cause the PublishingStrategy events to fire which will ensure that the cache is refreshed.
|
||||
result = ApplicationContext.Current.Services.ContentService
|
||||
.SaveAndPublishWithStatus(ContentEntity, userId);
|
||||
base.VersionDate = ContentEntity.UpdateDate;
|
||||
this.UpdateDate = ContentEntity.UpdateDate;
|
||||
//NOTE: The 'false' parameter will cause the PublishingStrategy events to fire which will ensure that the cache is refreshed.
|
||||
var result = ApplicationContext.Current.Services.ContentService
|
||||
.SaveAndPublishWithStatus(ContentEntity, userId);
|
||||
VersionDate = ContentEntity.UpdateDate;
|
||||
UpdateDate = ContentEntity.UpdateDate;
|
||||
|
||||
//NOTE: This is just going to call the CMSNode Save which will launch into the CMSNode.BeforeSave and CMSNode.AfterSave evenths
|
||||
// which actually do dick all and there's no point in even having them there but just in case for some insane reason someone
|
||||
// has bound to those events, I suppose we'll need to keep this here.
|
||||
base.Save();
|
||||
//NOTE: This is just going to call the CMSNode Save which will launch into the CMSNode.BeforeSave and CMSNode.AfterSave evenths
|
||||
// which actually do dick all and there's no point in even having them there but just in case for some insane reason someone
|
||||
// has bound to those events, I suppose we'll need to keep this here.
|
||||
base.Save();
|
||||
|
||||
//Launch the After Save event since we're doing 2 things in one operation: Saving and publishing.
|
||||
FireAfterSave(saveArgs);
|
||||
//Launch the After Save event since we're doing 2 things in one operation: Saving and publishing.
|
||||
FireAfterSave(saveArgs);
|
||||
|
||||
//Now we need to fire the After publish event
|
||||
FireAfterPublish(publishArgs);
|
||||
}
|
||||
}
|
||||
//Now we need to fire the After publish event
|
||||
FireAfterPublish(publishArgs);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user