Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.ViewModels.Document;
using Umbraco.Cms.Core.Models.ContentEditing;
using Umbraco.Cms.Core.Models.ContentEditing.Validation;
using Umbraco.Cms.Core.Models.ContentPublishing;
using Umbraco.Cms.Core.PropertyEditors.Validation;
using Umbraco.Cms.Core.Services.OperationStatus;
using Umbraco.Extensions;
Expand Down Expand Up @@ -106,6 +108,122 @@
.Build()),
});

protected IActionResult ContentPublishingOperationStatusResult(
ContentPublishingOperationStatus status,
IEnumerable<string>? invalidPropertyAliases = null,
IEnumerable<ContentPublishingBranchItemResult>? failedBranchItems = null)
=> OperationStatusResult(
status,
problemDetailsBuilder => status switch
{
ContentPublishingOperationStatus.ContentNotFound => NotFound(problemDetailsBuilder
.WithTitle("The requested document could not be found")
.Build()),
ContentPublishingOperationStatus.CancelledByEvent => BadRequest(problemDetailsBuilder
.WithTitle("Publish cancelled by event")
.WithDetail("The publish operation was cancelled by an event.")
.Build()),
ContentPublishingOperationStatus.ContentInvalid => BadRequest(problemDetailsBuilder
.WithTitle("Invalid document")
.WithDetail("The specified document had an invalid configuration.")
.WithExtension("invalidProperties", invalidPropertyAliases ?? Enumerable.Empty<string>())
.Build()),
ContentPublishingOperationStatus.NothingToPublish => BadRequest(problemDetailsBuilder
.WithTitle("Nothing to publish")
.WithDetail("None of the specified cultures needed publishing.")
.Build()),
ContentPublishingOperationStatus.MandatoryCultureMissing => BadRequest(problemDetailsBuilder
.WithTitle("Mandatory culture missing")
.WithDetail("Must include all mandatory cultures when publishing.")
.Build()),
ContentPublishingOperationStatus.HasExpired => BadRequest(problemDetailsBuilder
.WithTitle("Document expired")
.WithDetail("Could not publish the document because it was expired.")
.Build()),
ContentPublishingOperationStatus.CultureHasExpired => BadRequest(problemDetailsBuilder
.WithTitle("Document culture expired")
.WithDetail("Could not publish the document because some of the specified cultures were expired.")
.Build()),
ContentPublishingOperationStatus.AwaitingRelease => BadRequest(problemDetailsBuilder
.WithTitle("Document awaiting release")
.WithDetail("Could not publish the document because it was awaiting release.")
.Build()),
ContentPublishingOperationStatus.CultureAwaitingRelease => BadRequest(problemDetailsBuilder
.WithTitle("Document culture awaiting release")
.WithDetail(
"Could not publish the document because some of the specified cultures were awaiting release.")
.Build()),
ContentPublishingOperationStatus.InTrash => BadRequest(problemDetailsBuilder
.WithTitle("Document in the recycle bin")
.WithDetail("Could not publish the document because it was in the recycle bin.")
.Build()),
ContentPublishingOperationStatus.PathNotPublished => BadRequest(problemDetailsBuilder
.WithTitle("Parent not published")
.WithDetail("Could not publish the document because its parent was not published.")
.Build()),
ContentPublishingOperationStatus.InvalidCulture => BadRequest(problemDetailsBuilder
.WithTitle("Invalid cultures specified")
.WithDetail("A specified culture is not valid for the operation.")
.Build()),
ContentPublishingOperationStatus.CultureMissing => BadRequest(problemDetailsBuilder
.WithTitle("Culture missing")
.WithDetail("A culture needs to be specified to execute the operation.")
.Build()),
ContentPublishingOperationStatus.CannotPublishInvariantWhenVariant => BadRequest(problemDetailsBuilder
.WithTitle("Cannot publish invariant when variant")
.WithDetail("Cannot publish invariant culture when the document varies by culture.")
.Build()),
ContentPublishingOperationStatus.CannotPublishVariantWhenNotVariant => BadRequest(problemDetailsBuilder
.WithTitle("Cannot publish variant when not variant.")
.WithDetail("Cannot publish a given culture when the document is invariant.")
.Build()),
ContentPublishingOperationStatus.ConcurrencyViolation => BadRequest(problemDetailsBuilder
.WithTitle("Concurrency violation detected")
.WithDetail("An attempt was made to publish a version older than the latest version.")
.Build()),
ContentPublishingOperationStatus.UnsavedChanges => BadRequest(problemDetailsBuilder
.WithTitle("Unsaved changes")
.WithDetail(
"Could not publish the document because it had unsaved changes. Make sure to save all changes before attempting a publish.")
.Build()),
ContentPublishingOperationStatus.UnpublishTimeNeedsToBeAfterPublishTime => BadRequest(problemDetailsBuilder
.WithTitle("Unpublish time needs to be after the publish time")
.WithDetail(
"Cannot handle an unpublish time that is not after the specified publish time.")
.Build()),
ContentPublishingOperationStatus.PublishTimeNeedsToBeInFuture => BadRequest(problemDetailsBuilder
.WithTitle("Publish time needs to be higher than the current time")
.WithDetail(
"Cannot handle a publish time that is not after the current server time.")
.Build()),
ContentPublishingOperationStatus.UpublishTimeNeedsToBeInFuture => BadRequest(problemDetailsBuilder
.WithTitle("Unpublish time needs to be higher than the current time")
.WithDetail(
"Cannot handle an unpublish time that is not after the current server time.")
.Build()),
ContentPublishingOperationStatus.CannotUnpublishWhenReferenced => BadRequest(problemDetailsBuilder
.WithTitle("Cannot unpublish document when it's referenced somewhere else.")
.WithDetail(
"Cannot unpublish a referenced document, while the setting ContentSettings.DisableUnpublishWhenReferenced is enabled.")
.Build()),
ContentPublishingOperationStatus.FailedBranch => BadRequest(problemDetailsBuilder
.WithTitle("Failed branch operation")
.WithDetail("One or more items in the branch could not complete the operation.")
.WithExtension("failedBranchItems", failedBranchItems?.Select(item => new DocumentPublishBranchItemResult { Id = item.Key, OperationStatus = item.OperationStatus }) ?? [])
.Build()),
ContentPublishingOperationStatus.Failed => BadRequest(
problemDetailsBuilder
.WithTitle("Publish or unpublish failed")
.WithDetail(
"An unspecified error occurred while (un)publishing. Please check the logs for additional information.")
.Build()),
ContentPublishingOperationStatus.TaskResultNotFound => NotFound(problemDetailsBuilder
.WithTitle("The result of the submitted task could not be found")
.Build()),

_ => StatusCode(StatusCodes.Status500InternalServerError, "Unknown content operation status."),
});

Check warning on line 225 in src/Umbraco.Cms.Api.Management/Controllers/Content/ContentControllerBase.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (v18/dev)

❌ New issue: Large Method

ContentPublishingOperationStatusResult has 114 lines, threshold = 70. Large functions with many lines of code are generally harder to understand and lower the code health. Avoid adding more lines to this function.

protected IActionResult ContentEditingOperationStatusResult<TContentModelBase, TValueModel, TVariantModel>(
ContentEditingOperationStatus status,
TContentModelBase requestModel,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,123 +30,11 @@
where TContentModelBase : ContentModelBase<DocumentValueModel, DocumentVariantRequestModel>
=> ContentEditingOperationStatusResult<TContentModelBase, DocumentValueModel, DocumentVariantRequestModel>(status, requestModel, validationResult);

// TODO ELEMENTS: move this to ContentControllerBase
protected IActionResult DocumentPublishingOperationStatusResult(
ContentPublishingOperationStatus status,
IEnumerable<string>? invalidPropertyAliases = null,
IEnumerable<ContentPublishingBranchItemResult>? failedBranchItems = null)
=> OperationStatusResult(status, problemDetailsBuilder => status switch
{
ContentPublishingOperationStatus.ContentNotFound => NotFound(problemDetailsBuilder
.WithTitle("The requested document could not be found")
.Build()),
ContentPublishingOperationStatus.CancelledByEvent => BadRequest(problemDetailsBuilder
.WithTitle("Publish cancelled by event")
.WithDetail("The publish operation was cancelled by an event.")
.Build()),
ContentPublishingOperationStatus.ContentInvalid => BadRequest(problemDetailsBuilder
.WithTitle("Invalid document")
.WithDetail("The specified document had an invalid configuration.")
.WithExtension("invalidProperties", invalidPropertyAliases ?? Enumerable.Empty<string>())
.Build()),
ContentPublishingOperationStatus.NothingToPublish => BadRequest(problemDetailsBuilder
.WithTitle("Nothing to publish")
.WithDetail("None of the specified cultures needed publishing.")
.Build()),
ContentPublishingOperationStatus.MandatoryCultureMissing => BadRequest(problemDetailsBuilder
.WithTitle("Mandatory culture missing")
.WithDetail("Must include all mandatory cultures when publishing.")
.Build()),
ContentPublishingOperationStatus.HasExpired => BadRequest(problemDetailsBuilder
.WithTitle("Document expired")
.WithDetail("Could not publish the document because it was expired.")
.Build()),
ContentPublishingOperationStatus.CultureHasExpired => BadRequest(problemDetailsBuilder
.WithTitle("Document culture expired")
.WithDetail("Could not publish the document because some of the specified cultures were expired.")
.Build()),
ContentPublishingOperationStatus.AwaitingRelease => BadRequest(problemDetailsBuilder
.WithTitle("Document awaiting release")
.WithDetail("Could not publish the document because it was awaiting release.")
.Build()),
ContentPublishingOperationStatus.CultureAwaitingRelease => BadRequest(problemDetailsBuilder
.WithTitle("Document culture awaiting release")
.WithDetail(
"Could not publish the document because some of the specified cultures were awaiting release.")
.Build()),
ContentPublishingOperationStatus.InTrash => BadRequest(problemDetailsBuilder
.WithTitle("Document in the recycle bin")
.WithDetail("Could not publish the document because it was in the recycle bin.")
.Build()),
ContentPublishingOperationStatus.PathNotPublished => BadRequest(problemDetailsBuilder
.WithTitle("Parent not published")
.WithDetail("Could not publish the document because its parent was not published.")
.Build()),
ContentPublishingOperationStatus.InvalidCulture => BadRequest(problemDetailsBuilder
.WithTitle("Invalid cultures specified")
.WithDetail("A specified culture is not valid for the operation.")
.Build()),
ContentPublishingOperationStatus.CultureMissing => BadRequest(problemDetailsBuilder
.WithTitle("Culture missing")
.WithDetail("A culture needs to be specified to execute the operation.")
.Build()),
ContentPublishingOperationStatus.CannotPublishInvariantWhenVariant => BadRequest(problemDetailsBuilder
.WithTitle("Cannot publish invariant when variant")
.WithDetail("Cannot publish invariant culture when the document varies by culture.")
.Build()),
ContentPublishingOperationStatus.CannotPublishVariantWhenNotVariant => BadRequest(problemDetailsBuilder
.WithTitle("Cannot publish variant when not variant.")
.WithDetail("Cannot publish a given culture when the document is invariant.")
.Build()),
ContentPublishingOperationStatus.ConcurrencyViolation => BadRequest(problemDetailsBuilder
.WithTitle("Concurrency violation detected")
.WithDetail("An attempt was made to publish a version older than the latest version.")
.Build()),
ContentPublishingOperationStatus.UnsavedChanges => BadRequest(problemDetailsBuilder
.WithTitle("Unsaved changes")
.WithDetail(
"Could not publish the document because it had unsaved changes. Make sure to save all changes before attempting a publish.")
.Build()),
ContentPublishingOperationStatus.UnpublishTimeNeedsToBeAfterPublishTime => BadRequest(problemDetailsBuilder
.WithTitle("Unpublish time needs to be after the publish time")
.WithDetail(
"Cannot handle an unpublish time that is not after the specified publish time.")
.Build()),
ContentPublishingOperationStatus.PublishTimeNeedsToBeInFuture => BadRequest(problemDetailsBuilder
.WithTitle("Publish time needs to be higher than the current time")
.WithDetail(
"Cannot handle a publish time that is not after the current server time.")
.Build()),
ContentPublishingOperationStatus.UpublishTimeNeedsToBeInFuture => BadRequest(problemDetailsBuilder
.WithTitle("Unpublish time needs to be higher than the current time")
.WithDetail(
"Cannot handle an unpublish time that is not after the current server time.")
.Build()),
ContentPublishingOperationStatus.CannotUnpublishWhenReferenced => BadRequest(problemDetailsBuilder
.WithTitle("Cannot unpublish document when it's referenced somewhere else.")
.WithDetail(
"Cannot unpublish a referenced document, while the setting ContentSettings.DisableUnpublishWhenReferenced is enabled.")
.Build()),
ContentPublishingOperationStatus.FailedBranch => BadRequest(problemDetailsBuilder
.WithTitle("Failed branch operation")
.WithDetail("One or more items in the branch could not complete the operation.")
.WithExtension("failedBranchItems", failedBranchItems?.Select(item => new DocumentPublishBranchItemResult
{
Id = item.Key,
OperationStatus = item.OperationStatus
}) ?? Enumerable.Empty<DocumentPublishBranchItemResult>())
.Build()),
ContentPublishingOperationStatus.Failed => BadRequest(problemDetailsBuilder
.WithTitle("Publish or unpublish failed")
.WithDetail(
"An unspecified error occurred while (un)publishing. Please check the logs for additional information.")
.Build()),
ContentPublishingOperationStatus.TaskResultNotFound => NotFound(problemDetailsBuilder
.WithTitle("The result of the submitted task could not be found")
.Build()),

_ => StatusCode(StatusCodes.Status500InternalServerError, "Unknown content operation status."),
});
=> ContentPublishingOperationStatusResult(status, invalidPropertyAliases, failedBranchItems);

Check notice on line 37 in src/Umbraco.Cms.Api.Management/Controllers/Document/DocumentControllerBase.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (v18/dev)

✅ No longer an issue: Large Method

DocumentPublishingOperationStatusResult is no longer above the threshold for lines of code

protected IActionResult PublicAccessOperationStatusResult(PublicAccessOperationStatus status)
=> OperationStatusResult(status, problemDetailsBuilder => status switch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Umbraco.Cms.Api.Management.ViewModels.Element;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models.ContentEditing;
using Umbraco.Cms.Core.Models.ContentPublishing;
using Umbraco.Cms.Core.Services.OperationStatus;
using Umbraco.Cms.Web.Common.Authorization;

Expand All @@ -21,4 +22,10 @@ protected IActionResult ElementEditingOperationStatusResult<TContentModelBase>(
ContentValidationResult validationResult)
where TContentModelBase : ContentModelBase<ElementValueModel, ElementVariantRequestModel>
=> ContentEditingOperationStatusResult<TContentModelBase, ElementValueModel, ElementVariantRequestModel>(status, requestModel, validationResult);

protected IActionResult ElementPublishingOperationStatusResult(
ContentPublishingOperationStatus status,
IEnumerable<string>? invalidPropertyAliases = null,
IEnumerable<ContentPublishingBranchItemResult>? failedBranchItems = null)
=> ContentPublishingOperationStatusResult(status, invalidPropertyAliases, failedBranchItems);
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,7 @@ public async Task<IActionResult> Publish(CancellationToken cancellationToken, Gu

if (modelResult.Success is false)
{
// TODO ELEMENTS: use refactored DocumentPublishingOperationStatusResult from DocumentControllerBase once it's ready
return BadRequest();
return ElementPublishingOperationStatusResult(modelResult.Status);
}

Attempt<ContentPublishingResult, ContentPublishingOperationStatus> attempt = await _elementPublishingService.PublishAsync(
Expand All @@ -75,7 +74,6 @@ public async Task<IActionResult> Publish(CancellationToken cancellationToken, Gu
CurrentUserKey(_backOfficeSecurityAccessor));
return attempt.Success
? Ok()
// TODO ELEMENTS: use refactored DocumentPublishingOperationStatusResult from DocumentControllerBase once it's ready
: BadRequest();
: ElementPublishingOperationStatusResult(attempt.Status, attempt.Result.InvalidPropertyAliases);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ public async Task<IActionResult> Unpublish(CancellationToken cancellationToken,
CurrentUserKey(_backOfficeSecurityAccessor));
return attempt.Success
? Ok()
// TODO ELEMENTS: use refactored DocumentPublishingOperationStatusResult from DocumentControllerBase once it's ready
: BadRequest();
: ElementPublishingOperationStatusResult(attempt.Result);
}
}
Loading
Loading