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