001/* 002 * Copyright 2012 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.HashMap; 019import java.util.Map; 020import java.util.Set; 021 022import org.apache.avalon.framework.configuration.Configuration; 023import org.apache.avalon.framework.configuration.ConfigurationException; 024import org.apache.avalon.framework.configuration.DefaultConfiguration; 025import org.apache.avalon.framework.service.ServiceException; 026import org.apache.avalon.framework.service.ServiceManager; 027import org.apache.commons.lang.StringUtils; 028 029import org.ametys.cms.contenttype.ContentType; 030import org.ametys.cms.contenttype.ContentTypeExtensionPoint; 031import org.ametys.cms.contenttype.ContentTypesHelper; 032import org.ametys.cms.repository.Content; 033import org.ametys.core.observation.Event; 034import org.ametys.core.observation.ObservationManager; 035import org.ametys.core.ui.Callable; 036import org.ametys.core.ui.SimpleMenu; 037import org.ametys.core.ui.StaticClientSideElement; 038import org.ametys.core.util.I18nUtils; 039import org.ametys.plugins.repository.AmetysObject; 040import org.ametys.plugins.repository.AmetysObjectResolver; 041import org.ametys.runtime.model.View; 042import org.ametys.web.ObservationConstants; 043import org.ametys.web.repository.page.ContentTypesAssignmentHandler; 044import org.ametys.web.repository.page.ModifiableZoneItem; 045import org.ametys.web.repository.page.ZoneItem.ZoneType; 046 047/** 048 * Menu giving the possibility to change the view rendering the content in a given ZoneItem. 049 */ 050public class SetContentViewMenu extends SimpleMenu 051{ 052 /** The content type extension point. */ 053 protected ContentTypeExtensionPoint _contentTypeExtensionPoint; 054 055 /** The content types assignment handler */ 056 protected ContentTypesAssignmentHandler _cTypeHandler; 057 058 /** The content types helper */ 059 protected ContentTypesHelper _contentTypesHelper; 060 061 /** Repository content */ 062 protected AmetysObjectResolver _resolver; 063 064 /** The observation manager */ 065 protected ObservationManager _observationManager; 066 067 /** The i18n utils */ 068 protected I18nUtils _i18nUtils; 069 070 private boolean _galleryInitialized; 071 072 @Override 073 public void service(ServiceManager serviceManager) throws ServiceException 074 { 075 super.service(serviceManager); 076 _contentTypeExtensionPoint = (ContentTypeExtensionPoint) serviceManager.lookup(ContentTypeExtensionPoint.ROLE); 077 _cTypeHandler = (ContentTypesAssignmentHandler) serviceManager.lookup(ContentTypesAssignmentHandler.ROLE); 078 _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE); 079 _i18nUtils = (I18nUtils) serviceManager.lookup(I18nUtils.ROLE); 080 _contentTypesHelper = (ContentTypesHelper) serviceManager.lookup(ContentTypesHelper.ROLE); 081 _observationManager = (ObservationManager) serviceManager.lookup(ObservationManager.ROLE); 082 } 083 084 @Override 085 protected void _getGalleryItems(Map<String, Object> parameters, Map<String, Object> contextualParameters) 086 { 087 try 088 { 089 _lazyInitializeContentViewGallery(); 090 } 091 catch (Exception e) 092 { 093 throw new IllegalStateException("Unable to lookup client side element local components", e); 094 } 095 096 super._getGalleryItems(parameters, contextualParameters); 097 } 098 099 private synchronized void _lazyInitializeContentViewGallery() throws ConfigurationException 100 { 101 if (!_galleryInitialized) 102 { 103 Set<String> contentTypesIds = _contentTypeExtensionPoint.getExtensionsIds(); 104 105 if (contentTypesIds.size() > 0) 106 { 107 GalleryItem galleryItem = new GalleryItem(); 108 109 for (String contentTypeId : contentTypesIds) 110 { 111 ContentType contentType = _contentTypeExtensionPoint.getExtension(contentTypeId); 112 113 GalleryGroup galleryGroup = new GalleryGroup(contentType.getLabel()); 114 galleryItem.addGroup(galleryGroup); 115 116 for (String viewName : contentType.getViewNames(false)) 117 { 118 View view = contentType.getView(viewName); 119 120 String id = this.getId() + "." + contentTypeId + "." + viewName; 121 122 Configuration conf = _getViewItemConfiguration(id, view, contentTypeId); 123 _getGalleryItemManager().addComponent(_pluginName, null, id, StaticClientSideElement.class, conf); 124 galleryGroup.addItem(new UnresolvedItem(id, true)); 125 } 126 } 127 128 _galleryItems.add(galleryItem); 129 } 130 131 if (_galleryItems.size() > 0) 132 { 133 try 134 { 135 _getGalleryItemManager().initialize(); 136 } 137 catch (Exception e) 138 { 139 throw new ConfigurationException("Unable to lookup parameter local components", e); 140 } 141 } 142 } 143 144 _galleryInitialized = true; 145 } 146 147 /** 148 * Get the configuration for a view item 149 * @param itemId The item id 150 * @param view The view 151 * @param cTypeId The content type id 152 * @return The configuration 153 */ 154 protected Configuration _getViewItemConfiguration (String itemId, View view, String cTypeId) 155 { 156 DefaultConfiguration conf = new DefaultConfiguration("extension"); 157 conf.setAttribute("id", itemId); 158 159 DefaultConfiguration classConf = new DefaultConfiguration("class"); 160 classConf.setAttribute("name", "Ametys.ribbon.element.ui.ButtonController"); 161 162 // Label 163 DefaultConfiguration labelConf = new DefaultConfiguration("label"); 164 labelConf.setValue(_i18nUtils.translate(view.getLabel())); 165 classConf.addChild(labelConf); 166 167 // Description 168 DefaultConfiguration descConf = new DefaultConfiguration("description"); 169 descConf.setValue(_i18nUtils.translate(view.getDescription())); 170 classConf.addChild(descConf); 171 172 // Name 173 DefaultConfiguration nameConf = new DefaultConfiguration("name"); 174 nameConf.setValue(view.getName()); 175 classConf.addChild(nameConf); 176 177 // Content type 178 DefaultConfiguration cTypeConf = new DefaultConfiguration("contentType"); 179 cTypeConf.setValue(cTypeId); 180 classConf.addChild(cTypeConf); 181 182 // Icons or glyph 183 if (view.getIconGlyph() != null) 184 { 185 DefaultConfiguration iconGlyphConf = new DefaultConfiguration("icon-glyph"); 186 iconGlyphConf.setValue(view.getIconGlyph()); 187 classConf.addChild(iconGlyphConf); 188 } 189 if (view.getIconDecorator() != null) 190 { 191 DefaultConfiguration iconDecoratorConf = new DefaultConfiguration("icon-decorator"); 192 iconDecoratorConf.setValue(view.getIconDecorator()); 193 classConf.addChild(iconDecoratorConf); 194 } 195 if (view.getSmallIcon() != null) 196 { 197 DefaultConfiguration iconSmallConf = new DefaultConfiguration("icon-small"); 198 iconSmallConf.setValue(view.getSmallIcon()); 199 classConf.addChild(iconSmallConf); 200 DefaultConfiguration iconMediumConf = new DefaultConfiguration("icon-medium"); 201 iconMediumConf.setValue(view.getMediumIcon()); 202 classConf.addChild(iconMediumConf); 203 DefaultConfiguration iconLargeConf = new DefaultConfiguration("icon-large"); 204 iconLargeConf.setValue(view.getLargeIcon()); 205 classConf.addChild(iconLargeConf); 206 } 207 208 // Common configuration 209 @SuppressWarnings("unchecked") 210 Map<String, Object> commonConfig = (Map<String, Object>) this._script.getParameters().get("items-config"); 211 for (String tagName : commonConfig.keySet()) 212 { 213 DefaultConfiguration c = new DefaultConfiguration(tagName); 214 c.setValue(String.valueOf(commonConfig.get(tagName))); 215 classConf.addChild(c); 216 } 217 218 conf.addChild(classConf); 219 return conf; 220 } 221 222 /** 223 * Set the view of a content 224 * @param zoneItemId the id of the zone item 225 * @param viewName the name of the view to use 226 */ 227 @Callable 228 public void setContentView(String zoneItemId, String viewName) 229 { 230 AmetysObject object = _resolver.resolveById(zoneItemId); 231 if (!(object instanceof ModifiableZoneItem)) 232 { 233 throw new IllegalArgumentException("The provided ID '" + zoneItemId + "' does not reference a modifiable zone item."); 234 } 235 236 ModifiableZoneItem zoneItem = (ModifiableZoneItem) object; 237 238 if (!zoneItem.getType().equals(ZoneType.CONTENT)) 239 { 240 throw new IllegalArgumentException("The zone item '" + zoneItemId + "' does not contain a content."); 241 } 242 243 Content content = zoneItem.getContent(); 244 245 View view = _contentTypesHelper.getView(viewName, content.getTypes(), content.getMixinTypes()); 246 if (view == null) 247 { 248 throw new IllegalArgumentException("The view '" + viewName + "' can't be assigned on the content '" + StringUtils.join(content.getTypes(), ",") + "'."); 249 } 250 251 if (getLogger().isDebugEnabled()) 252 { 253 getLogger().debug("Setting view '" + viewName + "' in the content zone item '" + zoneItemId + "'."); 254 } 255 256 // Set the view name. 257 zoneItem.setViewName(viewName); 258 259 zoneItem.saveChanges(); 260 261 Map<String, Object> eventParams = new HashMap<>(); 262 eventParams.put(ObservationConstants.ARGS_PAGE, zoneItem.getZone().getPage()); 263 eventParams.put(ObservationConstants.ARGS_ZONE_ITEM_ID, zoneItemId); 264 eventParams.put(ObservationConstants.ARGS_ZONE_TYPE, ZoneType.CONTENT); 265 _observationManager.notify(new Event(ObservationConstants.EVENT_ZONEITEM_MOVED, _currentUserProvider.getUser(), eventParams)); 266 } 267}