001/* 002 * Copyright 2017 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.about; 017 018import java.util.HashMap; 019import java.util.Map; 020import java.util.Set; 021 022import org.apache.avalon.framework.service.ServiceException; 023import org.apache.avalon.framework.service.ServiceManager; 024import org.apache.commons.lang.IllegalClassException; 025import org.apache.commons.lang.StringUtils; 026 027import org.ametys.cms.FilterNameHelper; 028import org.ametys.cms.repository.Content; 029import org.ametys.cms.repository.ModifiableWorkflowAwareContent; 030import org.ametys.plugins.explorer.ExplorerNode; 031import org.ametys.plugins.explorer.resources.ModifiableResourceCollection; 032import org.ametys.plugins.explorer.resources.jcr.JCRResourcesCollectionFactory; 033import org.ametys.plugins.repository.AmetysRepositoryException; 034import org.ametys.plugins.workflow.AbstractWorkflowComponent; 035import org.ametys.plugins.workflow.support.WorkflowProvider; 036import org.ametys.plugins.workflow.support.WorkflowProvider.AmetysObjectWorkflow; 037import org.ametys.plugins.workspaces.AbstractWorkspaceModule; 038import org.ametys.plugins.workspaces.WorkspacesConstants; 039import org.ametys.plugins.workspaces.project.ProjectConstants; 040import org.ametys.plugins.workspaces.project.objects.Project; 041import org.ametys.runtime.i18n.I18nizableText; 042import org.ametys.web.repository.page.ModifiablePage; 043import org.ametys.web.repository.page.ModifiableZone; 044import org.ametys.web.repository.page.ModifiableZoneItem; 045import org.ametys.web.repository.page.Page; 046import org.ametys.web.repository.page.Page.PageType; 047import org.ametys.web.repository.page.ZoneItem.ZoneType; 048import org.ametys.web.repository.site.Site; 049import org.ametys.web.skin.Skin; 050import org.ametys.web.skin.SkinTemplate; 051import org.ametys.web.skin.SkinTemplateZone; 052import org.ametys.web.workflow.CreateContentFunction; 053 054import com.opensymphony.workflow.WorkflowException; 055 056/** 057 * Manager for the About module 058 */ 059public class AboutWorkspaceModule extends AbstractWorkspaceModule 060{ 061 /** Avalon ROLE */ 062 public static final String ABOUT_MODULE_ID = AboutWorkspaceModule.class.getName(); 063 064 /** Workspaces tasks list node name */ 065 private static final String __WORKSPACES_ABOUT_NODE_NAME = "about"; 066 067 /** The initial workflow action id */ 068 private static final int __INIT_WORKFLOW_ACTION_ID = 16; 069 070 /** The workflow provider */ 071 protected WorkflowProvider _workflowProvider; 072 073 @Override 074 public void service(ServiceManager manager) throws ServiceException 075 { 076 super.service(manager); 077 _workflowProvider = (WorkflowProvider) manager.lookup(WorkflowProvider.ROLE); 078 } 079 080 @Override 081 public String getId() 082 { 083 return ABOUT_MODULE_ID; 084 } 085 086 @Override 087 public String getModuleName() 088 { 089 return __WORKSPACES_ABOUT_NODE_NAME; 090 } 091 092 public int getOrder() 093 { 094 return ORDER_ABOUT; 095 } 096 097 @Override 098 protected String getModulePageName() 099 { 100 return "about"; 101 } 102 103 public I18nizableText getModuleTitle() 104 { 105 return new I18nizableText("plugin." + _pluginName, "PLUGINS_WORKSPACES_PROJECT_SERVICE_MODULE_ABOUT_LABEL"); 106 } 107 public I18nizableText getModuleDescription() 108 { 109 return new I18nizableText("plugin." + _pluginName, "PLUGINS_WORKSPACES_PROJECT_SERVICE_MODULE_ABOUT_DESCRIPTION"); 110 } 111 @Override 112 protected I18nizableText getModulePageTitle() 113 { 114 return new I18nizableText("plugin." + _pluginName, "PLUGINS_WORKSPACES_PROJECT_WORKSPACE_PAGE_ABOUT_TITLE"); 115 } 116 117 @Override 118 protected String getModulePageTemplate() 119 { 120 return ProjectConstants.ABOUT_TEMPLATE; 121 } 122 123 @Override 124 protected void initializeModulePage(ModifiablePage page) 125 { 126 String contentTitle = StringUtils.defaultIfEmpty(_i18nUtils.translate(getModulePageTitle(), page.getSitemapName()), "Missing title"); 127 _initializeAboutDefaultZone(page, page.getSite(), page.getSitemapName(), contentTitle); 128 } 129 130 /** 131 * Initialize the default zone for the about page 132 * @param aboutPage The about page 133 * @param site The site 134 * @param sitemapName The sitemap name 135 * @param title The content title 136 */ 137 protected void _initializeAboutDefaultZone(ModifiablePage aboutPage, Site site, String sitemapName, String title) 138 { 139 ModifiableZone defaultZone = aboutPage.createZone("default"); 140 141 ModifiableZoneItem defaultZoneItem = defaultZone.addZoneItem(); 142 defaultZoneItem.setType(ZoneType.CONTENT); 143 144 try 145 { 146 ModifiableWorkflowAwareContent content = createAboutContent(site, sitemapName, title); 147 defaultZoneItem.setContent(content); 148 content.saveChanges(); 149 } 150 catch (WorkflowException e) 151 { 152 getLogger().error("Unable to initialize the About page content for the new workspace, the about page will not be editable until the content is manually created in the BackOffice", e); 153 } 154 } 155 156 /** 157 * Retrieves the rights for the current user in the project 158 * @return The project 159 */ 160 /** 161 * Create the about content 162 * @param site The site 163 * @param sitemapName the name of the sitemap 164 * @param title The content title 165 * @return The content 166 * @throws WorkflowException if an error occurred 167 */ 168 public ModifiableWorkflowAwareContent createAboutContent(Site site, String sitemapName, String title) throws WorkflowException 169 { 170 Map<String, Object> inputs = new HashMap<>(); 171 inputs.put(org.ametys.cms.workflow.CreateContentFunction.CONTENT_TITLE_KEY, title); 172 inputs.put(org.ametys.cms.workflow.CreateContentFunction.CONTENT_NAME_KEY, FilterNameHelper.filterName(title)); 173 inputs.put(org.ametys.cms.workflow.CreateContentFunction.CONTENT_TYPES_KEY, new String[] {WorkspacesConstants.ABOUT_CONTENT_TYPE}); 174 inputs.put(org.ametys.cms.workflow.CreateContentFunction.CONTENT_LANGUAGE_KEY, sitemapName); 175 inputs.put(CreateContentFunction.SITE_KEY, site.getName()); 176 177 AmetysObjectWorkflow workflow = _workflowProvider.getAmetysObjectWorkflow(); 178 workflow.initialize(WorkspacesConstants.CONTENT_WORKFLOW_NAME, __INIT_WORKFLOW_ACTION_ID, inputs); 179 180 @SuppressWarnings("unchecked") 181 Map<String, Object> results = (Map<String, Object>) inputs.get(AbstractWorkflowComponent.RESULT_MAP_KEY); 182 ModifiableWorkflowAwareContent content = (ModifiableWorkflowAwareContent) results.get(Content.class.getName()); 183 184 return content; 185 } 186 187 188 189 190 /** 191 * Initialize the new about page 192 * @param aboutPage The page 193 * @param site The site 194 * @param sitemapName The sitemap name 195 * @param title The page title 196 * @param parentPage The parent page 197 */ 198 protected void _initializeAboutPage(ModifiablePage aboutPage, Site site, String sitemapName, String title, Page parentPage) 199 { 200 Skin skin = _skinsManager.getSkin(site.getSkinId()); 201 SkinTemplate template = skin.getTemplate(ProjectConstants.ABOUT_TEMPLATE); 202 203 if (template != null) 204 { 205 // Set the type and template. 206 aboutPage.setType(PageType.CONTAINER); 207 aboutPage.setTemplate(ProjectConstants.ABOUT_TEMPLATE); 208 209 // Initialize the zones. 210 Map<String, SkinTemplateZone> templateZones = template.getZones(); 211 if (templateZones.containsKey("default")) 212 { 213 _initializeAboutDefaultZone(aboutPage, site, sitemapName, title); 214 } 215 else 216 { 217 getLogger().error("A 'default' zone is mandatory in the about template!"); 218 return; 219 } 220 221 // Tag page as a sitemap section. 222 aboutPage.tag("SECTION"); 223 } 224 else 225 { 226 String errorMsg = String.format( 227 "The project workspace '%s' was created with the skin '%s' which doesn't possess the mandatory template '%s'.\nThe '%s' page of the project workspace could not be initialized.", 228 site.getName(), site.getSkinId(), ProjectConstants.ABOUT_TEMPLATE, aboutPage.getName()); 229 230 getLogger().error(errorMsg); 231 } 232 } 233 234 @Override 235 public ModifiableResourceCollection getModuleRoot(Project project, boolean create) 236 { 237 try 238 { 239 ExplorerNode projectRootNode = project.getExplorerRootNode(); 240 241 if (projectRootNode instanceof ModifiableResourceCollection) 242 { 243 ModifiableResourceCollection projectRootNodeRc = (ModifiableResourceCollection) projectRootNode; 244 return _getAmetysObject(projectRootNodeRc, __WORKSPACES_ABOUT_NODE_NAME, JCRResourcesCollectionFactory.RESOURCESCOLLECTION_NODETYPE, create); 245 } 246 else 247 { 248 throw new IllegalClassException(ModifiableResourceCollection.class, projectRootNode.getClass()); 249 } 250 } 251 catch (AmetysRepositoryException e) 252 { 253 throw new AmetysRepositoryException("Error getting the documents root node.", e); 254 } 255 } 256 257 @Override 258 public Set<String> getAllowedEventTypes() 259 { 260 return Set.of(); 261 } 262}