001/*
002 *  Copyright 2024 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.workspaces.comments;
017
018import java.io.IOException;
019import java.util.List;
020import java.util.Map;
021
022import org.apache.avalon.framework.context.Context;
023import org.apache.avalon.framework.context.ContextException;
024import org.apache.avalon.framework.context.Contextualizable;
025import org.apache.avalon.framework.service.ServiceException;
026import org.apache.avalon.framework.service.ServiceManager;
027import org.apache.cocoon.components.ContextHelper;
028import org.apache.cocoon.environment.Request;
029
030import org.ametys.cms.repository.mentions.AbstractNotifyMentionsObserver;
031import org.ametys.core.observation.Event;
032import org.ametys.core.right.RightManager;
033import org.ametys.core.user.User;
034import org.ametys.core.user.UserIdentity;
035import org.ametys.core.util.StringUtils;
036import org.ametys.plugins.workspaces.ObservationConstants;
037import org.ametys.plugins.workspaces.WorkspacesHelper;
038import org.ametys.plugins.workspaces.forum.ForumWorkspaceModule;
039import org.ametys.plugins.workspaces.forum.Thread;
040import org.ametys.plugins.workspaces.forum.json.ThreadJSONHelper;
041import org.ametys.plugins.workspaces.project.ProjectManager;
042import org.ametys.plugins.workspaces.project.modules.WorkspaceModuleExtensionPoint;
043import org.ametys.plugins.workspaces.project.objects.Project;
044import org.ametys.plugins.workspaces.project.rights.ProjectRightHelper;
045import org.ametys.runtime.i18n.I18nizableText;
046import org.ametys.web.WebConstants;
047import org.ametys.web.renderingcontext.RenderingContext;
048import org.ametys.web.renderingcontext.RenderingContextHandler;
049
050/**
051 * Observer to send mails to mentioned users in content of {@link Thread}
052 */
053public class NotifyThreadMentionsObserver extends AbstractNotifyMentionsObserver<Thread> implements Contextualizable
054{
055    
056    /** The right manager */
057    protected RightManager _rightManager;
058    
059    /** The forum module */
060    protected ForumWorkspaceModule _forumModule;
061    
062    /** The project manager */
063    protected ProjectManager _projectManager;
064
065    /** The project tags DAO */
066    protected ThreadJSONHelper _threadJSONHelper;
067
068    /** The Avalon context */
069    protected Context _context;
070
071    /** The Workspaces helper */
072    protected WorkspacesHelper _workspaceHelper;
073    
074    /** The project rights helper */
075    protected ProjectRightHelper _projectRightsHelper;
076
077    /** The rendering context handler */
078    protected RenderingContextHandler _renderingContextHandler;
079    
080    @Override
081    public void service(ServiceManager manager) throws ServiceException
082    {
083        super.service(manager);
084        _rightManager = (RightManager) manager.lookup(RightManager.ROLE);
085        WorkspaceModuleExtensionPoint moduleManagerEP = (WorkspaceModuleExtensionPoint) manager.lookup(WorkspaceModuleExtensionPoint.ROLE);
086        _forumModule = moduleManagerEP.getModule(ForumWorkspaceModule.FORUM_MODULE_ID);
087        _projectManager = (ProjectManager) manager.lookup(ProjectManager.ROLE);
088        _threadJSONHelper = (ThreadJSONHelper) manager.lookup(ThreadJSONHelper.ROLE);
089        _workspaceHelper = (WorkspacesHelper) manager.lookup(WorkspacesHelper.ROLE);
090        _projectRightsHelper = (ProjectRightHelper) manager.lookup(ProjectRightHelper.ROLE);
091        _renderingContextHandler = (RenderingContextHandler) manager.lookup(RenderingContextHandler.ROLE);
092    }
093
094    public void contextualize(Context context) throws ContextException
095    {
096        _context = context;
097    }
098
099    @Override
100    public void observe(Event event, Map<String, Object> transientVars) throws Exception
101    {
102        Map<String, Object> arguments = event.getArguments();
103
104        Thread thread = (Thread) arguments.get(ObservationConstants.ARGS_THREAD);
105        Project project = _projectManager.getParentProject(thread);
106        Request request = ContextHelper.getRequest(_context);
107        request.setAttribute(WebConstants.REQUEST_ATTR_SITE_NAME, project.getName());
108        super.observe(event, transientVars);
109    }
110    
111    public boolean supports(Event event)
112    {
113        return event.getId().equals(ObservationConstants.EVENT_THREAD_CREATED);
114    }
115
116    @Override
117    protected I18nizableText _getMailTitle(MentionableObject mentionableObject)
118    {
119        Thread thread = (Thread) mentionableObject.ametysObject();
120        Project project = _projectManager.getParentProject(thread);
121
122        List<String> i18nParams = List.of(project.getTitle());
123        
124        return new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_WORKSPACES_MENTION_MAIL_SUBJECT", i18nParams);
125    }
126
127    @Override
128    protected I18nizableText _getMailSubject(MentionableObject mentionableObject)
129    {
130        Project project = _projectManager.getParentProject(mentionableObject.ametysObject());
131        List<String> i18nParams = List.of(project.getTitle());
132        return new I18nizableText("plugin.cms", "PLUGINS_CMS_AMETYS_OBJECT_THREAD_MENTION_MAIL_SUBJECT", i18nParams);
133    }
134
135    @Override
136    protected MentionableObject _getMentionableObjectFromArguments(Map<String, Object> arguments) throws Exception
137    {
138        Thread thread = (Thread) arguments.get(ObservationConstants.ARGS_THREAD);
139        thread = _resolver.resolveById(thread.getId());
140        Project project = _projectManager.getParentProject(thread);
141        String content = _getContentFromThread(thread);
142        String url = _getUrl(thread, project);
143        
144        return new MentionableObject(
145            _userManager.getUser(thread.getAuthor()),
146            content,
147            _mentionUtils.extractMentionedUsersFromRichText(content),
148            thread.getCreationDate(),
149            thread,
150            new LinkToAmetysObject(url, new I18nizableText("plugin.workspaces", "PROJECT_MAIL_NOTIFICATION_BODY_FORUMTHREAD_BUTTON_TEXT")),
151            _workspaceHelper.getLang(project)
152        );
153    }
154    
155    private String _getContentFromThread(Thread thread) throws IOException
156    {
157        Request request = ContextHelper.getRequest(_context);
158        String siteName = (String) request.getAttribute("site");
159        Project project = _projectManager.getParentProject(thread);
160        if (siteName == null)
161        {
162            request.setAttribute("site", project.getSite().getName());
163        }
164        return _threadJSONHelper.richTextToRendering(thread.getContent());
165    }
166    
167    private String _getAmetysObjectTitle(Thread thread)
168    {
169        return thread.getTitle();
170    }
171
172    @Override
173    protected String _transformSyntaxTextToReadableTextWithColors(String content, UserIdentity recipient)
174    {
175        return _mentionUtils.transformRichTextToReadableText(content, recipient);
176    }
177
178    @Override
179    protected I18nizableText _getMailMessageType()
180    {
181        return new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_THREAD_MENTION_MAIL_DESCRIPTION_TITLE");
182    }
183
184    @Override
185    protected I18nizableText _getMailMessage(MentionableObject mentionableObject)
186    {
187        Thread thread = (Thread) mentionableObject.ametysObject();
188        Project project = _projectManager.getParentProject(thread);
189        User author = mentionableObject.author();
190        List<String> i18nParams = List.of(StringUtils.escapeHTML(author.getFullName()), StringUtils.escapeHTML(_getAmetysObjectTitle(thread)), StringUtils.escapeHTML(project.getTitle()));
191        return new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_THREAD_MENTION_MAIL_MESSAGE", i18nParams);
192    }
193    
194    @Override
195    protected boolean _canSendMailToMentionedUser(Thread thread, User authorIdentity, UserIdentity mentionedUserIdentity)
196    {
197        Project project = _projectManager.getParentProject(thread);
198        
199        return super._canSendMailToMentionedUser(thread, authorIdentity, mentionedUserIdentity)
200            && _projectRightsHelper.hasReadAccessOnModule(project, ForumWorkspaceModule.FORUM_MODULE_ID, mentionedUserIdentity);
201    }
202    
203    private String _getUrl(Thread thread, Project project)
204    {
205        Request request = ContextHelper.getRequest(_context);
206        request.setAttribute("forceAbsoluteUrl", true);
207
208        RenderingContext currentContext = _renderingContextHandler.getRenderingContext();
209        _renderingContextHandler.setRenderingContext(RenderingContext.FRONT);
210
211        try
212        {
213            return _forumModule.getThreadUri(project, thread.getId());
214        }
215        finally
216        {
217            _renderingContextHandler.setRenderingContext(currentContext);
218        }
219    }
220}