001/* 002 * Copyright 2010 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.web.clientsideelement; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.HashSet; 021import java.util.List; 022import java.util.Map; 023import java.util.Set; 024 025import org.apache.avalon.framework.configuration.Configuration; 026import org.apache.avalon.framework.configuration.ConfigurationException; 027import org.apache.avalon.framework.configuration.DefaultConfiguration; 028import org.apache.avalon.framework.service.ServiceException; 029import org.apache.avalon.framework.service.ServiceManager; 030import org.slf4j.LoggerFactory; 031 032import org.ametys.core.ui.Callable; 033import org.ametys.core.ui.StaticClientSideElement; 034import org.ametys.core.util.I18nUtils; 035import org.ametys.plugins.repository.AmetysObjectResolver; 036import org.ametys.runtime.i18n.I18nizableText; 037import org.ametys.runtime.plugin.component.ThreadSafeComponentManager; 038import org.ametys.web.repository.page.ModifiablePage; 039import org.ametys.web.repository.page.Page; 040import org.ametys.web.repository.page.Page.PageType; 041import org.ametys.web.repository.site.SiteManager; 042import org.ametys.web.skin.Skin; 043import org.ametys.web.skin.SkinTemplate; 044import org.ametys.web.skin.SkinsManager; 045import org.ametys.web.skin.TemplatesAssignmentHandler; 046 047/** 048 * This element finally creates a gallery button with one item per template 049 */ 050public class TemplatesMenu extends AbstractPageMenu 051{ 052 /** The plugin in which are the templates resources (messages and icons). */ 053 protected static final String _RESOURCES_PLUGIN = "web"; 054 055 /** The skins manager */ 056 protected SkinsManager _skinsManager; 057 /** The template assignment handler */ 058 protected TemplatesAssignmentHandler _templatesAssignmentHandler; 059 /** The site manager */ 060 protected SiteManager _siteManager; 061 /** The i18n utils */ 062 protected I18nUtils _i18nUtils; 063 064 @Override 065 public void service(ServiceManager smanager) throws ServiceException 066 { 067 super.service(smanager); 068 069 _skinsManager = (SkinsManager) smanager.lookup(SkinsManager.ROLE); 070 _templatesAssignmentHandler = (TemplatesAssignmentHandler) smanager.lookup(TemplatesAssignmentHandler.ROLE); 071 _siteManager = (SiteManager) smanager.lookup(SiteManager.ROLE); 072 _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE); 073 _i18nUtils = (I18nUtils) smanager.lookup(I18nUtils.ROLE); 074 } 075 076 /** 077 * Get the available templates for pages 078 * @param pageIds The ids of pages 079 * @return the list of templates' name 080 */ 081 @Callable 082 public Map<String, Object> getStatus (List<String> pageIds) 083 { 084 Map<String, Object> result = new HashMap<>(); 085 086 result.put("nomodifiable-pages", new ArrayList<Map<String, Object>>()); 087 result.put("noright-pages", new ArrayList<Map<String, Object>>()); 088 result.put("allright-pages", new ArrayList<Map<String, Object>>()); 089 090 Set<String> availableTemplateIds = new HashSet<>(); 091 for (String pageId : pageIds) 092 { 093 Page page = _resolver.resolveById(pageId); 094 availableTemplateIds.addAll(_templatesAssignmentHandler.getAvailablesTemplates(page)); 095 096 if (!(page instanceof ModifiablePage)) 097 { 098 Map<String, Object> pageParams = getPageDefaultParameters(page); 099 pageParams.put("description", getNoModifiablePageDescription(page)); 100 101 @SuppressWarnings("unchecked") 102 List<Map<String, Object>> norightPages = (List<Map<String, Object>>) result.get("nomodifiable-pages"); 103 norightPages.add(pageParams); 104 } 105 else if (!hasRight(page)) 106 { 107 Map<String, Object> pageParams = getPageDefaultParameters(page); 108 pageParams.put("description", getNoRightPageDescription(page)); 109 110 @SuppressWarnings("unchecked") 111 List<Map<String, Object>> norightPages = (List<Map<String, Object>>) result.get("noright-pages"); 112 norightPages.add(pageParams); 113 } 114 else 115 { 116 Map<String, Object> pageParams = getPageDefaultParameters(page); 117 pageParams.put("description", getAllRightPageDescription(page)); 118 if (page.getType() == PageType.CONTAINER) 119 { 120 pageParams.put("template", page.getTemplate()); 121 } 122 123 @SuppressWarnings("unchecked") 124 List<Map<String, Object>> allRightPages = (List<Map<String, Object>>) result.get("allright-pages"); 125 allRightPages.add(pageParams); 126 } 127 } 128 129 result.put("templates", new ArrayList<>(availableTemplateIds)); 130 return result; 131 } 132 133 @Override 134 public List<Script> getScripts(boolean ignoreRights, Map<String, Object> contextParameters) 135 { 136 String siteName = (String) contextParameters.get("siteName"); 137 138 String skinId = _siteManager.getSite(siteName).getSkinId(); 139 Skin skin = _skinsManager.getSkin(skinId); 140 141 if (skin.getTemplates().size() == 0) 142 { 143 // Hide menu if there is no template 144 return new ArrayList<>(); 145 } 146 147 return super.getScripts(ignoreRights, contextParameters); 148 } 149 150 151 @Override 152 protected void _getGalleryItems(Map<String, Object> parameters, Map<String, Object> contextualParameters) 153 { 154 try 155 { 156 _lazyInitializeTemplateGallery(contextualParameters); 157 } 158 catch (Exception e) 159 { 160 throw new IllegalStateException("Unable to lookup client side element local components", e); 161 } 162 163 super._getGalleryItems(parameters, contextualParameters); 164 } 165 166 private void _lazyInitializeTemplateGallery(Map<String, Object> contextualParameters) throws ConfigurationException 167 { 168 // We need to dispose and use a new manager each time as items depends on the current site 169 // FIXME make a smart cache by skin ? The cache has to be clear when the skin is updated 170 _galleryItemManager.dispose(); 171 172 _galleryItemManager = new ThreadSafeComponentManager<>(); 173 _galleryItemManager.setLogger(LoggerFactory.getLogger("cms.plugin.threadsafecomponent")); 174 _galleryItemManager.service(_smanager); 175 176 String siteName = (String) contextualParameters.get("siteName"); 177 178 String skinId = _siteManager.getSite(siteName).getSkinId(); 179 Set<String> availablesTemplates = _templatesAssignmentHandler.getAvailablesTemplates(skinId); 180 181 Skin skin = _skinsManager.getSkin(skinId); 182 183 if (availablesTemplates.size() > 0) 184 { 185 GalleryItem galleryItem = new GalleryItem(); 186 187 GalleryGroup galleryGroup = new GalleryGroup(new I18nizableText("plugin." + _RESOURCES_PLUGIN, "PLUGINS_WEB_PAGE_TEMPLATESMENU_GROUP_LABEL")); 188 galleryItem.addGroup(galleryGroup); 189 190 for (String templateId : availablesTemplates) 191 { 192 String id = this.getId() + "." + templateId; 193 194 SkinTemplate template = skin.getTemplate(templateId); 195 Configuration conf = _getTemplateItemConfiguration (id, template); 196 _galleryItemManager.addComponent(_pluginName, null, id, StaticClientSideElement.class, conf); 197 galleryGroup.addItem(new UnresolvedItem(id, true)); 198 } 199 200 _galleryItems.add(galleryItem); 201 } 202 203 if (_galleryItems.size() > 0) 204 { 205 try 206 { 207 _galleryItemManager.initialize(); 208 } 209 catch (Exception e) 210 { 211 throw new ConfigurationException("Unable to lookup parameter local components", e); 212 } 213 } 214 } 215 216 /** 217 * Get the configuration for a language item 218 * @param itemId The item id 219 * @param template The template used for the item 220 * @return The configuration 221 */ 222 protected Configuration _getTemplateItemConfiguration (String itemId, SkinTemplate template) 223 { 224 DefaultConfiguration conf = new DefaultConfiguration("extension"); 225 conf.setAttribute("id", itemId); 226 227 DefaultConfiguration classConf = new DefaultConfiguration("class"); 228 classConf.setAttribute("name", "Ametys.ribbon.element.ui.ButtonController"); 229 230 // Label 231 DefaultConfiguration labelConf = new DefaultConfiguration("label"); 232 labelConf.setValue(_i18nUtils.translate(template.getLabel())); 233 classConf.addChild(labelConf); 234 235 // Description 236 DefaultConfiguration descConf = new DefaultConfiguration("description"); 237 descConf.setValue(_i18nUtils.translate(template.getDescription())); 238 classConf.addChild(descConf); 239 240 // Name 241 DefaultConfiguration nameConf = new DefaultConfiguration("name"); 242 nameConf.setValue(template.getId()); 243 classConf.addChild(nameConf); 244 245 // Icons 246 DefaultConfiguration iconSmallConf = new DefaultConfiguration("icon-small"); 247 iconSmallConf.setValue(template.getSmallImage()); 248 classConf.addChild(iconSmallConf); 249 DefaultConfiguration iconMediumConf = new DefaultConfiguration("icon-medium"); 250 iconMediumConf.setValue(template.getMediumImage()); 251 classConf.addChild(iconMediumConf); 252 DefaultConfiguration iconLargeConf = new DefaultConfiguration("icon-large"); 253 iconLargeConf.setValue(template.getLargeImage()); 254 classConf.addChild(iconLargeConf); 255 256 // Toggle button 257 DefaultConfiguration toggleEnabledConf = new DefaultConfiguration("toggle-enabled"); 258 toggleEnabledConf.setValue("true"); 259 classConf.addChild(toggleEnabledConf); 260 261 // Common configuration 262 @SuppressWarnings("unchecked") 263 Map<String, Object> commonConfig = (Map<String, Object>) this._script.getParameters().get("items-config"); 264 for (String tagName : commonConfig.keySet()) 265 { 266 DefaultConfiguration c = new DefaultConfiguration(tagName); 267 c.setValue(String.valueOf(commonConfig.get(tagName))); 268 classConf.addChild(c); 269 } 270 271 conf.addChild(classConf); 272 return conf; 273 } 274 275}