diff --git a/src/Umbraco.Core/Services/Implement/ContentService.cs b/src/Umbraco.Core/Services/Implement/ContentService.cs index be9dee5d15..b1ff14899c 100644 --- a/src/Umbraco.Core/Services/Implement/ContentService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentService.cs @@ -1510,7 +1510,7 @@ namespace Umbraco.Core.Services.Implement var moveEventInfo = new MoveEventInfo(content, content.Path, parentId); var moveEventArgs = new MoveEventArgs(moveEventInfo); - if (scope.Events.DispatchCancelable(Moving, this, moveEventArgs)) + if (scope.Events.DispatchCancelable(Moving, this, moveEventArgs, nameof(Moving))) { scope.Complete(); return; // causes rollback @@ -1541,7 +1541,7 @@ namespace Umbraco.Core.Services.Implement moveEventArgs.MoveInfoCollection = moveInfo; moveEventArgs.CanCancel = false; - scope.Events.Dispatch(Moved, this, moveEventArgs); + scope.Events.Dispatch(Moved, this, moveEventArgs, nameof(Moved)); Audit(AuditType.Move, "Move Content performed by user", userId, content.Id); scope.Complete(); @@ -2249,7 +2249,7 @@ namespace Umbraco.Core.Services.Implement // but... UnPublishing event makes no sense (not going to cancel?) and no need to save // just raise the event if (content.Trashed == false && content.Published) - scope.Events.Dispatch(UnPublished, this, new PublishEventArgs(content, false, false), "UnPublished"); + scope.Events.Dispatch(UnPublished, this, new PublishEventArgs(content, false, false), nameof(UnPublished)); // if current content has children, move them to trash var c = content; @@ -2272,7 +2272,7 @@ namespace Umbraco.Core.Services.Implement .Select(x => new MoveEventInfo(x.Item1, x.Item2, x.Item1.ParentId)) .ToArray(); if (moveInfos.Length > 0) - scope.Events.Dispatch(Trashed, this, new MoveEventArgs(false, moveInfos), "Trashed"); + scope.Events.Dispatch(Trashed, this, new MoveEventArgs(false, moveInfos), nameof(Trashed)); scope.Events.Dispatch(TreeChanged, this, changes.ToEventArgs()); Audit(AuditType.Delete, $"Delete Content of Type {string.Join(",", contentTypeIdsA)} performed by user", userId, Constants.System.Root); diff --git a/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTItemTService.cs b/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTItemTService.cs index f02441eba0..9fa9a47003 100644 --- a/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTItemTService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTItemTService.cs @@ -39,12 +39,10 @@ namespace Umbraco.Core.Services.Implement public static event TypedEventHandler> SavedContainer; public static event TypedEventHandler> DeletingContainer; public static event TypedEventHandler> DeletedContainer; - - // fixme - can we have issues with event names? - + protected void OnChanged(IScope scope, ContentTypeChange.EventArgs args) { - scope.Events.Dispatch(Changed, This, args, "Changed"); + scope.Events.Dispatch(Changed, This, args, nameof(Changed)); } protected void OnUowRefreshedEntity(ContentTypeChange.EventArgs args) @@ -52,13 +50,7 @@ namespace Umbraco.Core.Services.Implement // that one is always immediate (not dispatched, transactional) UowRefreshedEntity.RaiseEvent(args, This); } - - // fixme what is thsi? - protected void OnSaving(IScope scope, SaveEventArgs args) - { - Saving.RaiseEvent(args, This); - } - + protected bool OnSavingCancelled(IScope scope, SaveEventArgs args) { return scope.Events.DispatchCancelable(Saving, This, args); @@ -68,29 +60,17 @@ namespace Umbraco.Core.Services.Implement { scope.Events.Dispatch(Saved, This, args); } - - // fixme what is thsi? - protected void OnDeleting(IScope scope, DeleteEventArgs args) - { - Deleting.RaiseEvent(args, This); - } - + protected bool OnDeletingCancelled(IScope scope, DeleteEventArgs args) { - return scope.Events.DispatchCancelable(Deleting, This, args); + return scope.Events.DispatchCancelable(Deleting, This, args, nameof(Deleting)); } - + protected void OnDeleted(IScope scope, DeleteEventArgs args) { scope.Events.Dispatch(Deleted, This, args); } - - // fixme what is thsi? - protected void OnMoving(IScope scope, MoveEventArgs args) - { - Moving.RaiseEvent(args, This); - } - + protected bool OnMovingCancelled(IScope scope, MoveEventArgs args) { return scope.Events.DispatchCancelable(Moving, This, args); @@ -100,35 +80,27 @@ namespace Umbraco.Core.Services.Implement { scope.Events.Dispatch(Moved, This, args); } - - // fixme what is this? - protected void OnSavingContainer(IScope scope, SaveEventArgs args) - { - SavingContainer.RaiseEvent(args, This); - } - + protected bool OnSavingContainerCancelled(IScope scope, SaveEventArgs args) { - return scope.Events.DispatchCancelable(SavingContainer, This, args); + return scope.Events.DispatchCancelable(SavingContainer, This, args, nameof(SavingContainer)); } protected void OnSavedContainer(IScope scope, SaveEventArgs args) { - scope.Events.DispatchCancelable(SavedContainer, This, args); + scope.Events.Dispatch(SavedContainer, This, args); + } + + protected bool OnRenamingContainerCancelled(IScope scope, SaveEventArgs args) + { + return scope.Events.DispatchCancelable(SavedContainer, This, args, nameof(SavedContainer)); } protected void OnRenamedContainer(IScope scope, SaveEventArgs args) { - // fixme changing the name of the event?! - scope.Events.DispatchCancelable(SavedContainer, This, args, "RenamedContainer"); + scope.Events.Dispatch(SavedContainer, This, args, nameof(SavedContainer)); } - - // fixme what is this? - protected void OnDeletingContainer(IScope scope, DeleteEventArgs args) - { - DeletingContainer.RaiseEvent(args, This); - } - + protected bool OnDeletingContainerCancelled(IScope scope, DeleteEventArgs args) { return scope.Events.DispatchCancelable(DeletingContainer, This, args); @@ -136,7 +108,7 @@ namespace Umbraco.Core.Services.Implement protected void OnDeletedContainer(IScope scope, DeleteEventArgs args) { - scope.Events.Dispatch(DeletedContainer, This, args, "DeletedContainer"); + scope.Events.Dispatch(DeletedContainer, This, args, nameof(DeletedContainer)); } } } diff --git a/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTRepositoryTItemTService.cs b/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTRepositoryTItemTService.cs index d05930564e..8ed0a0f645 100644 --- a/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTRepositoryTItemTService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTRepositoryTItemTService.cs @@ -795,7 +795,8 @@ namespace Umbraco.Core.Services.Implement using (var scope = ScopeProvider.CreateScope()) { - if (OnSavingContainerCancelled(scope, new SaveEventArgs(container, evtMsgs))) + var args = new SaveEventArgs(container, evtMsgs); + if (OnSavingContainerCancelled(scope, args)) { scope.Complete(); return OperationResult.Attempt.Cancel(evtMsgs); @@ -806,7 +807,8 @@ namespace Umbraco.Core.Services.Implement _containerRepository.Save(container); scope.Complete(); - OnSavedContainer(scope, new SaveEventArgs(container, evtMsgs)); + args.CanCancel = false; + OnSavedContainer(scope, args); } //TODO: Audit trail ? @@ -921,10 +923,19 @@ namespace Umbraco.Core.Services.Implement throw new InvalidOperationException("No container found with id " + id); container.Name = name; + + var saveEventArgs = new SaveEventArgs(container, evtMsgs); + if (OnRenamingContainerCancelled(scope, saveEventArgs)) + { + scope.Complete(); + return OperationResult.Attempt.Cancel(evtMsgs); + } + _containerRepository.Save(container); scope.Complete(); - OnRenamedContainer(scope, new SaveEventArgs(container, evtMsgs)); + saveEventArgs.CanCancel = false; + OnRenamedContainer(scope, saveEventArgs); return OperationResult.Attempt.Succeed(OperationResultType.Success, evtMsgs, container); } diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index 84f8773ed4..4ff2d05678 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -24,7 +24,8 @@ using Umbraco.Core.Scoping; using Umbraco.Core.Services.Implement; using Umbraco.Tests.Testing; using Umbraco.Web.PropertyEditors; - +using System.Reflection; + namespace Umbraco.Tests.Services { /// @@ -58,6 +59,32 @@ namespace Umbraco.Tests.Services // fixme - do it differently Container.Register(factory => factory.GetInstance().TextService); } + + /// + /// Used to list out all ambiguous events that will require dispatching with a name + /// + [Test] + public void List_Ambiguous_Events() + { + var events = ServiceContext.ContentService.GetType().GetEvents(BindingFlags.Static | BindingFlags.Public); + var typedEventHandler = typeof(TypedEventHandler<,>); + foreach(var e in events) + { + //only continue if this is a TypedEventHandler + if (!e.EventHandlerType.IsGenericType) continue; + var typeDef = e.EventHandlerType.GetGenericTypeDefinition(); + if (typedEventHandler != typeDef) continue; + + //get the event arg type + var eventArgType = e.EventHandlerType.GenericTypeArguments[1]; + + var found = EventNameExtractor.FindEvent(typeof(ContentService), eventArgType, EventNameExtractor.MatchIngNames); + if (!found.Success && found.Result.Error == EventNameExtractorError.Ambiguous) + { + Console.WriteLine($"Ambiguous event, source: {typeof(ContentService)}, args: {eventArgType}"); + } + } + } [Test] public void Create_Blueprint()