001/* 002 * Copyright 2016 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.threads; 017 018import java.util.HashMap; 019import java.util.Map; 020import java.util.Set; 021 022import org.apache.cocoon.components.ContextHelper; 023import org.apache.cocoon.environment.Request; 024import org.apache.commons.lang.IllegalClassException; 025 026import org.ametys.cms.transformation.xslt.ResolveURIComponent; 027import org.ametys.core.right.RightManager.RightResult; 028import org.ametys.core.ui.Callable; 029import org.ametys.plugins.explorer.ExplorerNode; 030import org.ametys.plugins.explorer.resources.ModifiableResourceCollection; 031import org.ametys.plugins.explorer.resources.jcr.JCRResourcesCollectionFactory; 032import org.ametys.plugins.explorer.threads.actions.ThreadDAO; 033import org.ametys.plugins.repository.AmetysObject; 034import org.ametys.plugins.repository.AmetysObjectIterable; 035import org.ametys.plugins.repository.AmetysRepositoryException; 036import org.ametys.plugins.repository.ModifiableTraversableAmetysObject; 037import org.ametys.plugins.repository.metadata.ModifiableCompositeMetadata; 038import org.ametys.plugins.workspaces.AbstractWorkspaceModule; 039import org.ametys.plugins.workspaces.project.objects.Project; 040import org.ametys.runtime.i18n.I18nizableText; 041import org.ametys.web.repository.page.ModifiablePage; 042import org.ametys.web.repository.page.ModifiableZone; 043import org.ametys.web.repository.page.ModifiableZoneItem; 044import org.ametys.web.repository.page.Page; 045import org.ametys.web.repository.page.ZoneItem.ZoneType; 046 047import com.google.common.collect.ImmutableSet; 048 049/** 050 * ThreadDAO to interact with projects aware threads 051 */ 052public class ThreadWorkspaceModule extends AbstractWorkspaceModule 053{ 054 /** The id of thread module */ 055 public static final String THREAD_MODULE_ID = ThreadWorkspaceModule.class.getName(); 056 057 /** Tag on the main page holding the thread module */ 058 private static final String __THREAD_MODULE_TAG = "WORKSPACES_MODULE_THREAD"; 059 060 /** Workspaces threads node name */ 061 private static final String __WORKSPACES_THREADS_NODE_NAME = "threads"; 062 063 /** Module i18n title key */ 064 private static final String __MODULE_TITLE_KEY = "PLUGINS_WORKSPACES_PROJECT_SERVICE_MODULE_THREAD_LABEL"; 065 066 @Override 067 public String getId() 068 { 069 return THREAD_MODULE_ID; 070 } 071 072 @Override 073 protected String getModulePageName() 074 { 075 return "forum"; 076 } 077 078 @Override 079 public I18nizableText getModuleTitle() 080 { 081 return new I18nizableText("plugin." + _pluginName, __MODULE_TITLE_KEY); 082 } 083 084 @Override 085 protected I18nizableText getModulePageTitle() 086 { 087 return new I18nizableText("plugin." + _pluginName, "PLUGINS_WORKSPACES_PROJECT_WORKSPACE_PAGE_FORUM_TITLE"); 088 } 089 090 @Override 091 protected String getModuleTagName() 092 { 093 return __THREAD_MODULE_TAG; 094 } 095 096 @Override 097 protected void initializeModulePage(ModifiablePage forumPage) 098 { 099 ModifiableZone defaultZone = forumPage.createZone("default"); 100 101 String serviceId = "org.ametys.plugins.workspaces.module.Thread"; 102 ModifiableZoneItem defaultZoneItem = defaultZone.addZoneItem(); 103 defaultZoneItem.setType(ZoneType.SERVICE); 104 defaultZoneItem.setServiceId(serviceId); 105 106 ModifiableCompositeMetadata serviceMetadata = defaultZoneItem.getServiceParameters(); 107 108 serviceMetadata.setMetadata("xslt", _getDefaultXslt(serviceId)); 109 } 110 111 /** 112 * Get the URI of a thread in project'site 113 * @param project The project 114 * @param threadId The id of thread 115 * @param language The sitemap language 116 * @return The thread uri 117 */ 118 public String getThreadUri(Project project, String threadId, String language) 119 { 120 AmetysObjectIterable<Page> pages = getModulePages(project, language); 121 122 if (pages.getSize() > 0) 123 { 124 Page page = pages.iterator().next(); 125 126 StringBuilder sb = new StringBuilder(); 127 sb.append(ResolveURIComponent.resolve("page", page.getId())); 128 sb.append("#").append(threadId); 129 130 return sb.toString(); 131 } 132 133 return null; 134 } 135 136 /** 137 * Retrieve the current user rights on the thread module 138 * @return The map of rights 139 */ 140 @Callable 141 public Map<String, Object> getThreadModuleRights() 142 { 143 Map<String, Object> rights = new HashMap<>(); 144 145 Request request = ContextHelper.getRequest(_context); 146 String projectName = (String) request.getAttribute("projectName"); 147 Project project = _projectManager.getProject(projectName); 148 ModifiableResourceCollection threadRoot = getModuleRoot(project, false); 149 150 rights.put("threadAdd", threadRoot != null && _rightManager.hasRight(_currentUserProvider.getUser(), ThreadDAO.__RIGHTS_THREAD_ADD, threadRoot) == RightResult.RIGHT_ALLOW); 151 152 return rights; 153 } 154 155 @Override 156 public ModifiableResourceCollection getModuleRoot(Project project, boolean create) 157 { 158 try 159 { 160 ExplorerNode projectRootNode = project.getExplorerRootNode(); 161 162 if (projectRootNode instanceof ModifiableResourceCollection) 163 { 164 ModifiableResourceCollection projectRootNodeRc = (ModifiableResourceCollection) projectRootNode; 165 return _getAmetysObject(projectRootNodeRc, __WORKSPACES_THREADS_NODE_NAME, JCRResourcesCollectionFactory.RESOURCESCOLLECTION_NODETYPE, create); 166 } 167 else 168 { 169 throw new IllegalClassException(ModifiableResourceCollection.class, projectRootNode.getClass()); 170 } 171 } 172 catch (AmetysRepositoryException e) 173 { 174 throw new AmetysRepositoryException("Error getting the documents root node.", e); 175 } 176 } 177 178 179 /** 180 * Utility method to get or create an ametys object 181 * @param <A> A sub class of AmetysObject 182 * @param parent The parent object 183 * @param name The ametys object name 184 * @param type The ametys object type 185 * @param create True to create the object if it does not exist 186 * @return ametys object 187 * @throws AmetysRepositoryException if an repository error occurs 188 */ 189 protected <A extends AmetysObject> A _getAmetysObject(ModifiableTraversableAmetysObject parent, String name, String type, boolean create) throws AmetysRepositoryException 190 { 191 A object = null; 192 193 if (parent.hasChild(name)) 194 { 195 object = parent.getChild(name); 196 } 197 else if (create) 198 { 199 object = parent.createChild(name, type); 200 parent.saveChanges(); 201 } 202 203 return object; 204 } 205 206 @Override 207 public Set<String> getAllowedEventTypes() 208 { 209 return ImmutableSet.of("thread.created", "thread.post.created"); 210 } 211}