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}