Skip to content

Commit d2707ac

Browse files
V14: Create seperate Create and Update in ContentTypeServiceBase (#16714)
* Create seperate Create and Update in ContentTypeServiceBase * Fix up notification for update --------- Co-authored-by: nikolajlauridsen <[email protected]>
1 parent d170193 commit d2707ac

File tree

5 files changed

+110
-7
lines changed

5 files changed

+110
-7
lines changed

src/Umbraco.Cms.Api.Management/Controllers/DocumentType/DocumentTypeControllerBase.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,18 @@ status is ContentTypeOperationStatus.Success
8686
.WithTitle("Operation not permitted")
8787
.WithDetail("The attempted operation was not permitted, likely due to a permission/configuration mismatch with the operation.")
8888
.Build()),
89+
ContentTypeOperationStatus.CancelledByNotification => new BadRequestObjectResult(problemDetailsBuilder
90+
.WithTitle("Cancelled by notification")
91+
.WithDetail("The attempted operation was cancelled by a notification.")
92+
.Build()),
93+
ContentTypeOperationStatus.NameCannotBeEmpty => new BadRequestObjectResult(problemDetailsBuilder
94+
.WithTitle("Name cannot be empty")
95+
.WithDetail("The name of the content type cannot be empty")
96+
.Build()),
97+
ContentTypeOperationStatus.NameTooLong => new BadRequestObjectResult(problemDetailsBuilder
98+
.WithTitle("Name was too long")
99+
.WithDetail("Name cannot be more than 255 characters in length.")
100+
.Build()),
89101
_ => new ObjectResult("Unknown content type operation status") { StatusCode = StatusCodes.Status500InternalServerError },
90102
});
91103

src/Umbraco.Core/Services/ContentTypeEditing/ContentTypeEditingService.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,12 @@ public ContentTypeEditingService(
4040
UpdateTemplates(contentType, model);
4141

4242
// save content type
43-
await SaveAsync(contentType, userKey);
43+
Attempt<ContentTypeOperationStatus> creationAttempt = await _contentTypeService.CreateAsync(contentType, userKey);
44+
45+
if(creationAttempt.Success is false)
46+
{
47+
return Attempt.FailWithStatus<IContentType?, ContentTypeOperationStatus>(creationAttempt.Result, contentType);
48+
}
4449

4550
return Attempt.SucceedWithStatus<IContentType?, ContentTypeOperationStatus>(ContentTypeOperationStatus.Success, contentType);
4651
}
@@ -58,9 +63,11 @@ public ContentTypeEditingService(
5863
UpdateHistoryCleanup(contentType, model);
5964
UpdateTemplates(contentType, model);
6065

61-
await SaveAsync(contentType, userKey);
66+
Attempt<ContentTypeOperationStatus> attempt = await _contentTypeService.UpdateAsync(contentType, userKey);
6267

63-
return Attempt.SucceedWithStatus<IContentType?, ContentTypeOperationStatus>(ContentTypeOperationStatus.Success, contentType);
68+
return attempt.Success
69+
? Attempt.SucceedWithStatus<IContentType?, ContentTypeOperationStatus>(ContentTypeOperationStatus.Success, contentType)
70+
: Attempt.FailWithStatus<IContentType?, ContentTypeOperationStatus>(attempt.Result, null);
6471
}
6572

6673
public async Task<IEnumerable<ContentTypeAvailableCompositionsResult>> GetAvailableCompositionsAsync(
@@ -93,9 +100,6 @@ private void UpdateTemplates(IContentType contentType, ContentTypeModelBase mode
93100
contentType.SetDefaultTemplate(allowedTemplates.FirstOrDefault(t => t.Key == model.DefaultTemplateKey));
94101
}
95102

96-
private async Task SaveAsync(IContentType contentType, Guid userKey)
97-
=> await _contentTypeService.SaveAsync(contentType, userKey);
98-
99103
protected override IContentType CreateContentType(IShortStringHelper shortStringHelper, int parentId)
100104
=> new ContentType(shortStringHelper, parentId);
101105

src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,75 @@ public void Save(IEnumerable<TItem> items, int userId = Constants.Security.Super
603603
}
604604
}
605605

606+
public async Task<Attempt<ContentTypeOperationStatus>> CreateAsync(TItem item, Guid performingUserKey) => await InternalSaveAsync(item, performingUserKey);
607+
608+
public async Task<Attempt<ContentTypeOperationStatus>> UpdateAsync(TItem item, Guid performingUserKey) => await InternalSaveAsync(item, performingUserKey);
609+
610+
private async Task<Attempt<ContentTypeOperationStatus>> InternalSaveAsync(TItem item, Guid performingUserKey)
611+
{
612+
using ICoreScope scope = ScopeProvider.CreateCoreScope();
613+
EventMessages eventMessages = EventMessagesFactory.Get();
614+
615+
Attempt<ContentTypeOperationStatus> validationAttempt = ValidateCommon(item);
616+
if (validationAttempt.Success is false)
617+
{
618+
return Attempt.Fail(validationAttempt.Result);
619+
}
620+
621+
SavingNotification<TItem> savingNotification = GetSavingNotification(item, eventMessages);
622+
if (await scope.Notifications.PublishCancelableAsync(savingNotification))
623+
{
624+
scope.Complete();
625+
return Attempt.Fail(ContentTypeOperationStatus.CancelledByNotification);
626+
}
627+
628+
scope.WriteLock(WriteLockIds);
629+
630+
// validate the DAG transform, within the lock
631+
ValidateLocked(item); // throws if invalid
632+
633+
int userId = await _userIdKeyResolver.GetAsync(performingUserKey);
634+
item.CreatorId = userId;
635+
if (item.Description == string.Empty)
636+
{
637+
item.Description = null;
638+
}
639+
640+
Repository.Save(item); // also updates content/media/member items
641+
642+
// figure out impacted content types
643+
ContentTypeChange<TItem>[] changes = ComposeContentTypeChanges(item).ToArray();
644+
645+
// Publish this in scope, see comment at GetContentTypeRefreshedNotification for more info.
646+
await _eventAggregator.PublishAsync(GetContentTypeRefreshedNotification(changes, eventMessages));
647+
648+
scope.Notifications.Publish(GetContentTypeChangedNotification(changes, eventMessages));
649+
650+
SavedNotification<TItem> savedNotification = GetSavedNotification(item, eventMessages);
651+
savedNotification.WithStateFrom(savingNotification);
652+
scope.Notifications.Publish(savedNotification);
653+
654+
Audit(AuditType.Save, userId, item.Id);
655+
scope.Complete();
656+
657+
return Attempt.Succeed(ContentTypeOperationStatus.Success);
658+
}
659+
660+
private Attempt<ContentTypeOperationStatus> ValidateCommon(TItem item)
661+
{
662+
if (string.IsNullOrWhiteSpace(item.Name))
663+
{
664+
return Attempt.Fail(ContentTypeOperationStatus.NameCannotBeEmpty);
665+
}
666+
667+
if (item.Name.Length > 255)
668+
{
669+
return Attempt.Fail(ContentTypeOperationStatus.NameTooLong);
670+
}
671+
672+
return Attempt.Succeed(ContentTypeOperationStatus.Success);
673+
}
674+
606675
#endregion
607676

608677
#region Delete

src/Umbraco.Core/Services/IContentTypeServiceBase.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,16 +67,31 @@ public interface IContentTypeBaseService<TItem> : IContentTypeBaseService, IServ
6767

6868
bool HasChildren(Guid id);
6969

70+
[Obsolete("Please use the respective Create or Update instead")]
7071
void Save(TItem? item, int userId = Constants.Security.SuperUserId);
7172

73+
[Obsolete("Please use the respective Create or Update instead")]
7274
Task SaveAsync(TItem item, Guid performingUserKey)
7375
{
7476
Save(item);
7577
return Task.CompletedTask;
7678
}
7779

80+
[Obsolete("Please use the respective Create or Update instead")]
7881
void Save(IEnumerable<TItem> items, int userId = Constants.Security.SuperUserId);
7982

83+
Task<Attempt<ContentTypeOperationStatus>> CreateAsync(TItem item, Guid performingUserKey)
84+
{
85+
Save(item);
86+
return Task.FromResult(Attempt.Succeed(ContentTypeOperationStatus.Success));
87+
}
88+
89+
Task<Attempt<ContentTypeOperationStatus>> UpdateAsync(TItem item, Guid performingUserKey)
90+
{
91+
Save(item);
92+
return Task.FromResult(Attempt.Succeed(ContentTypeOperationStatus.Success));
93+
}
94+
8095
void Delete(TItem item, int userId = Constants.Security.SuperUserId);
8196

8297
/// <summary>

src/Umbraco.Core/Services/OperationStatus/ContentTypeOperationStatus.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ public enum ContentTypeOperationStatus
55
Success,
66
DuplicateAlias,
77
InvalidAlias,
8+
NameCannotBeEmpty,
9+
NameTooLong,
810
InvalidPropertyTypeAlias,
911
PropertyTypeAliasCannotEqualContentTypeAlias,
1012
DuplicatePropertyTypeAlias,
@@ -17,5 +19,6 @@ public enum ContentTypeOperationStatus
1719
MissingContainer,
1820
DuplicateContainer,
1921
NotFound,
20-
NotAllowed
22+
NotAllowed,
23+
CancelledByNotification,
2124
}

0 commit comments

Comments
 (0)