// Copyright (c) Umbraco. // See LICENSE for more details. using System; using System.Collections.Generic; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Services.Implement; using Umbraco.Cms.Infrastructure.Services; using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors { // TODO: add copying handling public abstract class ComplexPropertyEditorContentNotificationHandler : INotificationHandler> { private readonly string _editorAlias; private readonly Func _formatPropertyValue; protected ComplexPropertyEditorContentNotificationHandler(string editorAlias, Func formatPropertyValue) { _editorAlias = editorAlias; _formatPropertyValue = formatPropertyValue; } public void Handle(SavingNotification notification) { foreach (var entity in notification.SavedEntities) { var props = entity.GetPropertiesByEditor(_editorAlias); UpdatePropertyValues(props, true); } } private void UpdatePropertyValues(IEnumerable props, bool onlyMissingKeys) { foreach (var prop in props) { // A Property may have one or more values due to cultures var propVals = prop.Values; foreach (var cultureVal in propVals) { // Remove keys from published value & any nested properties var updatedPublishedVal = _formatPropertyValue(cultureVal.PublishedValue?.ToString(), onlyMissingKeys); cultureVal.PublishedValue = updatedPublishedVal; // Remove keys from edited/draft value & any nested properties var updatedEditedVal = _formatPropertyValue(cultureVal.EditedValue?.ToString(), onlyMissingKeys); cultureVal.EditedValue = updatedEditedVal; } } } } /// /// Utility class for dealing with Copying/Saving events for complex editors /// public class ComplexPropertyEditorContentEventHandler : IDisposable { private readonly string _editorAlias; private readonly Func _formatPropertyValue; private bool _disposedValue; public ComplexPropertyEditorContentEventHandler(string editorAlias, Func formatPropertyValue) { _editorAlias = editorAlias; _formatPropertyValue = formatPropertyValue; ContentService.Copying += ContentService_Copying; //ContentService.Saving += ContentService_Saving; } /// /// Copying event handler /// /// /// private void ContentService_Copying(IContentService sender, CopyEventArgs e) { var props = e.Copy.GetPropertiesByEditor(_editorAlias); UpdatePropertyValues(props, false); } /// /// Saving event handler /// /// /// private void ContentService_Saving(IContentService sender, ContentSavingEventArgs e) { foreach (var entity in e.SavedEntities) { var props = entity.GetPropertiesByEditor(_editorAlias); UpdatePropertyValues(props, true); } } private void UpdatePropertyValues(IEnumerable props, bool onlyMissingKeys) { foreach (var prop in props) { // A Property may have one or more values due to cultures var propVals = prop.Values; foreach (var cultureVal in propVals) { // Remove keys from published value & any nested properties var updatedPublishedVal = _formatPropertyValue(cultureVal.PublishedValue?.ToString(), onlyMissingKeys); cultureVal.PublishedValue = updatedPublishedVal; // Remove keys from edited/draft value & any nested properties var updatedEditedVal = _formatPropertyValue(cultureVal.EditedValue?.ToString(), onlyMissingKeys); cultureVal.EditedValue = updatedEditedVal; } } } /// /// Unbinds from events /// /// protected virtual void Dispose(bool disposing) { if (!_disposedValue) { if (disposing) { ContentService.Copying -= ContentService_Copying; //ContentService.Saving -= ContentService_Saving; } _disposedValue = true; } } /// /// Unbinds from events /// public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } } }