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.frontedition; 017 018import java.util.ArrayList; 019import java.util.Arrays; 020import java.util.Collections; 021import java.util.HashMap; 022import java.util.LinkedHashMap; 023import java.util.List; 024import java.util.Map; 025import java.util.Set; 026 027import javax.jcr.RepositoryException; 028 029import org.apache.avalon.framework.service.ServiceException; 030import org.apache.avalon.framework.service.ServiceManager; 031import org.apache.avalon.framework.service.Serviceable; 032import org.apache.commons.lang3.ArrayUtils; 033import org.apache.commons.lang3.StringUtils; 034 035import org.ametys.cms.repository.Content; 036import org.ametys.cms.repository.WorkflowAwareContent; 037import org.ametys.cms.workflow.ContentWorkflowHelper; 038import org.ametys.core.right.RightManager; 039import org.ametys.core.right.RightManager.RightResult; 040import org.ametys.core.ui.ClientSideElement; 041import org.ametys.core.ui.ClientSideElement.Script; 042import org.ametys.core.ui.ClientSideElement.ScriptFile; 043import org.ametys.core.ui.widgets.richtext.RichTextConfiguration; 044import org.ametys.core.ui.widgets.richtext.RichTextConfigurationExtensionPoint; 045import org.ametys.core.util.JSONUtils; 046import org.ametys.plugins.core.ui.minimize.HashCache; 047import org.ametys.plugins.repository.AmetysObject; 048import org.ametys.plugins.repository.AmetysObjectResolver; 049import org.ametys.plugins.repository.AmetysRepositoryException; 050import org.ametys.plugins.repository.UnknownAmetysObjectException; 051import org.ametys.plugins.repository.jcr.DefaultTraversableAmetysObject; 052import org.ametys.plugins.repository.jcr.JCRAmetysObject; 053import org.ametys.plugins.repository.version.VersionableAmetysObject; 054import org.ametys.plugins.workflow.support.WorkflowHelper; 055import org.ametys.web.WebConstants; 056import org.ametys.web.cache.PageHelper; 057import org.ametys.web.renderingcontext.RenderingContext; 058import org.ametys.web.repository.page.ModifiablePage; 059import org.ametys.web.repository.page.ModifiableZone; 060import org.ametys.web.repository.page.Page; 061import org.ametys.web.repository.page.ZoneItem; 062import org.ametys.web.repository.site.Site; 063import org.ametys.web.repository.site.SiteManager; 064import org.ametys.web.repository.sitemap.Sitemap; 065import org.ametys.web.transformation.xslt.AmetysXSLTHelper; 066 067/** 068 * Helper for preparing the Ametys Edition 069 */ 070public class AmetysFrontEditionHelper implements Serviceable 071{ 072 /** The right's id from front-edition access */ 073 public static final String FRONT_EDITION_RIGHT_ID = "Front_Edition_Access_Right"; 074 075 private static AmetysObjectResolver _ametysObjectResolver; 076 private static HashCache _hashCache; 077 private static RichTextConfigurationExtensionPoint _richTextConfigurationExtensionPoint; 078 private static RightManager _rightManager; 079 private static ContentWorkflowHelper _contentWorkflowHelper; 080 private static PageHelper _pageHelper; 081 private static WorkflowHelper _workflowHelper; 082 private static JSONUtils _jsonUtils; 083 private static SiteManager _siteManager; 084 085 public void service(ServiceManager manager) throws ServiceException 086 { 087 _ametysObjectResolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 088 _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE); 089 _hashCache = (HashCache) manager.lookup(HashCache.ROLE); 090 _richTextConfigurationExtensionPoint = (RichTextConfigurationExtensionPoint) manager.lookup(RichTextConfigurationExtensionPoint.ROLE); 091 _rightManager = (RightManager) manager.lookup(RightManager.ROLE); 092 _contentWorkflowHelper = (ContentWorkflowHelper) manager.lookup(ContentWorkflowHelper.ROLE); 093 _pageHelper = (PageHelper) manager.lookup(PageHelper.ROLE); 094 _workflowHelper = (WorkflowHelper) manager.lookup(WorkflowHelper.ROLE); 095 _jsonUtils = (JSONUtils) manager.lookup(JSONUtils.ROLE); 096 } 097 098 /** 099 * Prepare a hashcode for js files 100 * @param locale The language code to use 101 * @param rtlMode Is for right-to-left language? 102 * @param theme The url for the theme 103 * @return The new hashcode to read the minimified concatened file 104 */ 105 public static String prepareJSFiles(String locale, boolean rtlMode, String theme) 106 { 107 String themeName = StringUtils.substringAfterLast(theme, "/"); 108 109 Map<String, String> filesInfos = new HashMap<>(); 110 filesInfos.put("media", ""); 111 filesInfos.put("tag", "script"); 112 113 Map<String, Map<String, String>> files = new LinkedHashMap<>(); 114 files.put("/plugins/extjs6/resources/ext-all.js", filesInfos); 115 files.put("/plugins/extjs6/resources/classic/locale/locale-" + locale + ".js", filesInfos); 116 files.put(theme + "/" + themeName + ".js", filesInfos); 117 118 files.put("/plugins/core-ui/resources/js/Ext.fixes.js", filesInfos); 119 files.put("/plugins/core-ui/resources/js/Ext.enhancements.js", filesInfos); 120 121 files.put("/plugins/core-ui/resources/js/Ametys.js", filesInfos); 122 files.put("/plugins/front-edition/resources/js/Ametys/override/Ametys.js", filesInfos); 123 files.put("/plugins/core-ui/resources/js/Ametys/mask/GlobalLoadMask.js", filesInfos); 124 125 files.put("/plugins/core-ui/resources/js/Ametys/log/Logger.js", filesInfos); 126 files.put("/plugins/core-ui/resources/js/Ametys/log/Logger/Entry.js", filesInfos); 127 files.put("/plugins/core-ui/resources/js/Ametys/log/LoggerFactory.js", filesInfos); 128 files.put("/plugins/core-ui/resources/js/Ametys/log/ErrorDialog.js", filesInfos); 129 130 files.put("/plugins/core-ui/resources/js/Ametys/window/DialogBox.js", filesInfos); 131 files.put("/plugins/core-ui/resources/js/Ametys/window/MessageBox.js", filesInfos); 132 133 files.put("/plugins/core-ui/resources/js/Ametys/form/AbstractField.js", filesInfos); 134 files.put("/plugins/core-ui/resources/js/Ametys/form/AbstractFieldsWrapper.js", filesInfos); 135 files.put("/plugins/core-ui/resources/js/Ametys/form/AbstractQueryableComboBox.js", filesInfos); 136 files.put("/plugins/core-ui/resources/js/Ametys/form/field/DateTime.js", filesInfos); 137 files.put("/plugins/core-ui/resources/js/Ametys/form/field/StringTime.js", filesInfos); 138 files.put("/plugins/core-ui/resources/js/Ametys/form/field/Password.js", filesInfos); 139 files.put("/plugins/core-ui/resources/js/Ametys/form/field/ChangePassword.js", filesInfos); 140 files.put("/plugins/core-ui/resources/js/Ametys/form/field/ReferencedNumberField.js", filesInfos); 141 files.put("/plugins/core-ui/resources/js/Ametys/form/field/RichText.js", filesInfos); 142 files.put("/plugins/core-ui/resources/js/Ametys/form/field/RichText/SplitterTracker.js", filesInfos); 143 files.put("/plugins/core-ui/resources/js/Ametys/form/field/TextArea.js", filesInfos); 144 files.put("/plugins/core-ui/resources/js/Ametys/form/field/ColorSelector.js", filesInfos); 145 files.put("/plugins/core-ui/resources/js/Ametys/form/field/SelectUserDirectory.js", filesInfos); 146 files.put("/plugins/core-ui/resources/js/Ametys/form/field/SelectGroupDirectories.js", filesInfos); 147 files.put("/plugins/core-ui/resources/js/Ametys/form/field/Code.js", filesInfos); 148 files.put("/plugins/tiny_mce/resources/js/tinymce.js", filesInfos); 149 files.put("/plugins/codemirror/resources/js/codemirror.js", filesInfos); 150 files.put("/plugins/codemirror/resources/js/addon/edit/matchbrackets.js", filesInfos); 151 files.put("/plugins/codemirror/resources/js/addon/selection/active-line.js", filesInfos); 152 files.put("/plugins/codemirror/resources/js/mode/xml/xml.js", filesInfos); 153 files.put("/plugins/codemirror/resources/js/mode/javascript/javascript.js", filesInfos); 154 files.put("/plugins/codemirror/resources/js/mode/css/css.js", filesInfos); 155 files.put("/plugins/codemirror/resources/js/mode/htmlmixed/htmlmixed.js", filesInfos); 156 157 files.put("/plugins/core-ui/resources/js/Ametys/data/ServerCaller.js", filesInfos); 158 files.put("/plugins/core-ui/resources/js/Ametys/data/ServerComm.js", filesInfos); 159 files.put("/plugins/front-edition/resources/js/Ametys/override/Ametys/data/ServerComm.js", filesInfos); 160 files.put("/plugins/core-ui/resources/js/Ametys/data/ServerCommProxy.js", filesInfos); 161 files.put("/plugins/core-ui/resources/js/Ametys/data/ServerComm/TimeoutDialog.js", filesInfos); 162 163 files.put("/plugins/core-ui/resources/js/Ametys/form/widget/RichText/RichTextConfiguration.js", filesInfos); 164 165 files.put("/plugins/core-ui/resources/js/Ametys/plugins/coreui/system/devmode/StacktraceHelper.js", filesInfos); 166 167 files.put("/plugins/front-edition/resources/js/front-comm.js", filesInfos); 168 files.put("/plugins/front-edition/resources/js/front-widget.js", filesInfos); 169// files.put("/plugins/front-edition/resources/js/front-page.js", filesInfos); 170 files.put("/plugins/core-ui/resources/js/Ametys/helper/EnterURL.js", filesInfos); 171 files.put("/plugins/core-ui/resources/js/Ametys/helper/FileUpload.js", filesInfos); 172 files.put("/plugins/web/resources/js/Ametys/web/helper/ChoosePage.js", filesInfos); 173 files.put("/plugins/web/resources/js/Ametys/web/helper/ContextToolbar.js", filesInfos); 174 files.put("/plugins/web/resources/js/Ametys/web/sitemap/SitemapTree.js", filesInfos); 175 files.put("/plugins/web/resources/js/Ametys/web/sitemap/SitemapTree/Page.js", filesInfos); 176 files.put("/plugins/web/resources/js/Ametys/web/sitemap/SitemapTree/Sitemap.js", filesInfos); 177 files.put("/plugins/web/resources/js/Ametys/web/site/SitesTree/Site.js", filesInfos); 178 files.put("/plugins/cms/resources/js/Ametys/cms/editor/LinkHandler.js", filesInfos); 179 files.put("/plugins/cms/resources/js/Ametys/plugins/cms/editor/Links.js", filesInfos); 180 files.put("/plugins/cms/resources/js/Ametys/plugins/cms/editor/Links/LinkHandler.js", filesInfos); 181 files.put("/plugins/web/resources/js/Ametys/plugins/web/editor/Links.js", filesInfos); 182 files.put("/plugins/web/resources/js/Ametys/plugins/web/editor/PageLinkHandler.js", filesInfos); 183 files.put("/plugins/cms/resources/js/Ametys/plugins/cms/editor/Images.js", filesInfos); 184 185 files.put("/plugins/front-edition/resources/js/tinymce/lists.js", filesInfos); 186 files.put("/plugins/front-edition/resources/js/tinymce/links.js", filesInfos); 187 files.put("/plugins/front-edition/resources/js/tinymce/styles.js", filesInfos); 188 files.put("/plugins/front-edition/resources/js/tinymce/images.js", filesInfos); 189 files.put("/plugins/front-edition/resources/js/tinymce/save.js", filesInfos); 190 files.put("/plugins/front-edition/resources/js/tinymce/stickyToolbar.js", filesInfos); 191 192 //TinyMCE Tables 193 files.put("/plugins/front-edition/resources/js/tinymce/tables.js", filesInfos); 194 files.put("/plugins/cms/resources/js/Ametys/plugins/cms/editor/Tables.js", filesInfos); 195 files.put("/plugins/cms/resources/js/Ametys/plugins/cms/editor/BasicActions.js", filesInfos); 196 //TinyMCE Images 197 files.put("/plugins/cms/resources/js/Ametys/cms/uihelper/ChooseResource.js", filesInfos); 198 files.put("/plugins/explorer/resources/js/Ametys/explorer/tree/ExplorerTree.js", filesInfos); 199 files.put("/plugins/explorer/resources/js/Ametys/explorer/tree/ExplorerTree/NodeEntry.js", filesInfos); 200 files.put("/plugins/explorer/resources/js/Ametys/explorer/Resource.js", filesInfos); 201 files.put("/plugins/explorer/resources/js/Ametys/explorer/ExplorerNodeDAO.js", filesInfos); 202 files.put("/plugins/explorer/resources/js/Ametys/explorer/applications/ExplorerApplicationProvider.js", filesInfos); 203 files.put("/plugins/cms/resources/js/Ametys/cms/attach/AttachmentsExplorerTree.js", filesInfos); 204 files.put("/plugins/cms/resources/js/Ametys/cms/uihelper/ChooseAttachmentFile.js", filesInfos); 205 files.put("/plugins/front-edition/resources/js/Ametys/override/Ametys/cms/uihelper/ChooseAttachmentFile.js", filesInfos); 206 files.put("/plugins/explorer/resources/js/Ametys/explorer/resources/actions/FileActions.js", filesInfos); 207 files.put("/plugins/explorer/resources/js/Ametys/explorer/resources/helper/ResourceUpload.js", filesInfos); 208 files.put("/plugins/core-ui/resources/js/Ametys/file/AbstractFileExplorerTree/FileNode.js", filesInfos); 209 files.put("/plugins/core-ui/resources/js/Ametys/file/AbstractFileExplorerTree.js", filesInfos); 210 211 //Empty Message class 212 files.put("/plugins/core-ui/resources/js/Ametys/message/Message.js", filesInfos); 213 files.put("/plugins/core-ui/resources/js/Ametys/message/MessageTarget.js", filesInfos); 214 files.put("/plugins/core-ui/resources/js/Ametys/message/MessageTargetFactory.js", filesInfos); 215 files.put("/plugins/core-ui/resources/js/Ametys/message/factory/DefaultMessageTargetFactory.js", filesInfos); 216 files.put("/plugins/front-edition/resources/js/Ametys/message/MessageTargetHelper.js", filesInfos); 217 //add page 218 files.put("/plugins/web/resources/js/Ametys/plugins/web/page/AddPageWizard.js", filesInfos); 219 files.put("/plugins/front-edition/resources/js/Ametys/override/Ametys/plugins/web/page/AddPageWizard.js", filesInfos); 220 files.put("/plugins/web/resources/js/Ametys/web/sitemap/SitemapDAO.js", filesInfos); 221 files.put("/plugins/web/resources/js/Ametys/web/sitemap/Sitemap.js", filesInfos); 222 files.put("/plugins/web/resources/js/Ametys/web/page/PageDAO.js", filesInfos); 223 files.put("/plugins/front-edition/resources/js/Ametys/override/Ametys/web/page/PageDAO.js", filesInfos); 224 files.put("/plugins/web/resources/js/Ametys/plugins/web/page/AddPageWizard/Card.js", filesInfos); 225 files.put("/plugins/web/resources/js/Ametys/plugins/web/page/AddPageWizard/CreatePageCard.js", filesInfos); 226 files.put("/plugins/web/resources/js/Ametys/plugins/web/page/AddPageWizard/PageContentCard.js", filesInfos); 227 files.put("/plugins/front-edition/resources/js/Ametys/override/Ametys/plugins/web/page/AddPageWizard/PageContentCard.js", filesInfos); 228 files.put("/plugins/cms/resources/js/Ametys/cms/content/ContentDAO.js", filesInfos); 229 files.put("/plugins/web/resources/js/Ametys/web/content/ContentDAO.js", filesInfos); 230 files.put("/plugins/front-edition/resources/js/Ametys/override/Ametys/cms/content/ContentDAO.js", filesInfos); 231 files.put("/plugins/cms/resources/js/Ametys/cms/content/Content.js", filesInfos); 232 files.put("/plugins/core-ui/resources/js/Ametys/navhistory/HistoryDAO.js", filesInfos); 233 files.put("/plugins/core-ui/resources/js/Ametys/window/MessageBox.js", filesInfos); 234 files.put("/plugins/front-edition/resources/js/Ametys/tool/ToolsManager.js", filesInfos); 235 236 files.put("/plugins/web/resources/js/Ametys/plugins/web/page/AddPageWizard/PageTypeCard.js", filesInfos); 237 files.put("/plugins/front-edition/resources/js/Ametys/override/Ametys/plugins/web/page/AddPageWizard/PageTypeCard.js", filesInfos); 238 files.put("/plugins/web/resources/js/Ametys/web/form/widget/SelectPage.js", filesInfos); 239 files.put("/plugins/front-edition/resources/js/Ametys/override/Ametys/web/form/widget/SelectPage.js", filesInfos); 240 files.put("/plugins/web/resources/js/Ametys/web/form/widget/SelectSite.js", filesInfos); 241 files.put("/plugins/web/resources/js/Ametys/web/helper/ChooseSite.js", filesInfos); 242 files.put("/plugins/web/resources/js/Ametys/web/site/SitesTree.js", filesInfos); 243 files.put("/plugins/web/resources/js/Ametys/web/site/SitesTree/Site.js", filesInfos); 244 files.put("/plugins/web/resources/js/Ametys/web/helper/ContextToolbar.js", filesInfos); 245 files.put("/plugins/web/resources/js/Ametys/web/site/SitesTree/Site.js", filesInfos); 246 files.put("/plugins/web/resources/js/Ametys/web/form/widget/SelectPage/PageEntry.js", filesInfos); 247 files.put("/plugins/web/resources/js/Ametys/plugins/web/page/AddPageWizard/TagsCard.js", filesInfos); 248 files.put("/plugins/web/resources/js/Ametys/plugins/web/page/AddPageWizard/TagsCardLite.js", filesInfos); 249 files.put("/plugins/web/resources/js/Ametys/web/page/Page.js", filesInfos); 250 files.put("/plugins/cms/resources/js/Ametys/plugins/cms/tag/TagsTreePanel.js", filesInfos); 251 files.put("/plugins/cms/resources/js/Ametys/plugins/cms/tag/TagsTreePanel/TagNode.js", filesInfos); 252 253 //delete page 254 files.put("/plugins/web/resources/js/Ametys/plugins/web/sitemap/SitemapActions.js", filesInfos); 255 256 //page tags 257 files.put("/plugins/web/resources/js/Ametys/plugins/web/tag/AffectTagAction.js", filesInfos); 258 files.put("/plugins/cms/resources/js/Ametys/cms/uihelper/ChooseTagHelper.js", filesInfos); 259 files.put("/plugins/cms/resources/js/Ametys/cms/uihelper/ChooseTag.js", filesInfos); 260 files.put("/plugins/web/resources/js/Ametys/web/helper/ChooseTag.js", filesInfos); 261 files.put("/plugins/cms/resources/js/Ametys/plugins/cms/tag/TagActions.js", filesInfos); 262 files.put("/plugins/web/resources/js/Ametys/plugins/web/tag/TagsTreePanel.js", filesInfos); 263 264 // ping 265 files.put("/plugins/core-ui/resources/js/Ametys/plugins/coreui/system/StartTimeChecker.js", filesInfos); 266 267 // actions on content 268 files.put("/plugins/web/resources/js/Ametys/plugins/web/zone/ZoneActions.js", filesInfos); 269 files.put("/plugins/web/resources/js/Ametys/plugins/web/zone/ZoneDAO.js", filesInfos); 270 271 // file widget (+cropping for image filter) 272 files.put("/plugins/core-ui/resources/js/Ametys/form/widget/File.js", filesInfos); 273 files.put("/plugins/core-ui/resources/js/Ametys/form/widget/File/FileSource.js", filesInfos); 274 files.put("/plugins/core-ui/resources/js/Ametys/form/widget/File/External.js", filesInfos); 275 files.put("/plugins/cms/resources/js/Ametys/cms/form/widget/File/Resource.js", filesInfos); 276 files.put("/plugins/core-ui/resources/js/Ametys/helper/crop/CropDialog.js", filesInfos); 277 files.put("/plugins/core-ui/resources/js/Jcrop/jquery.Jcrop.js", filesInfos); 278 279 // Let's add all richtextconfiguration files 280 _addRichTextConfigurationFiles(files, filesInfos, locale, rtlMode, true); 281 282 return _hashCache.createHash(files, locale); 283 } 284 285 /** 286 * Prepare a hashcode for css files 287 * @param locale The language code to use 288 * @param rtlMode Is for right-to-left language? 289 * @param theme The url for the theme 290 * @return The new hashcode to read the minimified concatened file 291 */ 292 public static String prepareCSSFiles(String locale, boolean rtlMode, String theme) 293 { 294 Map<String, String> filesInfos = new HashMap<>(); 295 filesInfos.put("media", ""); 296 filesInfos.put("tag", "link"); 297 298 Map<String, Map<String, String>> files = new LinkedHashMap<>(); 299 String themeName = StringUtils.substringAfterLast(theme, "/"); 300 files.put(theme + "/resources/" + themeName + "-all.css", filesInfos); 301 files.put("/plugins/front-edition/resources/css/theme-ametys-base-light.css", filesInfos); 302 files.put("/plugins/core-ui/resources/font/ametys/AmetysIcon.css", filesInfos); 303 files.put("/plugins/core-ui/resources/css/Jcrop/jquery.Jcrop.css", filesInfos); 304 305 // Let's add all richtextconfiguration files 306 _addRichTextConfigurationFiles(files, filesInfos, locale, rtlMode, false); 307 308 return _hashCache.createHash(files, locale); 309 } 310 311 private static List<ScriptFile> _getRichTextConfigurationFiles(boolean scripts, Map<String, Object> contextParameters) 312 { 313 List<ScriptFile> files = new ArrayList<>(); 314 315 for (String richTextConfigurationId : _richTextConfigurationExtensionPoint.getExtensionsIds()) 316 { 317 RichTextConfiguration richTextConfiguration = _richTextConfigurationExtensionPoint.getExtension(richTextConfigurationId); 318 for (String category : richTextConfiguration.getCategories()) 319 { 320 Set<ClientSideElement> convertors = richTextConfiguration.getConvertors(category, contextParameters); 321 if (convertors != null) 322 { 323 for (ClientSideElement convertor : convertors) 324 { 325 List<Script> scriptsToAdd = convertor.getScripts(Collections.EMPTY_MAP); 326 if (scriptsToAdd != null) 327 { 328 for (Script script : scriptsToAdd) 329 { 330 List<ScriptFile> scriptFiles = scripts ? script.getScriptFiles() : script.getCSSFiles(); 331 if (scriptFiles != null) 332 { 333 files.addAll(scriptFiles); 334 } 335 } 336 } 337 } 338 } 339 340 Set<ClientSideElement> validators = richTextConfiguration.getValidators(category, contextParameters); 341 if (validators != null) 342 { 343 for (ClientSideElement validator : validators) 344 { 345 List<Script> scriptsToAdd = validator.getScripts(Collections.EMPTY_MAP); 346 if (scriptsToAdd != null) 347 { 348 for (Script script : scriptsToAdd) 349 { 350 List<ScriptFile> scriptFiles = scripts ? script.getScriptFiles() : script.getCSSFiles(); 351 if (scriptFiles != null) 352 { 353 files.addAll(scriptFiles); 354 } 355 } 356 } 357 } 358 } 359 } 360 } 361 362 return files; 363 } 364 365 private static void _addRichTextConfigurationFiles(Map<String, Map<String, String>> files, Map<String, String> filesInfos, String locale, boolean rtlMode, boolean scripts) 366 { 367 Map<String, Object> contextParameters = new HashMap<>(); 368 contextParameters.put("siteName", AmetysXSLTHelper.site()); 369 370 List<ScriptFile> richTextConfigurationFiles = _getRichTextConfigurationFiles(scripts, contextParameters); 371 for (ScriptFile file : richTextConfigurationFiles) 372 { 373 String uri = null; 374 if (file.isLangSpecific()) 375 { 376 if (file.getLangPaths().containsKey(locale)) 377 { 378 uri = file.getLangPaths().get(locale); 379 } 380 else if (file.getLangPaths().containsKey(file.getDefaultLang())) 381 { 382 uri = file.getLangPaths().get(file.getDefaultLang()); 383 } 384 } 385 else 386 { 387 if (file.getRtlMode() == null || "all".equals(file.getRtlMode()) || Boolean.toString(rtlMode).equals(file.getRtlMode())) 388 { 389 uri = file.getPath(); 390 } 391 } 392 393 if (uri != null) 394 { 395 files.put(uri, filesInfos); 396 } 397 } 398 } 399 /** 400 * Check if we can display the front edition button for a specific right 401 * Checks : 402 * * Rendering context == front 403 * * Edition mode 404 * * Front_Edition_Access_Right 405 * * RightId available 406 * @param rightId right to check (can be null) 407 * @param inputPageId page to check 408 * @return true if all is OK, false if at least one is false 409 * @deprecated Use the version with three arguments 410 */ 411 @Deprecated 412 public static boolean hasFrontEditionRight(String rightId, String inputPageId) 413 { 414 return hasFrontEditionRight(rightId, inputPageId, true); 415 } 416 /** 417 * Check if we can display the front edition button for a specific right 418 * Checks : 419 * * Rendering context == front 420 * * Edition mode 421 * * Front_Edition_Access_Right 422 * * RightId available 423 * @param rightId right to check (can be null) 424 * @param objectId page/content to check 425 * @param editionModeOnly Check if the user is in edition mode 426 * @return true if all is OK, false if at least one is false 427 */ 428 public static boolean hasFrontEditionRight(String rightId, String objectId, boolean editionModeOnly) 429 { 430 String pageId = objectId; 431 if (StringUtils.isEmpty(pageId)) 432 { 433 pageId = AmetysXSLTHelper.pageId(); 434 } 435 436 if (StringUtils.isEmpty(pageId) // No page to check 437 || !RenderingContext.FRONT.toString().equals(AmetysXSLTHelper.renderingContext()) // We are no on front 438 || (editionModeOnly && !AmetysXSLTHelper.isEditionMode()) // Not in edition mode 439 || !hasFrontEditionRight()) // The user has the front edition right 440 { 441 442 return false; 443 } 444 445 if (StringUtils.contains(pageId, ";")) 446 { 447 String[] pageIds = StringUtils.split(pageId, ";"); 448 for (String pid : pageIds) 449 { 450 if (_rightManager.currentUserHasRight(rightId, _ametysObjectResolver.resolveById(pid)) == RightResult.RIGHT_ALLOW) // Check right on page (If this page does not exists an exception will be thrown... this is fine) 451 { 452 return true; 453 } 454 // else check the next one 455 } 456 return false; // No right inside the list 457 } 458 else 459 { 460 return StringUtils.isEmpty(rightId) // There is no right to check OR the user has the right 461 || _rightManager.currentUserHasRight(rightId, _ametysObjectResolver.resolveById(pageId)) == RightResult.RIGHT_ALLOW; // Check right on page (If this page does not exists an exception will be thrown... this is fine) 462 } 463 } 464 /** 465 * Check if the current user has the Front_Edition_Access_Right right 466 * @return true if right granted 467 */ 468 public static boolean hasFrontEditionRight() 469 { 470 String pageId = AmetysXSLTHelper.pageId(); 471 if (StringUtils.isNotEmpty(pageId)) 472 { 473 Page page = _ametysObjectResolver.resolveById(pageId); 474 return _rightManager.currentUserHasRight(FRONT_EDITION_RIGHT_ID, page) == RightResult.RIGHT_ALLOW; 475 } 476 477 String lang = AmetysXSLTHelper.lang(); 478 String siteName = AmetysXSLTHelper.site(); 479 480 if (StringUtils.isNotEmpty(siteName) && StringUtils.isNoneEmpty(lang)) 481 { 482 Site site = _siteManager.getSite(siteName); 483 Sitemap sitemap = site.getSitemap(lang); 484 return _rightManager.currentUserHasRight(FRONT_EDITION_RIGHT_ID, sitemap) == RightResult.RIGHT_ALLOW; 485 } 486 487 return false; 488 } 489 /** 490 * Check if the current workflow action is available on this content 491 * @param actionId action to check 492 * @param contentId content to check 493 * @param checkEditionMode check also if we are in edition mode 494 * @return true if right is granted 495 */ 496 public static boolean hasWorkflowRight(int actionId, String contentId, boolean checkEditionMode) 497 { 498 List<Integer> actionIds = new ArrayList<>(); 499 actionIds.add(actionId); 500 return hasWorkflowRight(actionIds, contentId, checkEditionMode); 501 } 502 /** 503 * Check if a list of workflow actions are available on this content 504 * @param actionIds list of action ids 505 * @param contentId id of the content to check 506 * @param checkEditionMode check also if we are in edition mode 507 * @return true if all actions are available 508 */ 509 public static boolean hasWorkflowRight(List<Integer> actionIds, String contentId, boolean checkEditionMode) 510 { 511 Content content = _ametysObjectResolver.resolveById(contentId); 512 return hasWorkflowRight(actionIds, content, checkEditionMode); 513 } 514 /** 515 * Check if a list of workflow actions are available on this content 516 * @param actionIds list of action ids 517 * @param content content to check 518 * @param checkEditionMode check also if we are in edition mode 519 * @return true if all actions are available 520 */ 521 public static boolean hasWorkflowRight(List<Integer> actionIds, Content content, boolean checkEditionMode) 522 { 523 if (checkEditionMode) 524 { 525 boolean editionModeOk = AmetysXSLTHelper.isEditionMode(); 526 if (!editionModeOk) 527 { 528 return false; 529 } 530 } 531 boolean result = false; 532 if (content instanceof WorkflowAwareContent) 533 { 534 WorkflowAwareContent wcontent = (WorkflowAwareContent) content; 535 int[] availableActions = _contentWorkflowHelper.getAvailableActions(wcontent); 536 for (int actionId : actionIds) 537 { 538 result = result || ArrayUtils.contains(availableActions, actionId); 539 if (result) 540 { 541 break; 542 } 543 } 544 } 545 return result; 546 } 547 /** 548 * Get a string representing a json map of the contentIds with true/false if they can/can't be modified 549 * @param actionId action to check 550 * @param inputPageId page (can be null) 551 * @param checkEditionMode check also if we are in edition mode 552 * @return {contentId : true/false, ....} 553 */ 554 public static String getContentModifiables(int actionId, String inputPageId, boolean checkEditionMode) 555 { 556 Map<String, Boolean> jsonObject = new HashMap<>(); 557 List<Integer> actionIds = new ArrayList<>(); 558 actionIds.add(actionId); 559 String pageId = inputPageId; 560 if (StringUtils.isEmpty(inputPageId)) 561 { 562 pageId = AmetysXSLTHelper.pageId(); 563 } 564 if (!StringUtils.isEmpty(pageId)) 565 { 566 AmetysObject resolveById = _ametysObjectResolver.resolveById(pageId); 567 if (resolveById instanceof Page) 568 { 569 Page page = (Page) resolveById; 570 List<Content> contents = _pageHelper.getAllContents(page); 571 for (Content content : contents) 572 { 573 jsonObject.put(content.getId(), hasWorkflowRight(actionIds, content, checkEditionMode)); 574 } 575 } 576 } 577 578 return _jsonUtils.convertObjectToJson(jsonObject); 579 } 580 /** 581 * Get the name of a workflow action 582 * @param workflowName workflow name 583 * @param actionId action id in the workflow 584 * @return name of the workflow action 585 */ 586 public static String getWorkflowName(String workflowName, int actionId) 587 { 588 String workflowNameKey = _workflowHelper.getActionName(workflowName, actionId); 589 String translatedName = org.ametys.core.util.AmetysXSLTHelper.translate(workflowNameKey); 590 return translatedName; 591 } 592 /** 593 * Get the status (validated/draft) of all contents in a page 594 * @param pageId id of the page to check 595 * @return "" if not a page, "draft" if all contents are drafts, "validated" if all contents are validated, and "mixed" if there are both 596 */ 597 public String getPageStatus(String pageId) 598 { 599 boolean hasDraft = false; 600 boolean hasValidated = false; 601 AmetysObject resolveById = _ametysObjectResolver.resolveById(pageId); 602 if (resolveById instanceof Page) 603 { 604 Page page = (Page) resolveById; 605 List<Content> contents = _pageHelper.getAllContents(page); 606 for (Content content : contents) 607 { 608 if (isContentLive(content)) 609 { 610 hasValidated = true; 611 } 612 else 613 { 614 hasDraft = true; 615 } 616 } 617 String result = "none"; 618 if (hasDraft && !hasValidated) 619 { 620 result = "draft"; 621 } 622 else if (!hasDraft && hasValidated) 623 { 624 result = "validated"; 625 } 626 else if (hasDraft && hasValidated) 627 { 628 result = "mixed"; 629 } 630 return result; 631 } 632 else 633 { 634 return ""; 635 } 636 } 637 638 /** 639 * Get the workflow step id of a content 640 * @param contentId id of the content 641 * @return the step Id 642 */ 643 public long getContentWorkflowId(String contentId) 644 { 645 AmetysObject resolvedById = _ametysObjectResolver.resolveById(contentId); 646 if (resolvedById instanceof Content) 647 { 648 Content content = (Content) resolvedById; 649 return getContentWorkflowId(content); 650 } 651 else 652 { 653 return 0; 654 } 655 } 656 /** 657 * Get the workflow step id of a content 658 * @param content content 659 * @return the step Id 660 */ 661 public long getContentWorkflowId(Content content) 662 { 663 WorkflowAwareContent wContent = (WorkflowAwareContent) content; 664 return wContent.getCurrentStepId(); 665 } 666 667 /** 668 * check if a content is published ot not 669 * @param contentId id of the content 670 * @return "validated" or "draft", "" if not found 671 */ 672 public String getContentStatus(String contentId) 673 { 674 AmetysObject resolvedById = _ametysObjectResolver.resolveById(contentId); 675 if (resolvedById instanceof Content) 676 { 677 Content content = (Content) resolvedById; 678 return getContentStatus(content); 679 } 680 else 681 { 682 return ""; 683 } 684 } 685 /** 686 * check if a content is published ot not 687 * @param content content 688 * @return "validated" or "draft" 689 */ 690 public String getContentStatus(Content content) 691 { 692 return isContentLive(content) ? "validated" : "draft"; 693 } 694 /** 695 * check if a content is published ot not 696 * @param contentId id of the content 697 * @return true if validated 698 */ 699 public boolean isContentLive(String contentId) 700 { 701 AmetysObject resolvedById = _ametysObjectResolver.resolveById(contentId); 702 if (resolvedById instanceof Content) 703 { 704 Content content = (Content) resolvedById; 705 return isContentLive(content); 706 } 707 else 708 { 709 return false; 710 } 711 } 712 /** 713 * check if a content is published ot not 714 * @param content content 715 * @return true if validated 716 */ 717 public boolean isContentLive(Content content) 718 { 719 return Arrays.asList(((VersionableAmetysObject) content).getLabels()).contains(WebConstants.LIVE_LABEL); 720 } 721 /** 722 * Get the position of this zoneItem in the zone, or -1 if not found 723 * @param zoneItemId zoneitem to search 724 * @param pageId page id 725 * @return zero based position, -1 if not found 726 * @throws UnknownAmetysObjectException If an error occurred 727 * @throws AmetysRepositoryException If an error occurred 728 * @throws RepositoryException If an error occurred 729 */ 730 public long getZoneItemPosition(String zoneItemId, String pageId) throws UnknownAmetysObjectException, AmetysRepositoryException, RepositoryException 731 { 732 ModifiablePage page = _ametysObjectResolver.resolveById(pageId); 733 ZoneItem zoneItem = page instanceof JCRAmetysObject ? (ZoneItem) _ametysObjectResolver.resolveById(zoneItemId, ((JCRAmetysObject) page).getNode().getSession()) : (ZoneItem) _ametysObjectResolver.resolveById(zoneItemId); 734 AmetysObject parent = zoneItem.getParent(); 735 if (parent instanceof DefaultTraversableAmetysObject) 736 { 737 return ((DefaultTraversableAmetysObject) parent).getChildPosition(zoneItem); 738 } 739 return -1; 740 } 741 /** 742 * Return the size of a zone 743 * @param zoneName zone name 744 * @param pageId page Id 745 * @return size of the zone (-1 if not found) 746 */ 747 public long getZoneSize(String zoneName, String pageId) 748 { 749 ModifiablePage page = _ametysObjectResolver.resolveById(pageId); 750 ModifiableZone zone = page.getZone(zoneName); 751 if (zone != null) 752 { 753 return zone.getZoneItems().getSize(); 754 } 755 return -1; 756 } 757}