001/* 002 * Copyright 2020 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; 017 018import java.util.ArrayList; 019import java.util.List; 020import java.util.Map; 021import java.util.Objects; 022import java.util.Optional; 023 024import org.apache.avalon.framework.component.Component; 025import org.apache.avalon.framework.context.Context; 026import org.apache.avalon.framework.context.ContextException; 027import org.apache.avalon.framework.context.Contextualizable; 028import org.apache.avalon.framework.service.ServiceException; 029import org.apache.avalon.framework.service.ServiceManager; 030import org.apache.avalon.framework.service.Serviceable; 031import org.apache.cocoon.Constants; 032import org.apache.cocoon.components.ContextHelper; 033import org.apache.cocoon.environment.Request; 034import org.apache.commons.lang3.StringUtils; 035 036import org.ametys.cms.content.indexing.solr.SolrResourceGroupedMimeTypes; 037import org.ametys.core.user.UserIdentity; 038import org.ametys.core.util.URIUtils; 039import org.ametys.plugins.explorer.resources.Resource; 040import org.ametys.plugins.repository.tag.TaggableAmetysObject; 041import org.ametys.plugins.workspaces.project.ProjectManager; 042import org.ametys.plugins.workspaces.project.objects.Project; 043import org.ametys.plugins.workspaces.tags.ProjectTagsDAO; 044import org.ametys.runtime.plugin.component.AbstractLogEnabled; 045import org.ametys.web.URIPrefixHandler; 046import org.ametys.web.WebHelper; 047import org.ametys.web.repository.site.Site; 048import org.ametys.web.repository.site.SiteManager; 049import org.ametys.web.repository.sitemap.Sitemap; 050 051/** 052 * Utility classes for workspaces 053 * 054 */ 055public class WorkspacesHelper extends AbstractLogEnabled implements Component, Serviceable, Contextualizable 056{ 057 /** Avalon role */ 058 public static final String ROLE = WorkspacesHelper.class.getName(); 059 060 /** 061 * Enumeration for file type 062 */ 063 public enum FileType 064 { 065 /** Text document */ 066 TEXT, 067 /** PDF document */ 068 PDF, 069 /** Spreadsheet */ 070 SPREADSHEET, 071 /** Presentation */ 072 PRES, 073 /** Image */ 074 IMAGE, 075 /** Video */ 076 VIDEO, 077 /** Audio */ 078 AUDIO, 079 /** Archive */ 080 ARCHIVE, 081 /** Unknown type */ 082 UNKNOWN 083 } 084 085 private Context _context; 086 private org.apache.cocoon.environment.Context _cocoonContext; 087 private URIPrefixHandler _prefixHandler; 088 private ProjectTagsDAO _projectTagsDAO; 089 private SiteManager _siteManager; 090 private ProjectManager _projectManager; 091 092 public void contextualize(Context context) throws ContextException 093 { 094 _context = context; 095 _cocoonContext = (org.apache.cocoon.environment.Context) _context.get(Constants.CONTEXT_ENVIRONMENT_CONTEXT); 096 } 097 098 public void service(ServiceManager smanager) throws ServiceException 099 { 100 _prefixHandler = (URIPrefixHandler) smanager.lookup(URIPrefixHandler.ROLE); 101 _projectTagsDAO = (ProjectTagsDAO) smanager.lookup(ProjectTagsDAO.ROLE); 102 _projectManager = (ProjectManager) smanager.lookup(ProjectManager.ROLE); 103 _siteManager = (SiteManager) smanager.lookup(SiteManager.ROLE); 104 } 105 106 /** 107 * Determines if the resource file is an image 108 * @param file the resource 109 * @return true if the resource file is an image 110 */ 111 public boolean isImage(Resource file) 112 { 113 return SolrResourceGroupedMimeTypes.getGroup(file.getMimeType()) 114 .map(groupMimeType -> FileType.IMAGE == FileType.valueOf(groupMimeType.toUpperCase())) 115 .orElse(false); 116 } 117 118 /** 119 * Get the file type of a resource file 120 * @param file the resource 121 * @return the {@link FileType} 122 */ 123 public FileType getFileType(Resource file) 124 { 125 Optional<String> group = SolrResourceGroupedMimeTypes.getGroup(file.getMimeType()); 126 127 return group 128 .map(groupMimeType -> FileType.valueOf(groupMimeType.toUpperCase())) 129 .orElse(FileType.UNKNOWN); 130 } 131 132 /** 133 * Get the file type of a resource from its name 134 * @param filename the resource's name 135 * @return the {@link FileType} 136 */ 137 public FileType getFileType(String filename) 138 { 139 String mimeType = _cocoonContext.getMimeType(filename); 140 Optional<String> group = SolrResourceGroupedMimeTypes.getGroup(mimeType); 141 142 return group 143 .map(groupMimeType -> FileType.valueOf(groupMimeType.toUpperCase())) 144 .orElse(FileType.UNKNOWN); 145 } 146 147 /** 148 * Get user avatar 149 * @param userIdentity the user identity 150 * @param lang the lang for user's content 151 * @param size the size in pixel of image 152 * @return the avatar url 153 */ 154 public String getAvatar(UserIdentity userIdentity, String lang, int size) 155 { 156 StringBuilder sb = new StringBuilder(); 157 158 String siteName = WebHelper.getSiteName(_getRequest()); 159 sb.append(_prefixHandler.getUriPrefix(siteName)) 160 .append("/_plugins/user-directory/user/") 161 .append(userIdentity.getPopulationId()) 162 .append("/") 163 .append(URIUtils.encodePath(userIdentity.getLogin())) 164 .append("/image_") 165 .append(size) 166 .append("?lang=") 167 .append(lang); 168 169 return sb.toString(); 170 } 171 172 private Request _getRequest() 173 { 174 return ContextHelper.getRequest(_context); 175 } 176 177 /** 178 * Get current project from request 179 * @return the current project or null if not found. 180 */ 181 public Project getProjectFromRequest() 182 { 183 Request request = _getRequest(); 184 String projectName = (String) request.getAttribute(WorkspacesConstants.REQUEST_ATTR_PROJECT_NAME); 185 186 if (StringUtils.isNotEmpty(projectName)) 187 { 188 return _projectManager.getProject(projectName); 189 } 190 191 String siteName = WebHelper.getSiteName(request); 192 if (StringUtils.isNotEmpty(siteName) && _siteManager.hasSite(siteName)) 193 { 194 Site site = _siteManager.getSite(siteName); 195 List<Project> projects = _projectManager.getProjectsForSite(site); 196 if (!projects.isEmpty()) 197 { 198 return projects.get(0); 199 } 200 } 201 202 return null; 203 } 204 205 /** 206 * Handle tags for the edition of a TaggableAmetysObject 207 * @param taggableAmetysObject the object to edit 208 * @param tags the tags 209 * @return the created tags 210 */ 211 public List<Map<String, Object>> handleTags(TaggableAmetysObject taggableAmetysObject, List<Object> tags) 212 { 213 List<String> createdTags = new ArrayList<>(); 214 List<Map<String, Object>> createdTagsJson = new ArrayList<>(); 215 // Tag new tags 216 for (Object tag : tags) 217 { 218 // Tag doesn't exist so create the tag 219 if (tag instanceof Map) 220 { 221 @SuppressWarnings("unchecked") 222 String tagText = (String) ((Map<String, Object>) tag).get("text"); 223 List<Map<String, Object>> newTags = _projectTagsDAO.addTags(new String[] {tagText}); 224 String newTag = (String) newTags.get(0).get("name"); 225 taggableAmetysObject.tag(newTag); 226 createdTags.add(newTag); 227 createdTagsJson.addAll(newTags); 228 } 229 else 230 { 231 taggableAmetysObject.tag((String) tag); 232 } 233 } 234 // Untag unused tags 235 for (String tag : taggableAmetysObject.getTags()) 236 { 237 if (!tags.contains(tag) && !createdTags.contains(tag)) 238 { 239 taggableAmetysObject.untag(tag); 240 } 241 } 242 return createdTagsJson; 243 } 244 245 /** 246 * Get the lang for this project, or en if none found 247 * @param project the project to check 248 * @return a lang in this project 249 */ 250 public String getLang(Project project) 251 { 252 /* 253 * get the site, then the sitemaps (transformed back to a stream of sitemap) 254 * then get the name 255 * return the 1st one, or "en" by default if none is available, or if the site could not be found 256 */ 257 258 Site site = project.getSite(); 259 260 if (site != null) 261 { 262 return site.getSitemaps() 263 .stream() 264 .filter(Objects::nonNull) 265 .map(Sitemap::getName) 266 .findFirst() 267 .orElse("en"); 268 } 269 else 270 { 271 return "en"; 272 } 273 } 274}