001/* 002 * Copyright 2019 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 */ 016package org.ametys.plugins.ugc.observation; 017 018import java.io.IOException; 019import java.time.ZoneId; 020import java.time.ZonedDateTime; 021import java.time.format.FormatStyle; 022import java.util.Collection; 023import java.util.HashMap; 024import java.util.Map; 025 026import org.apache.avalon.framework.configuration.Configurable; 027import org.apache.avalon.framework.configuration.Configuration; 028import org.apache.avalon.framework.configuration.ConfigurationException; 029import org.apache.avalon.framework.logger.AbstractLogEnabled; 030import org.apache.avalon.framework.service.ServiceException; 031import org.apache.avalon.framework.service.ServiceManager; 032import org.apache.avalon.framework.service.Serviceable; 033import org.apache.commons.lang3.StringUtils; 034 035import org.ametys.cms.contenttype.ContentTypesHelper; 036import org.ametys.cms.repository.Content; 037import org.ametys.core.observation.Observer; 038import org.ametys.core.user.User; 039import org.ametys.core.user.UserIdentity; 040import org.ametys.core.user.UserManager; 041import org.ametys.core.user.population.UserPopulationDAO; 042import org.ametys.core.util.I18nUtils; 043import org.ametys.core.util.language.UserLanguagesManager; 044import org.ametys.core.util.mail.SendMailHelper; 045import org.ametys.plugins.ugc.UGCConstants; 046import org.ametys.runtime.config.Config; 047import org.ametys.runtime.i18n.I18nizableDateTime; 048import org.ametys.runtime.i18n.I18nizableText; 049import org.ametys.runtime.i18n.I18nizableTextParameter; 050import org.ametys.web.repository.content.WebContent; 051import org.ametys.web.repository.page.Page; 052import org.ametys.web.repository.site.Site; 053 054import jakarta.mail.MessagingException; 055 056/** 057 * Abstract observer to send mail to UGC author on UGC content event 058 * 059 */ 060public abstract class AbstractUGCContentObserver extends AbstractLogEnabled implements Observer, Serviceable, Configurable 061{ 062 /** The content type helper */ 063 protected ContentTypesHelper _cTypeHelper; 064 /** The i18n utils */ 065 protected I18nUtils _i18nUtils; 066 /** The user manager */ 067 protected UserManager _userManager; 068 /** The user languages manager */ 069 protected UserLanguagesManager _userLanguagesManager; 070 071 /** The i18n key for mail subject */ 072 protected String _subjectI18nKey; 073 /** The i18n key for mail body */ 074 protected String _bodyI18nKey; 075 076 @Override 077 public void service(ServiceManager smanager) throws ServiceException 078 { 079 _cTypeHelper = (ContentTypesHelper) smanager.lookup(ContentTypesHelper.ROLE); 080 _i18nUtils = (I18nUtils) smanager.lookup(I18nUtils.ROLE); 081 _userManager = (UserManager) smanager.lookup(UserManager.ROLE); 082 _userLanguagesManager = (UserLanguagesManager) smanager.lookup(UserLanguagesManager.ROLE); 083 } 084 085 public void configure(Configuration configuration) throws ConfigurationException 086 { 087 _subjectI18nKey = configuration.getChild("mailSubjectKey").getValue(null); 088 _bodyI18nKey = configuration.getChild("mailBodyKey").getValue(null); 089 } 090 091 @Override 092 public int getPriority() 093 { 094 return MIN_PRIORITY; 095 } 096 097 /** 098 * Send mail to the UGC author 099 * @param ugcContent The UGC content 100 * @param comment The comment. Can be null. 101 */ 102 protected void sendMailToUGCAuthor(Content ugcContent, String comment) 103 { 104 String recipient = ugcContent.getValue(UGCConstants.ATTRIBUTE_PATH_UGC_MAIL, false, null); 105 if (StringUtils.isNotBlank(recipient)) 106 { 107 String language = getMailLanguage(ugcContent); 108 String sender = Config.getInstance().getValue("smtp.mail.from"); 109 if (ugcContent instanceof WebContent) 110 { 111 Site site = ((WebContent) ugcContent).getSite(); 112 sender = site.getValue("site-mail-from", false, Config.getInstance().getValue("smtp.mail.from")); 113 } 114 115 String subject = getMailSubject(ugcContent, language); 116 String body = getMailBody(ugcContent, comment, language); 117 118 try 119 { 120 SendMailHelper.newMail() 121 .withSubject(subject) 122 .withTextBody(body) 123 .withSender(sender) 124 .withRecipient(recipient) 125 .withAsync(true) 126 .sendMail(); 127 } 128 catch (MessagingException | IOException e) 129 { 130 getLogger().warn("Fail to send UGC content notification mail to " + recipient, e); 131 } 132 } 133 } 134 135 /** 136 * Get the mail language 137 * @param ugcContent The UGC content 138 * @return the language to use in the mail or null if none was found 139 */ 140 protected String getMailLanguage(Content ugcContent) 141 { 142 String language = null; 143 UserIdentity userIdentity = ugcContent.getCreator(); 144 if (userIdentity != null && !UserPopulationDAO.SYSTEM_USER_IDENTITY.equals(userIdentity)) 145 { 146 User user = _userManager.getUser(userIdentity); 147 if (user != null) 148 { 149 language = user.getLanguage(); 150 } 151 } 152 153 // ugc content language can also be null 154 return StringUtils.defaultIfEmpty(language, _userLanguagesManager.getDefaultLanguage()); 155 } 156 157 /** 158 * Get the mail subject 159 * @param ugcContent The UGC content 160 * @param language The language to use 161 * @return the mail text subject 162 */ 163 protected String getMailSubject (Content ugcContent, String language) 164 { 165 I18nizableText subjectKey = new I18nizableText(null, _subjectI18nKey, getSubjectI18nParams(ugcContent)); 166 return _i18nUtils.translate(subjectKey, language); 167 } 168 169 /** 170 * Get the mail body 171 * @param ugcContent The UGC content 172 * @param comment The comment. Can be null. 173 * @param language The language to use 174 * @return the mail text body 175 */ 176 protected String getMailBody (Content ugcContent, String comment, String language) 177 { 178 I18nizableText bodyKey = new I18nizableText(null, _bodyI18nKey, getBodyI18nParams(ugcContent, comment)); 179 return _i18nUtils.translate(bodyKey, language); 180 } 181 182 /** 183 * Get the i18n parameters for mail subject 184 * @param ugcContent The UGC content 185 * @return the i18n parameters for mail subject 186 */ 187 protected Map<String, I18nizableTextParameter> getSubjectI18nParams(Content ugcContent) 188 { 189 Map<String, I18nizableTextParameter> params = new HashMap<>(); 190 191 params.put("contentTitle", new I18nizableText(ugcContent.getTitle())); 192 if (ugcContent instanceof WebContent) 193 { 194 Site site = ((WebContent) ugcContent).getSite(); 195 params.put("siteTitle", new I18nizableText(site.getTitle())); 196 } 197 198 return params; 199 } 200 201 /** 202 * Get the i18n parameters for mail body 203 * @param ugcContent The UGC content 204 * @param comment The comment. Can be null. 205 * @return the i18n parameters for mail body 206 */ 207 protected Map<String, I18nizableTextParameter> getBodyI18nParams(Content ugcContent, String comment) 208 { 209 Map<String, I18nizableTextParameter> params = new HashMap<>(); 210 211 String authorFullName = ugcContent.getValue(UGCConstants.ATTRIBUTE_PATH_UGC_AUTHOR, false, null); 212 params.put("authorFullName", new I18nizableText(authorFullName)); 213 214 params.put("contentTitle", new I18nizableText(ugcContent.getTitle())); 215 216 if (ugcContent instanceof WebContent) 217 { 218 Site site = ((WebContent) ugcContent).getSite(); 219 params.put("siteTitle", new I18nizableText(site.getTitle())); 220 params.put("siteUrl", new I18nizableText(site.getUrl())); 221 222 Collection<Page> pages = ((WebContent) ugcContent).getReferencingPages(); 223 if (!pages.isEmpty()) 224 { 225 Page page = pages.iterator().next(); 226 String uri = site.getUrl() + "/" + page.getSitemapName() + "/" + page.getPathInSitemap() + ".html"; 227 params.put("uri", new I18nizableText(uri)); 228 } 229 } 230 231 ZonedDateTime creationDate = ugcContent.getCreationDate(); 232 params.put("creationDate", new I18nizableDateTime(creationDate, ZoneId.from(creationDate), FormatStyle.LONG)); 233 234 if (StringUtils.isNotBlank(comment)) 235 { 236 params.put("comment", new I18nizableText(comment)); 237 } 238 239 return params; 240 } 241}