001/* 002 * Copyright 2010 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.ametys.web.repository.comment; 018 019import java.io.IOException; 020import java.util.ArrayList; 021import java.util.List; 022import java.util.Map; 023import java.util.Set; 024 025import org.apache.avalon.framework.context.Context; 026import org.apache.avalon.framework.context.ContextException; 027import org.apache.avalon.framework.context.Contextualizable; 028import org.apache.avalon.framework.service.ServiceException; 029import org.apache.avalon.framework.service.ServiceManager; 030import org.apache.avalon.framework.service.Serviceable; 031import org.apache.cocoon.components.ContextHelper; 032import org.apache.cocoon.environment.Request; 033import org.apache.commons.lang.StringUtils; 034 035import org.ametys.cms.ObservationConstants; 036import org.ametys.cms.content.ContentHelper; 037import org.ametys.cms.repository.Content; 038import org.ametys.cms.repository.comment.Comment; 039import org.ametys.core.observation.Event; 040import org.ametys.core.observation.Observer; 041import org.ametys.core.right.RightManager; 042import org.ametys.core.user.User; 043import org.ametys.core.user.UserIdentity; 044import org.ametys.core.user.UserManager; 045import org.ametys.core.user.population.PopulationContextHelper; 046import org.ametys.core.util.I18nUtils; 047import org.ametys.core.util.mail.SendMailHelper; 048import org.ametys.runtime.config.Config; 049import org.ametys.runtime.i18n.I18nizableText; 050import org.ametys.runtime.plugin.component.AbstractLogEnabled; 051import org.ametys.runtime.plugin.component.PluginAware; 052import org.ametys.web.repository.content.WebContent; 053import org.ametys.web.repository.site.Site; 054 055import jakarta.mail.MessagingException; 056 057/** 058 * Listener to send mails to moderators or observers 059 */ 060public class SendMailToContributorCommentListener extends AbstractLogEnabled implements Observer, Serviceable, Contextualizable, PluginAware 061{ 062 /** The i18n utils of runtime */ 063 protected I18nUtils _i18nUtils; 064 /** The avalon context */ 065 protected Context _context; 066 /** The ametys rights manager */ 067 protected RightManager _rightManager; 068 /** The users manager. */ 069 protected UserManager _userManager; 070 /** The content helper */ 071 protected ContentHelper _contentHelper; 072 /** The plugin name */ 073 protected String _pluginName; 074 075 @Override 076 public void service(ServiceManager manager) throws ServiceException 077 { 078 _i18nUtils = (I18nUtils) manager.lookup(I18nUtils.ROLE); 079 _rightManager = (RightManager) manager.lookup(RightManager.ROLE); 080 _userManager = (UserManager) manager.lookup(UserManager.ROLE); 081 _contentHelper = (ContentHelper) manager.lookup(ContentHelper.ROLE); 082 } 083 084 @Override 085 public void contextualize(Context context) throws ContextException 086 { 087 _context = context; 088 } 089 090 public void setPluginInfo(String pluginName, String featureName, String id) 091 { 092 _pluginName = pluginName; 093 } 094 095 public int getPriority(Event event) 096 { 097 return MAX_PRIORITY; 098 } 099 100 @Override 101 public boolean supports(Event event) 102 { 103 return event.getId().equals(ObservationConstants.EVENT_CONTENT_COMMENT_VALIDATED) 104 || event.getId().equals(ObservationConstants.EVENT_CONTENT_COMMENT_REPORTED) 105 || event.getId().equals(ObservationConstants.EVENT_CONTENT_COMMENT_ADDED); 106 } 107 108 public void observe(Event event, Map<String, Object> transientVars) throws Exception 109 { 110 Map<String, Object> arguments = event.getArguments(); 111 Content content = (Content) arguments.get(ObservationConstants.ARGS_CONTENT); 112 Comment comment = (Comment) arguments.get(ObservationConstants.ARGS_COMMENT); 113 114 _setRequestAttributes (content); 115 116 if (event.getId().equals(ObservationConstants.EVENT_CONTENT_COMMENT_ADDED)) 117 { 118 _sendCommentAddedNotificationMail(content, comment); 119 } 120 else if (event.getId().equals(ObservationConstants.EVENT_CONTENT_COMMENT_REPORTED)) 121 { 122 UserIdentity issuer = event.getIssuer(); 123 _sendCommentReportedNotificationMail(content, comment, issuer); 124 } 125 else 126 { 127 _sendCommentValidatedNotificationMail(content, comment); 128 } 129 } 130 131 private void _setRequestAttributes (Content content) 132 { 133 Request request = ContextHelper.getRequest(_context); 134 135 if (content instanceof WebContent) 136 { 137 String siteName = ((WebContent) content).getSiteName(); 138 139 // Set the site name into the request for the other components to be able to retrieve it. 140 request.setAttribute("siteName", siteName); 141 142 List<String> populationContexts = new ArrayList<>(); 143 144 // Set the population contexts to be able to get allowed users 145 populationContexts.add("/sites/" + siteName); 146 populationContexts.add("/sites-fo/" + siteName); 147 148 request.setAttribute(PopulationContextHelper.POPULATION_CONTEXTS_REQUEST_ATTR, populationContexts); 149 } 150 } 151 152 private List<String> _getRecipients(Set<UserIdentity> users) 153 { 154 List<String> recipients = new ArrayList<>(); 155 156 for (UserIdentity userIdentity : users) 157 { 158 User user = _userManager.getUser(userIdentity); 159 if (user != null && StringUtils.isNotBlank(user.getEmail())) 160 { 161 recipients.add(user.getEmail()); 162 } 163 } 164 return recipients; 165 } 166 167 /** 168 * Send email notification on comment added 169 * @param content the content 170 * @param comment the added comment 171 */ 172 protected void _sendCommentAddedNotificationMail (Content content, Comment comment) 173 { 174 if (comment.isValidated()) 175 { 176 Set<UserIdentity> users = _rightManager.getAllowedUsers("CMS_Rights_CommentNotified", content).resolveAllowedUsers(Config.getInstance().getValue("runtime.mail.massive.sending")); 177 List<String> recipients = _getRecipients(users); 178 179 _sendMail(content, comment, recipients, "PLUGINS_WEB_CONTENT_COMMENTS_NOTIFICATION_SUBJECT", "PLUGINS_WEB_CONTENT_COMMENTS_NOTIFICATION_BODY"); 180 } 181 else 182 { 183 // Determine the list of listeners 184 Set<UserIdentity> users = _rightManager.getAllowedUsers("CMS_Rights_CommentModerate", content).resolveAllowedUsers(Config.getInstance().getValue("runtime.mail.massive.sending")); 185 List<String> recipients = _getRecipients(users); 186 187 _sendMail(content, comment, recipients, "PLUGINS_WEB_CONTENT_COMMENTS_MODERATION_SUBJECT", "PLUGINS_WEB_CONTENT_COMMENTS_MODERATION_BODY"); 188 } 189 } 190 191 /** 192 * Send email notification on comment validated 193 * @param content the content 194 * @param comment the validated comment 195 */ 196 protected void _sendCommentValidatedNotificationMail (Content content, Comment comment) 197 { 198 Set<UserIdentity> users = _rightManager.getAllowedUsers("CMS_Rights_CommentNotified", content).resolveAllowedUsers(Config.getInstance().getValue("runtime.mail.massive.sending")); 199 List<String> recipients = _getRecipients(users); 200 201 _sendMail(content, comment, recipients, "PLUGINS_WEB_CONTENT_COMMENTS_NOTIFICATION_SUBJECT", "PLUGINS_WEB_CONTENT_COMMENTS_NOTIFICATION_BODY"); 202 } 203 204 /** 205 * Send email notification on comment report 206 * @param content the content 207 * @param comment the reported comment 208 * @param issuer the issuer 209 */ 210 protected void _sendCommentReportedNotificationMail (Content content, Comment comment, UserIdentity issuer) 211 { 212 Set<UserIdentity> users = _rightManager.getAllowedUsers("CMS_Rights_CommentNotified", content).resolveAllowedUsers(Config.getInstance().getValue("runtime.mail.massive.sending")); 213 List<String> recipients = _getRecipients(users); 214 215 List<String> i18nParams = _getCommonBodyI18nParams(content, comment); 216 User issuerAsUser = _userManager.getUser(issuer); 217 i18nParams.add(issuerAsUser.getFullName()); // {6} 218 219 _sendMail(content, comment, recipients, "PLUGINS_WEB_CONTENT_COMMENTS_REPORTED_SUBJECT", "PLUGINS_WEB_CONTENT_COMMENTS_REPORTED_BODY"); 220 } 221 222 /** 223 * Send notification on comment to contributor 224 * @param content the content 225 * @param comment the modified comment 226 * @param recipients the list of recipients 227 * @param subjectI18nKey the i18n for email subject 228 * @param bodyI18nKey the i18n for email body 229 */ 230 protected void _sendMail(Content content, Comment comment, List<String> recipients, String subjectI18nKey, String bodyI18nKey) 231 { 232 _sendMail(content, comment, recipients, subjectI18nKey, bodyI18nKey, _getCommonBodyI18nParams(content, comment)); 233 } 234 235 /** 236 * Send notification on comment to contributor 237 * @param content the content 238 * @param comment the modified comment 239 * @param recipients the list of recipients 240 * @param subjectI18nKey the i18n for email subject 241 * @param bodyI18nKey the i18n for email body 242 * @param i18nParams the i18n parameters 243 */ 244 protected void _sendMail(Content content, Comment comment, List<String> recipients, String subjectI18nKey, String bodyI18nKey, List<String> i18nParams) 245 { 246 getLogger().debug("Send email notification to '{}' for his comment '{}' on content '{}'", comment.getAuthorEmail(), comment.getId(), content.getId()); 247 248 I18nizableText i18nSubject = new I18nizableText("plugin." + _pluginName, subjectI18nKey, i18nParams); 249 String subject = _i18nUtils.translate(i18nSubject, content.getLanguage()); 250 251 I18nizableText i18nBody = new I18nizableText("plugin." + _pluginName, bodyI18nKey, i18nParams); 252 String body = _i18nUtils.translate(i18nBody, content.getLanguage()); 253 254 String from = Config.getInstance().getValue("smtp.mail.from"); 255 if (content instanceof WebContent) 256 { 257 Site site = ((WebContent) content).getSite(); 258 from = site.getValue("site-mail-from"); 259 } 260 261 try 262 { 263 SendMailHelper.newMail() 264 .withSubject(subject) 265 .withTextBody(body) 266 .withSender(from) 267 .withRecipients(recipients) 268 .withAsync(true) 269 .sendMail(); 270 } 271 catch (MessagingException | IOException e) 272 { 273 getLogger().warn("Could not send a notification mail to {}", recipients, e); 274 } 275 } 276 277 /** 278 * The comment i18n parameters for email notification 279 * @param content the content 280 * @param comment the comment 281 * @return the i18n parameters 282 */ 283 protected List<String> _getCommonBodyI18nParams(Content content, Comment comment) 284 { 285 List<String> i18nparam = new ArrayList<>(); 286 287 i18nparam.add(_contentHelper.getTitle(content)); // {0} 288 i18nparam.add(_getContentURI(content)); // {1} 289 i18nparam.add(comment.getAuthorName()); // {2} 290 i18nparam.add(comment.getContent()); // {3} 291 292 if (content instanceof WebContent) 293 { 294 Site site = ((WebContent) content).getSite(); 295 i18nparam.add(site.getName()); // {4} 296 i18nparam.add(site.getTitle()); // {5} 297 } 298 299 return i18nparam; 300 } 301 302 /** 303 * Get the content URI in back-office 304 * @param content the content 305 * @return the content uri 306 */ 307 protected String _getContentURI(Content content) 308 { 309 String cmsUrl = StringUtils.stripEnd(StringUtils.removeEndIgnoreCase(Config.getInstance().getValue("cms.url"), "index.html"), "/"); 310 311 StringBuilder url = new StringBuilder(cmsUrl); 312 313 if (content instanceof WebContent) 314 { 315 Site site = ((WebContent) content).getSite(); 316 url.append("/").append(site.getName()); 317 } 318 url.append("/index.html?uitool=uitool-content,id:%27").append(content.getId()).append("%27"); 319 return url.toString(); 320 } 321}