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.util.List;
019import java.util.Map;
020
021import org.apache.avalon.framework.context.Context;
022import org.apache.avalon.framework.context.ContextException;
023import org.apache.avalon.framework.context.Contextualizable;
024import org.apache.avalon.framework.service.ServiceException;
025import org.apache.avalon.framework.service.ServiceManager;
026import org.apache.cocoon.components.ContextHelper;
027import org.apache.cocoon.environment.Request;
028
029import org.ametys.cms.repository.CommentableAmetysObject;
030import org.ametys.cms.repository.comment.contributor.AbstractCommentNotifyMentionsObserver;
031import org.ametys.core.observation.Event;
032import org.ametys.core.right.RightManager;
033import org.ametys.core.ui.mail.StandardMailBodyHelper;
034import org.ametys.core.ui.mail.StandardMailBodyHelper.MailBodyBuilder;
035import org.ametys.core.user.User;
036import org.ametys.core.user.UserIdentity;
037import org.ametys.core.util.StringUtils;
038import org.ametys.plugins.repository.AmetysObject;
039import org.ametys.plugins.workspaces.WorkspacesHelper;
040import org.ametys.plugins.workspaces.documents.DocumentWorkspaceModule;
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.plugins.workspaces.tasks.TasksWorkspaceModule;
046import org.ametys.runtime.i18n.I18nizableText;
047import org.ametys.web.WebConstants;
048import org.ametys.web.renderingcontext.RenderingContext;
049import org.ametys.web.renderingcontext.RenderingContextHandler;
050
051/**
052 * Observer to send mails to mentioned users in contributor comments of workspaces objects
053 * @param <T> type of the {@link CommentableAmetysObject}
054 */
055public abstract class AbstractNotifyWorkspacesCommentMentionsObserver<T extends CommentableAmetysObject> extends AbstractCommentNotifyMentionsObserver<T> implements Contextualizable
056{
057    /** The right manager */
058    protected RightManager _rightManager;
059
060    /** The project manager */
061    protected ProjectManager _projectManager;
062
063    /** The task module */
064    protected TasksWorkspaceModule _taskModule;
065    
066    /** The document module */
067    protected DocumentWorkspaceModule _documentModule;
068
069    /** The Workspaces helper */
070    protected WorkspacesHelper _workspaceHelper;
071    
072    /** The context */
073    protected Context _context;
074    
075    /** The project rights helper */
076    protected ProjectRightHelper _projectRightsHelper;
077
078    /** The rendering context handler */
079    protected RenderingContextHandler _renderingContextHandler;
080    
081    @Override
082    public void service(ServiceManager manager) throws ServiceException
083    {
084        super.service(manager);
085        _rightManager = (RightManager) manager.lookup(RightManager.ROLE);
086        _projectManager = (ProjectManager) manager.lookup(ProjectManager.ROLE);
087        WorkspaceModuleExtensionPoint moduleManagerEP = (WorkspaceModuleExtensionPoint) manager.lookup(WorkspaceModuleExtensionPoint.ROLE);
088        _taskModule = moduleManagerEP.getModule(TasksWorkspaceModule.TASK_MODULE_ID);
089        _documentModule = moduleManagerEP.getModule(DocumentWorkspaceModule.DOCUMENT_MODULE_ID);
090        _workspaceHelper = (WorkspacesHelper) manager.lookup(WorkspacesHelper.ROLE);
091        _projectRightsHelper = (ProjectRightHelper) manager.lookup(ProjectRightHelper.ROLE);
092        _renderingContextHandler = (RenderingContextHandler) manager.lookup(RenderingContextHandler.ROLE);
093    }
094    
095    public void contextualize(Context context) throws ContextException
096    {
097        _context = context;
098    }
099
100    @Override
101    public void observe(Event event, Map<String, Object> transientVars) throws Exception
102    {
103        Map<String, Object> arguments = event.getArguments();
104        
105        AmetysObject ametysObject = _getAmetysObjectFromArguments(arguments);
106        Project project = _projectManager.getParentProject(ametysObject);
107        Request request = ContextHelper.getRequest(_context);
108        request.setAttribute(WebConstants.REQUEST_ATTR_SITE_NAME, project.getName());
109        super.observe(event, transientVars);
110    }
111    
112    /**
113     * Get the language of the project containing the given object
114     * @param project the project
115     * @return the language code
116     */
117    protected String _getLanguage(Project project)
118    {
119        return _workspaceHelper.getLang(project);
120    }
121    
122    /**
123     * Get the Ametys object from the event arguments
124     * @param arguments the event arguments
125     * @return the Ametys object
126     */
127    protected T _getAmetysObjectFromArguments(Map<String, Object> arguments)
128    {
129        String ametysObjectId = (String) arguments.get(org.ametys.plugins.explorer.ObservationConstants.ARGS_ID);
130        T ametysObject = _resolver.resolveById(ametysObjectId);
131        return ametysObject;
132    }
133
134    @Override
135    protected MailBodyBuilder getStandardMailBodyHelper()
136    {
137        return StandardMailBodyHelper.newHTMLBody();
138    }
139    
140    @Override
141    protected I18nizableText _getMailSubject(MentionableObject mentionableObject)
142    {
143        Project project = _projectManager.getParentProject(mentionableObject.ametysObject());
144        List<String> i18nParams = List.of(project.getTitle());
145        return new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_WORKSPACES_MENTION_MAIL_TITLE", i18nParams);
146    }
147    
148    @Override
149    protected I18nizableText _getMailTitle(MentionableObject mentionableObject)
150    {
151        AmetysObject ametysObject = mentionableObject.ametysObject();
152        Project project = _projectManager.getParentProject(ametysObject);
153
154        List<String> i18nParams = List.of(StringUtils.escapeHTML(project.getTitle()));
155        return new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_WORKSPACES_MENTION_MAIL_SUBJECT", i18nParams);
156    }
157    
158    @Override
159    protected boolean _canSendMailToMentionedUser(T ametysObject, User authorIdentity, UserIdentity mentionedUserIdentity)
160    {
161        Project project = _projectManager.getParentProject(ametysObject);
162        
163        return super._canSendMailToMentionedUser(ametysObject, authorIdentity, mentionedUserIdentity)
164            && _projectRightsHelper.hasReadAccessOnModule(project, _getModuleId(), mentionedUserIdentity);
165    }
166
167    /**
168     * Get the module id to check read access
169     * @return the module id
170     */
171    protected abstract String _getModuleId();
172
173    
174    /**
175     * Get the absolute URL of the given Ametys object in the context of the given project
176     * @param ametysObject the Ametys object
177     * @param project the project containing the Ametys object
178     * @return the absolute URL
179     */
180    protected String _getAbsoluteUrl(T ametysObject, Project project)
181    {
182        Request request = ContextHelper.getRequest(_context);
183        request.setAttribute("forceAbsoluteUrl", true);
184        
185        RenderingContext currentContext = _renderingContextHandler.getRenderingContext();
186        _renderingContextHandler.setRenderingContext(RenderingContext.FRONT);
187        
188        try
189        {
190            return getUrl(ametysObject, project);
191        }
192        finally
193        {
194            _renderingContextHandler.setRenderingContext(currentContext);
195        }
196    }
197
198    /**
199     * Get the URL of the given Ametys object in the context of the given project
200     * @param ametysObject the Ametys object
201     * @param project the project containing the Ametys object
202     * @return the URL (may be relative or absolute depending on the implementation)
203     */
204    protected abstract String getUrl(T ametysObject, Project project);
205
206    /**
207     * Get the common i18n parameters for the mail message
208     * @param mentionableObject the mentionable object
209     * @return the list of i18n parameters
210     */
211    protected List<String> _getCommonMailI18nParameters(MentionableObject mentionableObject)
212    {
213        @SuppressWarnings("unchecked")
214        T ametysObject = (T) mentionableObject.ametysObject();
215        User author = mentionableObject.author();
216        Project project = _projectManager.getParentProject(ametysObject);
217        List<String> i18nParams = List.of(StringUtils.escapeHTML(author.getFullName()), StringUtils.escapeHTML(_getAmetysObjectTitle(ametysObject)), StringUtils.escapeHTML(project.getTitle()));
218        return i18nParams;
219    }
220}