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 */
016
017package org.ametys.cms.repository.reports.ui;
018
019import java.util.ArrayList;
020import java.util.HashMap;
021import java.util.HashSet;
022import java.util.List;
023import java.util.Map;
024import java.util.Set;
025
026import org.apache.avalon.framework.service.ServiceException;
027import org.apache.avalon.framework.service.ServiceManager;
028
029import org.ametys.cms.ObservationConstants;
030import org.ametys.cms.content.ContentHelper;
031import org.ametys.cms.repository.Content;
032import org.ametys.cms.repository.ModifiableContent;
033import org.ametys.cms.repository.ReportableObject;
034import org.ametys.cms.repository.comment.Comment;
035import org.ametys.cms.repository.comment.CommentableContent;
036import org.ametys.core.observation.Event;
037import org.ametys.core.observation.ObservationManager;
038import org.ametys.core.right.RightManager.RightResult;
039import org.ametys.core.ui.Callable;
040import org.ametys.core.ui.StaticClientSideElement;
041import org.ametys.core.user.CurrentUserProvider;
042import org.ametys.core.user.UserIdentity;
043import org.ametys.plugins.repository.AmetysObjectResolver;
044import org.ametys.plugins.repository.UnknownAmetysObjectException;
045import org.ametys.plugins.repository.metadata.UnknownMetadataException;
046
047/**
048 * This client site elements creates a button representing the validation state of a content's comment
049 */
050public class ReportsClientSideElement extends StaticClientSideElement
051{
052    /** The Ametys object resolver */
053    protected AmetysObjectResolver _resolver;
054    /** The current user provider */
055    protected CurrentUserProvider _userProvider;
056    /** The observation manager */
057    protected ObservationManager _observationManager;
058    /** The content helper */
059    private ContentHelper _contentHelper;
060
061    @Override
062    public void service(ServiceManager smanager) throws ServiceException
063    {
064        super.service(smanager);
065        _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE);
066        _userProvider = (CurrentUserProvider) smanager.lookup(CurrentUserProvider.ROLE);
067        _observationManager = (ObservationManager) smanager.lookup(ObservationManager.ROLE);
068        _contentHelper = (ContentHelper) smanager.lookup(ContentHelper.ROLE);
069    }
070    
071    /**
072     * Ignore reports on objects (contents or comments) when it is possible.
073     * @param reportedObjects the objects where to ignore reports
074     * @return the JSON result with contents and comments with ignored reports or not
075     */
076    @Callable
077    public Map<String, Object> ignoreReports(List<Map<String, String>> reportedObjects)
078    {
079        List<Map<String, Object>> contentsWithIgnoredReports = new ArrayList<>();
080        List<Map<String, Object>> commentsWithIgnoredReports = new ArrayList<>();
081        List<Map<String, Object>> unknownContents = new ArrayList<>();
082        List<Map<String, Object>> unknownComments = new ArrayList<>();
083        List<Map<String, Object>> uncommentableContents = new ArrayList<>();
084        List<Map<String, Object>> unreportableContents = new ArrayList<>();
085        List<Map<String, Object>> noRightContents = new ArrayList<>();
086        
087        Map<String, Content> resolvedContentsById = new HashMap<>();
088        Set<ModifiableContent> modifiedContents = new HashSet<>();
089        
090        UserIdentity currentUser = _userProvider.getUser();
091        
092        for (Map<String, String> reportedObject : reportedObjects)
093        {
094            String contentId = reportedObject.get("contentId");
095            
096            try
097            {
098                Content content = resolvedContentsById.get(contentId);
099                if (content == null)
100                {
101                    content = _resolver.resolveById(contentId);
102                    resolvedContentsById.put(contentId, content);
103                }
104                
105                Map<String, Object> contentParams = _getContentParameters(content);
106                
107                if (_rightManager.hasRight(currentUser, "CMS_Rights_CommentModerate", content) == RightResult.RIGHT_ALLOW)
108                {
109                    if (reportedObject.containsKey("commentId"))
110                    {
111                        String commentId = reportedObject.get("commentId");
112                        Map<String, Object> commentParams = _getCommentParameters(commentId, content);
113                        
114                        if (content instanceof CommentableContent)
115                        {
116                            try
117                            {
118                                CommentableContent cContent = (CommentableContent) content;
119                                boolean ignored = _ignoreReportsOnComment(commentId, cContent, currentUser);
120                                if (ignored)
121                                {
122                                    modifiedContents.add(cContent);
123                                    commentsWithIgnoredReports.add(commentParams);
124                                }
125                            }
126                            catch (UnknownMetadataException e)
127                            {
128                                getLogger().error("Can not ignore reports on a non existing comment", e);
129                                unknownComments.add(commentParams);
130                            }
131                        }
132                        else
133                        {
134                            getLogger().error("Can not ignore reports on a comment on a non commentable content");
135                            uncommentableContents.add(contentParams);
136                        }
137                    }
138                    else
139                    {
140                        if (content instanceof ReportableObject && content instanceof ModifiableContent)
141                        {
142                            boolean ignored = _ignoreReportsOnContent((ReportableObject) content, currentUser);
143                            if (ignored)
144                            {
145                                modifiedContents.add((ModifiableContent) content);
146                                contentsWithIgnoredReports.add(contentParams);
147                            }
148                        }
149                        else
150                        {
151                            getLogger().error("Can not ignore reports on a non reportable content");
152                            unreportableContents.add(contentParams);
153                        }
154                    }
155                }
156                else
157                {
158                    getLogger().error("User '" + currentUser + "' does not have right to ignore reports on content '" + content.getId() + "'");
159                    noRightContents.add(contentParams);
160                }
161            }
162            catch (UnknownAmetysObjectException e)
163            {
164                getLogger().error("Can not ignore reports on a comment on a non existing content", e);
165                unknownContents.add(Map.of("id", contentId));
166            }
167        }
168
169        for (ModifiableContent modifiedContent : modifiedContents)
170        {
171            modifiedContent.saveChanges();
172        }
173        
174        return Map.of("contents-with-ignored-reports", contentsWithIgnoredReports,
175            "comments-with-ignored-reports", commentsWithIgnoredReports,
176            "unknown-contents", unknownContents,
177            "unknown-comments", unknownComments,
178            "uncommentable-contents", uncommentableContents,
179            "unreportable-contents", unreportableContents,
180            "noright-contents", noRightContents);
181    }
182
183    /**
184     * Retrieves the given content's parameters
185     * @param content the content
186     * @return the content's parameters
187     */
188    protected Map<String, Object> _getContentParameters(Content content)
189    {
190        Map<String, Object> contentParams = new HashMap<>();
191        contentParams.put("id", content.getId());
192        contentParams.put("title", _contentHelper.getTitle(content));
193        return contentParams;
194    }
195
196    /**
197     * Ignores the reports on the given content
198     * @param content the content
199     * @param currentUser the current user
200     * @return <code>true</code> if there are reports that have been ignored, <code>false</code> otherwise
201     */
202    protected boolean _ignoreReportsOnContent(ReportableObject content, UserIdentity currentUser)
203    {
204        if (content.getReportsCount() > 0)
205        {
206            content.clearReports();
207            
208            Map<String, Object> eventParams = new HashMap<>();
209            eventParams.put(ObservationConstants.ARGS_CONTENT, content);
210            _observationManager.notify(new Event(ObservationConstants.EVENT_CONTENT_IGNORE_REPORTS, currentUser, eventParams));
211            
212            return true;
213        }
214        else
215        {
216            return false;
217        }
218    }
219
220    /**
221     * Retrieves the given comment's parameters
222     * @param commentId the comment identifier
223     * @param content the content of the comment
224     * @return the comment's parameters
225     */
226    protected Map<String, Object> _getCommentParameters(String commentId, Content content)
227    {
228        Map<String, Object> commentParams = new HashMap<>();
229        commentParams.put("id", commentId);
230        commentParams.put("contentId", content.getId());
231        commentParams.put("contentTitle", _contentHelper.getTitle(content));
232        return commentParams;
233    }
234
235    /**
236     * Ignores the reports on the given comment
237     * @param commentId the identifier of the comment
238     * @param content the content of the comment
239     * @param currentUser the current user
240     * @return <code>true</code> if there are reports that have been ignored, <code>false</code> otherwise
241     */
242    protected boolean _ignoreReportsOnComment(String commentId, CommentableContent content, UserIdentity currentUser)
243    {
244        Comment comment = content.getComment(commentId);
245        
246        if (comment.getReportsCount() > 0)
247        {
248            comment.clearReports();
249            
250            Map<String, Object> eventParams = new HashMap<>();
251            eventParams.put(ObservationConstants.ARGS_CONTENT, content);
252            eventParams.put(ObservationConstants.ARGS_COMMENT, comment);
253            _observationManager.notify(new Event(ObservationConstants.EVENT_CONTENT_COMMENT_IGNORE_REPORTS, currentUser, eventParams));
254            
255            return true;
256        }
257        else
258        {
259            return false;
260        }
261    }
262}