From ca6fd56f09d6cbe27dd44cf1379d89cb6d23b02c Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 25 Oct 2018 17:21:10 +1100 Subject: [PATCH] Gets send to publish emails working for variants --- src/Umbraco.Core/Models/Content.cs | 6 +- .../Models/NotificationEmailBodyParams.cs | 4 + .../Services/Implement/NotificationService.cs | 106 +++++++++++++----- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 4 +- src/Umbraco.Web.UI/Umbraco/config/lang/en.xml | 10 +- .../Umbraco/config/lang/en_us.xml | 10 +- .../Components/NotificationsComponent.cs | 52 ++++++--- 7 files changed, 141 insertions(+), 51 deletions(-) diff --git a/src/Umbraco.Core/Models/Content.cs b/src/Umbraco.Core/Models/Content.cs index dfd0313078..b048998691 100644 --- a/src/Umbraco.Core/Models/Content.cs +++ b/src/Umbraco.Core/Models/Content.cs @@ -467,8 +467,10 @@ namespace Umbraco.Core.Models { base.ResetDirtyProperties(rememberDirty); - Template.ResetDirtyProperties(rememberDirty); - ContentType.ResetDirtyProperties(rememberDirty); + if (Template != null) + Template.ResetDirtyProperties(rememberDirty); + if (ContentType != null) + ContentType.ResetDirtyProperties(rememberDirty); // take care of the published state _publishedState = _published ? PublishedState.Published : PublishedState.Unpublished; diff --git a/src/Umbraco.Core/Models/NotificationEmailBodyParams.cs b/src/Umbraco.Core/Models/NotificationEmailBodyParams.cs index ff316b1cf7..e85284fe5a 100644 --- a/src/Umbraco.Core/Models/NotificationEmailBodyParams.cs +++ b/src/Umbraco.Core/Models/NotificationEmailBodyParams.cs @@ -21,6 +21,10 @@ namespace Umbraco.Core.Models public string ItemName { get; } public string ItemId { get; } public string ItemUrl { get; } + + /// + /// This will either be an HTML or text based summary depending on the email type being sent + /// public string Summary { get; } public string EditedUser { get; } public string SiteUrl { get; } diff --git a/src/Umbraco.Core/Services/Implement/NotificationService.cs b/src/Umbraco.Core/Services/Implement/NotificationService.cs index 5d7860026b..ef2bfafcf6 100644 --- a/src/Umbraco.Core/Services/Implement/NotificationService.cs +++ b/src/Umbraco.Core/Services/Implement/NotificationService.cs @@ -24,12 +24,13 @@ namespace Umbraco.Core.Services.Implement private readonly IScopeProvider _uowProvider; private readonly IUserService _userService; private readonly IContentService _contentService; + private readonly ILocalizationService _localizationService; private readonly INotificationsRepository _notificationsRepository; private readonly IGlobalSettings _globalSettings; private readonly IContentSection _contentSection; private readonly ILogger _logger; - public NotificationService(IScopeProvider provider, IUserService userService, IContentService contentService, + public NotificationService(IScopeProvider provider, IUserService userService, IContentService contentService, ILocalizationService localizationService, ILogger logger, INotificationsRepository notificationsRepository, IGlobalSettings globalSettings, IContentSection contentSection) { _notificationsRepository = notificationsRepository; @@ -38,6 +39,7 @@ namespace Umbraco.Core.Services.Implement _uowProvider = provider ?? throw new ArgumentNullException(nameof(provider)); _userService = userService ?? throw new ArgumentNullException(nameof(userService)); _contentService = contentService ?? throw new ArgumentNullException(nameof(contentService)); + _localizationService = localizationService; _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } @@ -279,7 +281,7 @@ namespace Umbraco.Core.Services.Implement /// /// Callback to create the mail subject /// Callback to create the mail body - private NotificationRequest CreateNotificationRequest(IUser performingUser, IUser mailingUser, IContentBase content, IContentBase oldDoc, + private NotificationRequest CreateNotificationRequest(IUser performingUser, IUser mailingUser, IContent content, IContentBase oldDoc, string actionName, Uri siteUri, Func<(IUser user, NotificationEmailSubjectParams subject), string> createSubject, @@ -294,34 +296,88 @@ namespace Umbraco.Core.Services.Implement // build summary var summary = new StringBuilder(); - var props = content.Properties.ToArray(); - foreach (var p in props) + + if (content.ContentType.VariesByNothing()) { - //fixme doesn't take into account variants - - var newText = p.GetValue() != null ? p.GetValue().ToString() : ""; - var oldText = newText; - - // check if something was changed and display the changes otherwise display the fields - if (oldDoc.Properties.Contains(p.PropertyType.Alias)) + if (!_contentSection.DisableHtmlEmail) { - var oldProperty = oldDoc.Properties[p.PropertyType.Alias]; - oldText = oldProperty.GetValue() != null ? oldProperty.GetValue().ToString() : ""; + //create the html summary for invariant content - // replace html with char equivalent - ReplaceHtmlSymbols(ref oldText); - ReplaceHtmlSymbols(ref newText); + //list all of the property values like we used to + summary.Append(""); + foreach (var p in content.Properties) + { + //fixme doesn't take into account variants + + var newText = p.GetValue() != null ? p.GetValue().ToString() : ""; + var oldText = newText; + + // check if something was changed and display the changes otherwise display the fields + if (oldDoc.Properties.Contains(p.PropertyType.Alias)) + { + var oldProperty = oldDoc.Properties[p.PropertyType.Alias]; + oldText = oldProperty.GetValue() != null ? oldProperty.GetValue().ToString() : ""; + + // replace html with char equivalent + ReplaceHtmlSymbols(ref oldText); + ReplaceHtmlSymbols(ref newText); + } + + //show the values + summary.Append(""); + summary.Append(""); + summary.Append(""); + summary.Append(""); + } + summary.Append("
"); + summary.Append(p.PropertyType.Name); + summary.Append(""); + summary.Append(newText); + summary.Append("
"); } + + } + else if (content.ContentType.VariesByCulture()) + { + //it's variant, so detect what cultures have changed - //show the values - summary.Append(""); - summary.Append(""); - summary.Append(p.PropertyType.Name); - summary.Append(""); - summary.Append(""); - summary.Append(newText); - summary.Append(""); - summary.Append(""); + if (!_contentSection.DisableHtmlEmail) + { + //Create the html based summary (ul of culture names) + + var culturesChanged = content.CultureInfos.Where(x => x.Value.WasDirty()) + .Select(x => x.Key) + .Select(_localizationService.GetLanguageByIsoCode) + .WhereNotNull() + .Select(x => x.CultureName); + summary.Append(""); + } + else + { + //Create the text based summary (csv of culture names) + + var culturesChanged = string.Join(", ", content.CultureInfos.Where(x => x.Value.WasDirty()) + .Select(x => x.Key) + .Select(_localizationService.GetLanguageByIsoCode) + .WhereNotNull() + .Select(x => x.CultureName)); + + summary.Append("'"); + summary.Append(culturesChanged); + summary.Append("'"); + } + } + else + { + //not supported yet... + throw new NotSupportedException(); } var protocol = _globalSettings.UseHttps ? "https" : "http"; diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 6d0d14ce11..088a696986 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -160,10 +160,11 @@ namespace Umbraco.Tests.TestHelpers var runtimeState = Mock.Of(); var idkMap = new IdkMap(scopeProvider); + var localizationService = GetLazyService(container, c => new LocalizationService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c))); var userService = GetLazyService(container, c => new UserService(scopeProvider, logger, eventMessagesFactory, runtimeState, GetRepo(c), GetRepo(c),globalSettings)); var dataTypeService = GetLazyService(container, c => new DataTypeService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); var contentService = GetLazyService(container, c => new ContentService(scopeProvider, logger, eventMessagesFactory, mediaFileSystem, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); - var notificationService = GetLazyService(container, c => new NotificationService(scopeProvider, userService.Value, contentService.Value, logger, GetRepo(c), globalSettings, umbracoSettings.Content)); + var notificationService = GetLazyService(container, c => new NotificationService(scopeProvider, userService.Value, contentService.Value, localizationService.Value, logger, GetRepo(c), globalSettings, umbracoSettings.Content)); var serverRegistrationService = GetLazyService(container, c => new ServerRegistrationService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); var memberGroupService = GetLazyService(container, c => new MemberGroupService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); var memberService = GetLazyService(container, c => new MemberService(scopeProvider, logger, eventMessagesFactory, memberGroupService.Value, mediaFileSystem, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); @@ -171,7 +172,6 @@ namespace Umbraco.Tests.TestHelpers var contentTypeService = GetLazyService(container, c => new ContentTypeService(scopeProvider, logger, eventMessagesFactory, contentService.Value, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); var mediaTypeService = GetLazyService(container, c => new MediaTypeService(scopeProvider, logger, eventMessagesFactory, mediaService.Value, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); var fileService = GetLazyService(container, c => new FileService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); - var localizationService = GetLazyService(container, c => new LocalizationService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c))); var memberTypeService = GetLazyService(container, c => new MemberTypeService(scopeProvider, logger, eventMessagesFactory, memberService.Value, GetRepo(c), GetRepo(c), GetRepo(c))); var entityService = GetLazyService(container, c => new EntityService( diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml index e852be1a4e..cd1591df8d 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml @@ -943,10 +943,13 @@ To manage your website, simply open the Umbraco back office and start adding con Go to http://%4%/#/content/content/edit/%5% to edit. + %6% + Have a nice day! Cheers from the Umbraco robot ]]> + The following languages have been modified %0% @@ -1002,9 +1005,7 @@ To manage your website, simply open the Umbraco back office and start adding con

Update summary:

- - %6% -
+ %6%

Have a nice day!

@@ -1025,6 +1026,9 @@ To manage your website, simply open the Umbraco back office and start adding con ]]> + The following languages have been modified:

+ %0% + ]]>
[%0%] Notification about %1% performed on %2% Notifications diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index 54d86eee5c..c6574198e8 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -963,10 +963,13 @@ To manage your website, simply open the Umbraco back office and start adding con Go to http://%4%/#/content/content/edit/%5% to edit. + %6% + Have a nice day! Cheers from the Umbraco robot ]]> + The following languages have been modified %0% @@ -1022,9 +1025,7 @@ To manage your website, simply open the Umbraco back office and start adding con

Update summary:

- - %6% -
+ %6%

Have a nice day!

@@ -1045,6 +1046,9 @@ To manage your website, simply open the Umbraco back office and start adding con ]]> + The following languages have been modified:

+ %0% + ]]>
[%0%] Notification about %1% performed on %2% Notifications diff --git a/src/Umbraco.Web/Components/NotificationsComponent.cs b/src/Umbraco.Web/Components/NotificationsComponent.cs index 7eaaf0e18c..40c19d0df4 100644 --- a/src/Umbraco.Web/Components/NotificationsComponent.cs +++ b/src/Umbraco.Web/Components/NotificationsComponent.cs @@ -150,22 +150,42 @@ namespace Umbraco.Web.Components if (sender == null) throw new ArgumentNullException(nameof(sender)); if (siteUri == null) throw new ArgumentNullException(nameof(siteUri)); - _notificationService.SendNotifications( - sender, - entities, - action.Letter.ToString(CultureInfo.InvariantCulture), - _textService.Localize("actions", action.Alias), - siteUri, - ((IUser user, NotificationEmailSubjectParams subject) x) - => _textService.Localize( - "notifications/mailSubject", - x.user.GetUserCulture(_textService, _globalSettings), - new[] { x.subject.SiteUrl, x.subject.Action, x.subject.ItemName }), - ((IUser user, NotificationEmailBodyParams body, bool isHtml) x) - => _textService.Localize( - x.isHtml ? "notifications/mailBodyHtml" : "notifications/mailBody", - x.user.GetUserCulture(_textService, _globalSettings), - new[] { x.body.RecipientName, x.body.Action, x.body.ItemName, x.body.EditedUser, x.body.SiteUrl, x.body.ItemId, x.body.Summary, x.body.ItemUrl })); + //group by the content type variation since the emails will be different + foreach(var contentVariantGroup in entities.GroupBy(x => x.ContentType.Variations)) + { + if (contentVariantGroup.Key == ContentVariation.CultureAndSegment || contentVariantGroup.Key == ContentVariation.Segment) + throw new NotSupportedException("Segments are not yet supported in Umbraco"); + + _notificationService.SendNotifications( + sender, + contentVariantGroup, + action.Letter.ToString(CultureInfo.InvariantCulture), + _textService.Localize("actions", action.Alias), + siteUri, + ((IUser user, NotificationEmailSubjectParams subject) x) + => _textService.Localize( + "notifications/mailSubject", + x.user.GetUserCulture(_textService, _globalSettings), + new[] { x.subject.SiteUrl, x.subject.Action, x.subject.ItemName }), + ((IUser user, NotificationEmailBodyParams body, bool isHtml) x) + => _textService.Localize( + x.isHtml ? "notifications/mailBodyHtml" : "notifications/mailBody", + x.user.GetUserCulture(_textService, _globalSettings), + new[] + { + x.body.RecipientName, + x.body.Action, + x.body.ItemName, + x.body.EditedUser, + x.body.SiteUrl, + x.body.ItemId, + //format the summary depending on if it's variant or not + contentVariantGroup.Key == ContentVariation.Culture + ? (x.isHtml ? _textService.Localize("notifications/mailBodyVariantHtmlSummary", new[]{ x.body.Summary }) : _textService.Localize("notifications/mailBodyVariantSummary", new []{ x.body.Summary })) + : x.body.Summary, + x.body.ItemUrl + })); + } } }