From 9838977806908bcb3c8272ea00b013c885a66a7e Mon Sep 17 00:00:00 2001 From: Claus Date: Wed, 30 May 2018 14:39:12 +0200 Subject: [PATCH 1/3] fixes U4-11385 Can't create doc type folders. using dispatch instead of dispatchcancelable when the event is not cancelable for both saving and renaming. --- .../Implement/ContentTypeServiceBaseOfTItemTService.cs | 4 ++-- .../ContentTypeServiceBaseOfTRepositoryTItemTService.cs | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTItemTService.cs b/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTItemTService.cs index f02441eba0..543c506653 100644 --- a/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTItemTService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTItemTService.cs @@ -114,13 +114,13 @@ namespace Umbraco.Core.Services.Implement protected void OnSavedContainer(IScope scope, SaveEventArgs args) { - scope.Events.DispatchCancelable(SavedContainer, This, args); + scope.Events.Dispatch(SavedContainer, This, args); } 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, "RenamedContainer"); } // fixme what is this? diff --git a/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTRepositoryTItemTService.cs b/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTRepositoryTItemTService.cs index d05930564e..1d53fad4de 100644 --- a/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTRepositoryTItemTService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTRepositoryTItemTService.cs @@ -924,7 +924,8 @@ namespace Umbraco.Core.Services.Implement _containerRepository.Save(container); scope.Complete(); - OnRenamedContainer(scope, new SaveEventArgs(container, evtMsgs)); + var saveEventArgs = new SaveEventArgs(container, evtMsgs) {CanCancel = false}; + OnRenamedContainer(scope, saveEventArgs); return OperationResult.Attempt.Succeed(OperationResultType.Success, evtMsgs, container); } From 5ed5ebf054989c40acda47f19e200541f4e9a00f Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 31 May 2018 14:59:26 +1000 Subject: [PATCH 2/3] Fixes event handling for content type containers --- .../ContentTypeServiceBaseOfTItemTService.cs | 62 +++++-------------- ...peServiceBaseOfTRepositoryTItemTService.cs | 16 ++++- 2 files changed, 30 insertions(+), 48 deletions(-) diff --git a/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTItemTService.cs b/src/Umbraco.Core/Services/Implement/ContentTypeServiceBaseOfTItemTService.cs index 543c506653..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,16 +80,10 @@ 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) @@ -117,18 +91,16 @@ namespace Umbraco.Core.Services.Implement 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.Dispatch(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 1d53fad4de..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,18 @@ 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(); - var saveEventArgs = new SaveEventArgs(container, evtMsgs) {CanCancel = false}; + saveEventArgs.CanCancel = false; OnRenamedContainer(scope, saveEventArgs); return OperationResult.Attempt.Succeed(OperationResultType.Success, evtMsgs, container); From a2aa318e1861487c243c4a9da1732c0393752eab Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 31 May 2018 15:43:39 +1000 Subject: [PATCH 3/3] Fixes moving event dispatching in content service which prohibited you from moving anything --- .../Services/Implement/ContentService.cs | 8 ++--- .../Services/ContentServiceTests.cs | 29 ++++++++++++++++++- 2 files changed, 32 insertions(+), 5 deletions(-) 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.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()