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