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