001/*
002 *  Copyright 2018 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.actions;
017
018import java.io.IOException;
019import java.util.ArrayList;
020import java.util.HashMap;
021import java.util.List;
022import java.util.Map;
023
024import org.apache.avalon.framework.parameters.Parameters;
025import org.apache.avalon.framework.service.ServiceException;
026import org.apache.avalon.framework.service.ServiceManager;
027import org.apache.cocoon.acting.ServiceableAction;
028import org.apache.cocoon.environment.ObjectModelHelper;
029import org.apache.cocoon.environment.Redirector;
030import org.apache.cocoon.environment.Request;
031import org.apache.cocoon.environment.SourceResolver;
032import org.apache.commons.lang.StringUtils;
033
034import org.ametys.cms.contenttype.ContentType;
035import org.ametys.cms.contenttype.ContentTypeExtensionPoint;
036import org.ametys.cms.contenttype.ContentTypesHelper;
037import org.ametys.cms.repository.Content;
038import org.ametys.cms.repository.WorkflowAwareContent;
039import org.ametys.core.captcha.CaptchaHelper;
040import org.ametys.core.cocoon.ActionResultGenerator;
041import org.ametys.core.user.CurrentUserProvider;
042import org.ametys.core.user.User;
043import org.ametys.core.user.UserIdentity;
044import org.ametys.core.user.UserManager;
045import org.ametys.core.util.I18nUtils;
046import org.ametys.core.util.JSONUtils;
047import org.ametys.core.util.URIUtils;
048import org.ametys.core.util.mail.SendMailHelper;
049import org.ametys.plugins.repository.AmetysObjectResolver;
050import org.ametys.plugins.repository.data.holder.ModelAwareDataHolder;
051import org.ametys.plugins.ugc.UGCConstants;
052import org.ametys.runtime.config.Config;
053import org.ametys.runtime.i18n.I18nizableText;
054import org.ametys.web.cache.PageHelper;
055import org.ametys.web.content.FOContentCreationHelper;
056import org.ametys.web.repository.content.WebContent;
057import org.ametys.web.repository.page.Page;
058import org.ametys.web.repository.page.ZoneItem;
059import org.ametys.web.repository.site.Site;
060
061import com.google.common.collect.ArrayListMultimap;
062import com.google.common.collect.Multimap;
063
064import jakarta.mail.MessagingException;
065
066/**
067 * Create content action
068 */
069public class ProposeContentAction extends ServiceableAction
070{  
071    private static final int _INITIAL_ACTION_ID = 1111;
072    
073    /** Ametys object resolver. */
074    protected AmetysObjectResolver _resolver;
075    
076    /** The content type extension point */
077    protected ContentTypeExtensionPoint _cTypeEP;
078    
079    /** The content type helper */
080    protected ContentTypesHelper _contentTypeHelper;
081    
082    /** The JSON Utils */
083    protected JSONUtils _jsonUtils;
084    
085    /** The current user provider */
086    protected CurrentUserProvider _currentUserProvider;
087    
088    /** The I18n utils */
089    protected I18nUtils _i18nUtils;
090
091    /** The user manager */
092    protected UserManager _userManager;
093
094    /** Helper for FO content creation */
095    protected FOContentCreationHelper _foContentCreationHelper;
096    
097    /** The page helper */
098    protected PageHelper _pageHelper;
099    
100    @Override
101    public void service(ServiceManager serviceManager) throws ServiceException
102    {
103        super.service(serviceManager);
104        _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE);
105        _cTypeEP = (ContentTypeExtensionPoint) serviceManager.lookup(ContentTypeExtensionPoint.ROLE);
106        _contentTypeHelper = (ContentTypesHelper) serviceManager.lookup(ContentTypesHelper.ROLE);
107        _jsonUtils = (JSONUtils) serviceManager.lookup(JSONUtils.ROLE);
108        _currentUserProvider = (CurrentUserProvider) serviceManager.lookup(CurrentUserProvider.ROLE);
109        _i18nUtils = (I18nUtils) serviceManager.lookup(I18nUtils.ROLE);
110        _userManager = (UserManager) serviceManager.lookup(UserManager.ROLE);
111        _foContentCreationHelper = (FOContentCreationHelper) serviceManager.lookup(FOContentCreationHelper.ROLE);
112        _pageHelper = (PageHelper) serviceManager.lookup(PageHelper.ROLE);
113    }
114    
115    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
116    {
117        Map<String, Object> result = new HashMap<>();
118        
119        Multimap<String, I18nizableText> errors = ArrayListMultimap.create();
120
121        Request request = ObjectModelHelper.getRequest(objectModel);
122        
123        String zoneId = request.getParameter("zoneId");
124        ZoneItem zoneItem = _resolver.resolveById(zoneId);
125        Page page = zoneItem.getParent().getParent().getParent().getParent();
126        
127        ModelAwareDataHolder serviceParameters = zoneItem.getServiceParameters();
128        String workflowName = serviceParameters.getValue("workflow");
129        String contentTypeId = serviceParameters.getValue("content-type");
130        UserIdentity[] adminUsers = serviceParameters.getValue("users");
131        
132        String siteName = request.getParameter("site");
133        String language = request.getParameter("lang");
134        
135        ContentType ugcMixin = _cTypeEP.getExtension(UGCConstants.UGC_MIXIN_TYPE);
136        
137        ContentType contentType = _cTypeEP.getExtension(contentTypeId);
138        Map<String, Object> values = _foContentCreationHelper.getAndValidateFormValues(request, contentType, "main", errors);
139        values.putAll(_foContentCreationHelper.getAndValidateFormValues(request, ugcMixin, "main", errors));
140        
141        // Check captcha if needed
142        if (_pageHelper.isCaptchaRequired(page))
143        {   
144            String captchaValue = request.getParameter("captcha");
145            String captchaKey = request.getParameter("captcha-key");
146
147            // Validate the input
148            if (!CaptchaHelper.checkAndInvalidate(captchaKey, captchaValue))
149            {
150                errors.put("captcha", new I18nizableText("plugin.ugc", "PLUGINS_UGC_SERVICE_FORM_ERROR_INVALID_CAPTCHA"));
151            }
152        }
153        
154        // If there are no errors
155        if (errors.isEmpty())
156        {            
157            String title = request.getParameter("title");
158            
159            // we add a prefix to the title for the content name to prevent issue with numeric title
160            String prefix = StringUtils.substringAfterLast(contentTypeId, ".");
161            
162            result = _foContentCreationHelper.createAndEditContent(_INITIAL_ACTION_ID, new String[] {contentTypeId}, new String[] {UGCConstants.UGC_MIXIN_TYPE}, siteName, prefix + "-" + title, title, language, values, workflowName, null, new HashMap<String, Object>());
163            
164            if (result.containsKey(Content.class.getName()))
165            {
166                result.put("success", true);
167
168                // Send mail
169                WorkflowAwareContent content = (WorkflowAwareContent) result.get(Content.class.getName());
170                _sendMail(adminUsers, content);
171            }
172            else
173            {
174                result.put("success", false);
175            }
176        }
177        else
178        {
179            result.put("success", false);
180            result.put("errors", _jsonUtils.convertObjectToJson(errors.asMap()));
181        }
182        
183        request.setAttribute(ActionResultGenerator.MAP_REQUEST_ATTR, result);
184        return EMPTY_MAP;
185    }
186
187    /**
188     * Send mail to inform that a content is created
189     * @param adminUsers the admin users
190     * @param content the created content
191     */
192    protected void _sendMail(UserIdentity[] adminUsers, WorkflowAwareContent content)
193    {
194        if (adminUsers != null)
195        {
196            String creatorFullName = null;
197            UserIdentity creatorIdentity = _currentUserProvider.getUser();
198            if (creatorIdentity != null)
199            {
200                User creator = _userManager.getUser(creatorIdentity);
201                creatorFullName = creator.getFullName();
202            }
203            else
204            {
205                creatorFullName = content.getValue(UGCConstants.ATTRIBUTE_PATH_UGC_AUTHOR);
206            }
207            
208            Site site = _getSite(content);
209            
210            I18nizableText i18nSubject = _getI18nSubject(site);
211            I18nizableText i18nBody = _getI18nBody(content, creatorFullName, site);
212            
213            String subject = _i18nUtils.translate(i18nSubject);
214            String body = _i18nUtils.translate(i18nBody);
215            
216            for (UserIdentity adminUser : adminUsers)
217            {
218                User user = _userManager.getUser(adminUser);
219                if (user == null)
220                {
221                    getLogger().error("Can not send an e-mail for the content creation to the unexisting user " + adminUser);
222                }
223                else
224                {
225                    String email = user.getEmail();
226                    try
227                    {
228                        SendMailHelper.newMail()
229                                      .withSubject(subject)
230                                      .withTextBody(body)
231                                      .withRecipient(email)
232                                      .sendMail();
233                    }
234                    catch (MessagingException | IOException e)
235                    {
236                        getLogger().warn("Could not send an e-mail for the content creation to " + email, e);
237                    }
238                }
239            }
240        }
241    }
242
243    /**
244     * Get the i18n body
245     * @param content the content
246     * @param creatorFullName the creator full name
247     * @param site the site
248     * @return The i18n body
249     */
250    protected I18nizableText _getI18nBody(WorkflowAwareContent content, String creatorFullName, Site site)
251    {
252        List<String> parametersBody = new ArrayList<>();
253        parametersBody.add(content.getTitle());
254        parametersBody.add(creatorFullName);
255        I18nizableText i18nBody = null;
256        if (site != null)
257        {
258            parametersBody.add(_getContentUri(content, site));
259            parametersBody.add(site.getTitle());
260            parametersBody.add(site.getUrl());
261            i18nBody = new I18nizableText("plugin.ugc", "PLUGINS_UGC_SERVICE_FORM_CREATED_CONTENT_MAIL_BODY", parametersBody);
262        }
263        else
264        {
265            i18nBody = new I18nizableText("plugin.ugc", "PLUGINS_UGC_SERVICE_FORM_CREATED_CONTENT_MAIL_BODY_NO_SITE", parametersBody);
266        }
267        return i18nBody;
268    }
269
270    /**
271     * Get the i18n subject
272     * @param site the site
273     * @return The i18n subject
274     */
275    protected I18nizableText _getI18nSubject(Site site)
276    {
277        I18nizableText i18nSubject = null;
278        if (site != null)
279        {
280            List<String> parametersSubject = new ArrayList<>();
281            parametersSubject.add(site.getTitle());
282            i18nSubject = new I18nizableText("plugin.ugc", "PLUGINS_UGC_SERVICE_FORM_CREATED_CONTENT_MAIL_SUBJECT", parametersSubject);
283        }
284        else
285        {
286            i18nSubject = new I18nizableText("plugin.ugc", "PLUGINS_UGC_SERVICE_FORM_CREATED_CONTENT_MAIL_SUBJECT_NO_SITE");
287        }
288        return i18nSubject;
289    }
290    
291    /**
292     * Get the site name
293     * @param content The content
294     * @return the site name
295     */
296    protected Site _getSite(WorkflowAwareContent content)
297    {
298        if (content instanceof WebContent)
299        {
300            return ((WebContent) content).getSite();
301        }
302        
303        return null;
304    }
305    
306    
307    /**
308     * Get the content uri
309     * @param content the content
310     * @param site The site
311     * @return the content uri
312     */
313    protected String _getContentUri(WorkflowAwareContent content, Site site)
314    {
315        return _getRequestUri() + "/" + site.getName() + "/index.html?uitool=uitool-content,id:%27" + URIUtils.encodeParameter(content.getId()) + "%27";
316    }
317    
318    /**
319     * Get the request URI.
320     * @return the full request URI.
321     */
322    protected String _getRequestUri()
323    {
324        return StringUtils.stripEnd(StringUtils.removeEndIgnoreCase(Config.getInstance().getValue("cms.url"), "index.html"), "/");
325    }
326}