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