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